summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsongyanchao <[email protected]>2023-12-28 06:15:25 +0000
committersongyanchao <[email protected]>2023-12-28 06:15:25 +0000
commitdda2a20a5fc0187f304994fd116711e40fec8493 (patch)
tree0175137766130396d3996c7b94e9bb187f00d11f
parentb269cd473f22c60203ed50804dc7a26638e6964f (diff)
🐞 fix(TSG-18237): Fix bug where ICMP packets fail to match Classifier rules.v4.6.68-20231228
Fix bug where ICMP packets fail to match Classifier rules.
-rw-r--r--infra/src/pkt_classifier_engine.c16
-rw-r--r--infra/test/TestPktClassifierEngine.cc360
2 files changed, 372 insertions, 4 deletions
diff --git a/infra/src/pkt_classifier_engine.c b/infra/src/pkt_classifier_engine.c
index e4f331c..4359b44 100644
--- a/infra/src/pkt_classifier_engine.c
+++ b/infra/src/pkt_classifier_engine.c
@@ -1213,11 +1213,17 @@ int match_field_data_prepare_for_tree(const char * mbuf_data, struct pkt_parser_
}
}
- if (unlikely(match_field_addr_set == 0) || unlikely(match_field_port_set == 0))
+ if (unlikely(match_field_addr_set == 0))
{
return RT_ERR;
}
+ if (unlikely(match_field_port_set == 0))
+ {
+ out_match_field->src_port = 0;
+ out_match_field->dst_port = 0;
+ }
+
return RT_SUCCESS;
}
@@ -1264,11 +1270,17 @@ int match_field_data_prepare_for_linear(const char * mbuf_data, struct pkt_parse
}
}
- if (unlikely(match_field_addr_set == 0) || unlikely(match_field_port_set == 0))
+ if (unlikely(match_field_addr_set == 0))
{
return RT_ERR;
}
+ if (unlikely(match_field_port_set == 0))
+ {
+ out_match_field->src_port = 0;
+ out_match_field->dst_port = 0;
+ }
+
return RT_SUCCESS;
}
diff --git a/infra/test/TestPktClassifierEngine.cc b/infra/test/TestPktClassifierEngine.cc
index d05f591..03b4fd3 100644
--- a/infra/test/TestPktClassifierEngine.cc
+++ b/infra/test/TestPktClassifierEngine.cc
@@ -79,7 +79,7 @@ void construct_pkt_for_ipv4(struct rte_mbuf * mbuf, char * src_addr, char * dst_
udp_hdr->dgram_len = rte_cpu_to_be_16(0x0014);
udp_hdr->dgram_cksum = rte_cpu_to_be_16(0x0000);
}
- else
+ else if (proto == IPPROTO_TCP)
{
struct rte_tcp_hdr * tcp_hdr = rte_pktmbuf_mtod_offset(
mbuf, struct rte_tcp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr));
@@ -90,6 +90,17 @@ void construct_pkt_for_ipv4(struct rte_mbuf * mbuf, char * src_addr, char * dst_
tcp_hdr->cksum = rte_cpu_to_be_16(0x0000);
tcp_hdr->tcp_urp = rte_cpu_to_be_16(0x0000);
}
+ else if (proto == IPPROTO_ICMP)
+ {
+ struct rte_icmp_hdr * icmp_hdr = rte_pktmbuf_mtod_offset(
+ mbuf, struct rte_icmp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr));
+
+ icmp_hdr->icmp_type = 0x08;
+ icmp_hdr->icmp_code = 0x00;
+ icmp_hdr->icmp_cksum = rte_cpu_to_be_16(0x0000);
+ icmp_hdr->icmp_ident = rte_cpu_to_be_16(0x0000);
+ icmp_hdr->icmp_seq_nb = rte_cpu_to_be_16(0x0000);
+ }
}
void construct_pkt_for_ipv6(struct rte_mbuf * mbuf, char * src_addr, char * dst_addr, uint8_t proto, uint16_t src_port,
@@ -121,7 +132,7 @@ void construct_pkt_for_ipv6(struct rte_mbuf * mbuf, char * src_addr, char * dst_
udp_hdr->dgram_len = rte_cpu_to_be_16(0x0014);
udp_hdr->dgram_cksum = rte_cpu_to_be_16(0x0000);
}
- else
+ else if (proto == IPPROTO_TCP)
{
struct rte_tcp_hdr * tcp_hdr = rte_pktmbuf_mtod_offset(
mbuf, struct rte_tcp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr));
@@ -132,6 +143,17 @@ void construct_pkt_for_ipv6(struct rte_mbuf * mbuf, char * src_addr, char * dst_
tcp_hdr->cksum = rte_cpu_to_be_16(0x0000);
tcp_hdr->tcp_urp = rte_cpu_to_be_16(0x0000);
}
+ else if (proto == IPPROTO_ICMP)
+ {
+ struct rte_icmp_hdr * icmp_hdr = rte_pktmbuf_mtod_offset(
+ mbuf, struct rte_icmp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr));
+
+ icmp_hdr->icmp_type = 0x08;
+ icmp_hdr->icmp_code = 0x00;
+ icmp_hdr->icmp_cksum = rte_cpu_to_be_16(0x0000);
+ icmp_hdr->icmp_ident = rte_cpu_to_be_16(0x0000);
+ icmp_hdr->icmp_seq_nb = rte_cpu_to_be_16(0x0000);
+ }
}
void rule_list_engine_generator_for_full_field_match(uint32_t nr_rules, struct rule_list_engine * rule_list_engine)
@@ -2146,6 +2168,340 @@ TEST_F(TestCasePktClassifierEngine, DuplicateRulesCheckTest)
EXPECT_EQ(ret, -1);
}
+TEST_F(TestCasePktClassifierEngine, IcmpTestForLinearSearch)
+{
+ /* Generator rule list */
+ struct rule_list_engine rule_list_engine = {0};
+ rule_list_engine.nr_rules = 4;
+
+ /* Full-field matching V4 */
+ struct rule_field_engine * rule = &rule_list_engine.rules[0];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 0;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 0;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 0;
+ rule->ether_type = RTE_ETHER_TYPE_IPV4;
+ rule->src_addr_mask_len = 32;
+ rule->dst_addr_mask_len = 32;
+ inet_pton(AF_INET, "172.17.1.1", &rule->src_addr_v4);
+ inet_pton(AF_INET, "172.17.1.2", &rule->dst_addr_v4);
+
+ /* Full-field matching V6*/
+ rule = &rule_list_engine.rules[1];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 0;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 1;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 1;
+ rule->ether_type = RTE_ETHER_TYPE_IPV6;
+ rule->src_addr_mask_len = 128;
+ rule->dst_addr_mask_len = 128;
+ inet_pton(AF_INET6, "2001:db8:0:1:1:1:1:1", &rule->src_addr_v6);
+ inet_pton(AF_INET6, "2001:db8:0:1:1:1:1:2", &rule->dst_addr_v6);
+
+ /* Fuzzy matching V4 */
+ rule = &rule_list_engine.rules[2];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 1;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 2;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 2;
+ rule->ether_type = RTE_ETHER_TYPE_IPV4;
+ rule->src_addr_mask_len = 0;
+ rule->dst_addr_mask_len = 0;
+
+ /* Fuzzy matching V6 */
+ rule = &rule_list_engine.rules[3];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 1;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 3;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 3;
+ rule->ether_type = RTE_ETHER_TYPE_IPV6;
+ rule->src_addr_mask_len = 0;
+ rule->dst_addr_mask_len = 0;
+
+ /* Build the engine */
+ char str_error_reason[MR_STRING_MAX];
+ int ret =
+ pkt_classifier_engine_build(engine_instance_, &rule_list_engine, str_error_reason, sizeof(str_error_reason));
+ if (ret != 0)
+ {
+ printf("error reason: %s\n", str_error_reason);
+ }
+ EXPECT_EQ(ret, 0);
+
+ /* Create the pkts */
+ int nr_pkts = 4;
+ struct rte_mbuf * pkts[nr_pkts];
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool_, pkts, RTE_DIM(pkts));
+ ASSERT_EQ(ret, 0);
+ char str_ip_src_addr[MR_SYMBOL_MAX] = {};
+ char str_ip_dst_addr[MR_SYMBOL_MAX] = {};
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "172.17.1.1");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "172.17.1.2");
+ construct_pkt_for_ipv4(pkts[0], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "2001:db8:0:1:1:1:1:1");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "2001:db8:0:1:1:1:1:2");
+ construct_pkt_for_ipv6(pkts[1], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "172.17.1.3");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "172.17.1.4");
+ construct_pkt_for_ipv4(pkts[2], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "2001:db8:0:1:1:1:1:3");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "2001:db8:0:1:1:1:1:4");
+ construct_pkt_for_ipv6(pkts[3], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ /* Parser pkts */
+ for (uint8_t pkt_idx = 0; pkt_idx < nr_pkts; pkt_idx++)
+ {
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkts[pkt_idx], MR_NODE_CTRLZONE_ID);
+ memset(mrb_meta, 0, sizeof(struct mrb_metadata));
+ struct pkt_parser pkt_parser;
+ pkt_parser_init(&pkt_parser, &mrb_meta->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX);
+ pkt_parser_exec(&pkt_parser, pkts[pkt_idx]);
+ }
+
+ /* Generate the domain field for all pkts */
+ uint16_t domain_field_for_pkts[nr_pkts];
+ for (int index = 0; index < nr_pkts; index++)
+ {
+ domain_field_for_pkts[index] = 0;
+ }
+
+ /* Match all pkts */
+ struct match_result_engine result[nr_pkts];
+ pkt_classifier_engine_multi_match(engine_instance_, 1, pkts, nr_pkts, domain_field_for_pkts, result);
+
+ /* Check the results */
+ EXPECT_EQ(result[0].nr_actions, 2);
+ EXPECT_EQ(result[0].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[0].actions[0].data, 0);
+ EXPECT_EQ(result[0].actions[1].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[0].actions[1].data, 2);
+
+ EXPECT_EQ(result[1].nr_actions, 2);
+ EXPECT_EQ(result[1].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[1].actions[0].data, 1);
+ EXPECT_EQ(result[1].actions[1].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[1].actions[1].data, 3);
+
+ EXPECT_EQ(result[2].nr_actions, 1);
+ EXPECT_EQ(result[2].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[2].actions[0].data, 2);
+
+ EXPECT_EQ(result[3].nr_actions, 1);
+ EXPECT_EQ(result[3].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[3].actions[0].data, 3);
+
+ /* Free the packet */
+ rte_pktmbuf_free_bulk(pkts, RTE_DIM(pkts));
+}
+
+TEST_F(TestCasePktClassifierEngine, IcmpTestForTreeSearch)
+{
+ /* Generator rule list */
+ struct rule_list_engine rule_list_engine = {0};
+ rule_list_engine.nr_rules = 128;
+
+ /* Full-field matching V4 */
+ struct rule_field_engine * rule = &rule_list_engine.rules[0];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 0;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 0;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 0;
+ rule->ether_type = RTE_ETHER_TYPE_IPV4;
+ rule->src_addr_mask_len = 32;
+ rule->dst_addr_mask_len = 32;
+ inet_pton(AF_INET, "172.17.1.1", &rule->src_addr_v4);
+ inet_pton(AF_INET, "172.17.1.2", &rule->dst_addr_v4);
+
+ /* Full-field matching V6*/
+ rule = &rule_list_engine.rules[1];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 0;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 1;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 1;
+ rule->ether_type = RTE_ETHER_TYPE_IPV6;
+ rule->src_addr_mask_len = 128;
+ rule->dst_addr_mask_len = 128;
+ inet_pton(AF_INET6, "2001:db8:0:1:1:1:1:1", &rule->src_addr_v6);
+ inet_pton(AF_INET6, "2001:db8:0:1:1:1:1:2", &rule->dst_addr_v6);
+
+ /* Fuzzy matching V4 */
+ rule = &rule_list_engine.rules[2];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 1;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 2;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 2;
+ rule->ether_type = RTE_ETHER_TYPE_IPV4;
+ rule->src_addr_mask_len = 0;
+ rule->dst_addr_mask_len = 0;
+
+ /* Fuzzy matching V6 */
+ rule = &rule_list_engine.rules[3];
+ rule->proto = 0;
+ rule->proto_mask = 0;
+ rule->priority = 1;
+ rule->domain = 0;
+ rule->src_port_start = 0;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 3;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 3;
+ rule->ether_type = RTE_ETHER_TYPE_IPV6;
+ rule->src_addr_mask_len = 0;
+ rule->dst_addr_mask_len = 0;
+
+ for (int index = 4; index < rule_list_engine.nr_rules; index++)
+ {
+ struct rule_field_engine * rule = &rule_list_engine.rules[index];
+ rule->proto = IPPROTO_UDP;
+ rule->proto_mask = 0;
+ rule->priority = 0;
+ rule->domain = 0;
+ rule->src_port_start = index;
+ rule->src_port_end = 65535;
+ rule->dst_port_start = 0;
+ rule->dst_port_end = 65535;
+ rule->rule_id = 0;
+ rule->action.type = ACTION_NF_STEERING;
+ rule->action.data = 0;
+ rule->ether_type = RTE_ETHER_TYPE_IPV4;
+ rule->src_addr_mask_len = 24;
+ rule->dst_addr_mask_len = 0;
+ inet_pton(AF_INET, "172.17.1.1", &rule->src_addr_v4);
+ }
+
+ /* Build the engine */
+ char str_error_reason[MR_STRING_MAX];
+ int ret =
+ pkt_classifier_engine_build(engine_instance_, &rule_list_engine, str_error_reason, sizeof(str_error_reason));
+ if (ret != 0)
+ {
+ printf("error reason: %s\n", str_error_reason);
+ }
+ EXPECT_EQ(ret, 0);
+
+ /* Create the pkts */
+ int nr_pkts = 4;
+ struct rte_mbuf * pkts[nr_pkts];
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool_, pkts, RTE_DIM(pkts));
+ ASSERT_EQ(ret, 0);
+ char str_ip_src_addr[MR_SYMBOL_MAX] = {};
+ char str_ip_dst_addr[MR_SYMBOL_MAX] = {};
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "172.17.1.1");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "172.17.1.2");
+ construct_pkt_for_ipv4(pkts[0], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "2001:db8:0:1:1:1:1:1");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "2001:db8:0:1:1:1:1:2");
+ construct_pkt_for_ipv6(pkts[1], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "172.17.1.3");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "172.17.1.4");
+ construct_pkt_for_ipv4(pkts[2], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ snprintf(str_ip_src_addr, sizeof(str_ip_src_addr) - 1, "2001:db8:0:1:1:1:1:3");
+ snprintf(str_ip_dst_addr, sizeof(str_ip_dst_addr) - 1, "2001:db8:0:1:1:1:1:4");
+ construct_pkt_for_ipv6(pkts[3], str_ip_src_addr, str_ip_dst_addr, IPPROTO_ICMP, 0, 0);
+
+ /* Parser pkts */
+ for (uint8_t pkt_idx = 0; pkt_idx < nr_pkts; pkt_idx++)
+ {
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkts[pkt_idx], MR_NODE_CTRLZONE_ID);
+ memset(mrb_meta, 0, sizeof(struct mrb_metadata));
+ struct pkt_parser pkt_parser;
+ pkt_parser_init(&pkt_parser, &mrb_meta->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX);
+ pkt_parser_exec(&pkt_parser, pkts[pkt_idx]);
+ }
+
+ /* Generate the domain field for all pkts */
+ uint16_t domain_field_for_pkts[nr_pkts];
+ for (int index = 0; index < nr_pkts; index++)
+ {
+ domain_field_for_pkts[index] = 0;
+ }
+
+ /* Match all pkts */
+ struct match_result_engine result[nr_pkts];
+ pkt_classifier_engine_multi_match(engine_instance_, 1, pkts, nr_pkts, domain_field_for_pkts, result);
+
+ /* Check the results */
+ EXPECT_EQ(result[0].nr_actions, 2);
+ EXPECT_EQ(result[0].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[0].actions[0].data, 0);
+ EXPECT_EQ(result[0].actions[1].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[0].actions[1].data, 2);
+
+ EXPECT_EQ(result[1].nr_actions, 2);
+ EXPECT_EQ(result[1].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[1].actions[0].data, 1);
+ EXPECT_EQ(result[1].actions[1].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[1].actions[1].data, 3);
+
+ EXPECT_EQ(result[2].nr_actions, 1);
+ EXPECT_EQ(result[2].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[2].actions[0].data, 2);
+
+ EXPECT_EQ(result[3].nr_actions, 1);
+ EXPECT_EQ(result[3].actions[0].type, ACTION_NF_STEERING);
+ EXPECT_EQ(result[3].actions[0].data, 3);
+
+ /* Free the packet */
+ rte_pktmbuf_free_bulk(pkts, RTE_DIM(pkts));
+}
+
#if 0
TEST_F(TestCasePktClassifierEngine, RuleValidityCheckTest)
{