diff options
| author | songyanchao <[email protected]> | 2023-12-28 06:15:25 +0000 |
|---|---|---|
| committer | songyanchao <[email protected]> | 2023-12-28 06:15:25 +0000 |
| commit | dda2a20a5fc0187f304994fd116711e40fec8493 (patch) | |
| tree | 0175137766130396d3996c7b94e9bb187f00d11f | |
| parent | b269cd473f22c60203ed50804dc7a26638e6964f (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.c | 16 | ||||
| -rw-r--r-- | infra/test/TestPktClassifierEngine.cc | 360 |
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) { |
