106d63eb5SAaron Conole /* SPDX-License-Identifier: BSD-3-Clause 206d63eb5SAaron Conole * Copyright(c) 2020 Red Hat, Inc. 306d63eb5SAaron Conole */ 406d63eb5SAaron Conole 53c60274cSJie Zhou #include "test.h" 63c60274cSJie Zhou 706d63eb5SAaron Conole #include <time.h> 806d63eb5SAaron Conole 906d63eb5SAaron Conole #include <rte_common.h> 1006d63eb5SAaron Conole #include <rte_cycles.h> 1106d63eb5SAaron Conole #include <rte_hexdump.h> 1206d63eb5SAaron Conole #include <rte_ip.h> 1306d63eb5SAaron Conole #include <rte_ip_frag.h> 1406d63eb5SAaron Conole #include <rte_mbuf.h> 1506d63eb5SAaron Conole #include <rte_random.h> 1606d63eb5SAaron Conole 1706d63eb5SAaron Conole #define NUM_MBUFS 128 1806d63eb5SAaron Conole #define BURST 32 1906d63eb5SAaron Conole 20b50a14a8SHuichao Cai uint8_t expected_first_frag_ipv4_opts_copied[] = { 21b50a14a8SHuichao Cai 0x07, 0x0b, 0x04, 0x00, 22b50a14a8SHuichao Cai 0x00, 0x00, 0x00, 0x00, 23b50a14a8SHuichao Cai 0x00, 0x00, 0x00, 0x83, 24b50a14a8SHuichao Cai 0x07, 0x04, 0xc0, 0xa8, 25b50a14a8SHuichao Cai 0xe3, 0x96, 0x00, 0x00, 26b50a14a8SHuichao Cai }; 27b50a14a8SHuichao Cai 28b50a14a8SHuichao Cai uint8_t expected_sub_frag_ipv4_opts_copied[] = { 29b50a14a8SHuichao Cai 0x83, 0x07, 0x04, 0xc0, 30b50a14a8SHuichao Cai 0xa8, 0xe3, 0x96, 0x00, 31b50a14a8SHuichao Cai }; 32b50a14a8SHuichao Cai 33b50a14a8SHuichao Cai uint8_t expected_first_frag_ipv4_opts_nocopied[] = { 34b50a14a8SHuichao Cai 0x07, 0x0b, 0x04, 0x00, 35b50a14a8SHuichao Cai 0x00, 0x00, 0x00, 0x00, 36b50a14a8SHuichao Cai 0x00, 0x00, 0x00, 0x00, 37b50a14a8SHuichao Cai }; 38b50a14a8SHuichao Cai 39b50a14a8SHuichao Cai uint8_t expected_sub_frag_ipv4_opts_nocopied[0]; 40b50a14a8SHuichao Cai 41b50a14a8SHuichao Cai struct test_opt_data { 42b50a14a8SHuichao Cai bool is_first_frag; /**< offset is 0 */ 43b50a14a8SHuichao Cai bool opt_copied; /**< ip option copied flag */ 44b50a14a8SHuichao Cai uint16_t len; /**< option data len */ 45b50a14a8SHuichao Cai uint8_t data[RTE_IPV4_HDR_OPT_MAX_LEN]; /**< option data */ 46b50a14a8SHuichao Cai }; 47b50a14a8SHuichao Cai 4806d63eb5SAaron Conole static struct rte_mempool *pkt_pool, 4906d63eb5SAaron Conole *direct_pool, 5006d63eb5SAaron Conole *indirect_pool; 5106d63eb5SAaron Conole 52b50a14a8SHuichao Cai static inline void 53b50a14a8SHuichao Cai hex_to_str(uint8_t *hex, uint16_t len, char *str) 54b50a14a8SHuichao Cai { 55b50a14a8SHuichao Cai int i; 56b50a14a8SHuichao Cai 57b50a14a8SHuichao Cai for (i = 0; i < len; i++) { 58b50a14a8SHuichao Cai sprintf(str, "%02x", hex[i]); 59b50a14a8SHuichao Cai str += 2; 60b50a14a8SHuichao Cai } 61b50a14a8SHuichao Cai *str = 0; 62b50a14a8SHuichao Cai } 63b50a14a8SHuichao Cai 6406d63eb5SAaron Conole static int 6506d63eb5SAaron Conole setup_buf_pool(void) 6606d63eb5SAaron Conole { 6706d63eb5SAaron Conole pkt_pool = rte_pktmbuf_pool_create("FRAG_MBUF_POOL", 6806d63eb5SAaron Conole NUM_MBUFS, BURST, 0, 6906d63eb5SAaron Conole RTE_MBUF_DEFAULT_BUF_SIZE, 7006d63eb5SAaron Conole SOCKET_ID_ANY); 7106d63eb5SAaron Conole if (pkt_pool == NULL) { 7206d63eb5SAaron Conole printf("%s: Error creating pkt mempool\n", __func__); 7306d63eb5SAaron Conole goto bad_setup; 7406d63eb5SAaron Conole } 7506d63eb5SAaron Conole 7606d63eb5SAaron Conole direct_pool = rte_pktmbuf_pool_create("FRAG_D_MBUF_POOL", 7706d63eb5SAaron Conole NUM_MBUFS, BURST, 0, 7806d63eb5SAaron Conole RTE_MBUF_DEFAULT_BUF_SIZE, 7906d63eb5SAaron Conole SOCKET_ID_ANY); 8006d63eb5SAaron Conole if (direct_pool == NULL) { 8106d63eb5SAaron Conole printf("%s: Error creating direct mempool\n", __func__); 8206d63eb5SAaron Conole goto bad_setup; 8306d63eb5SAaron Conole } 8406d63eb5SAaron Conole 8506d63eb5SAaron Conole indirect_pool = rte_pktmbuf_pool_create("FRAG_I_MBUF_POOL", 8606d63eb5SAaron Conole NUM_MBUFS, BURST, 0, 8706d63eb5SAaron Conole 0, SOCKET_ID_ANY); 8806d63eb5SAaron Conole if (indirect_pool == NULL) { 8906d63eb5SAaron Conole printf("%s: Error creating indirect mempool\n", __func__); 9006d63eb5SAaron Conole goto bad_setup; 9106d63eb5SAaron Conole } 9206d63eb5SAaron Conole 9306d63eb5SAaron Conole return TEST_SUCCESS; 9406d63eb5SAaron Conole 9506d63eb5SAaron Conole bad_setup: 9606d63eb5SAaron Conole rte_mempool_free(pkt_pool); 9706d63eb5SAaron Conole pkt_pool = NULL; 9806d63eb5SAaron Conole 9906d63eb5SAaron Conole rte_mempool_free(direct_pool); 10006d63eb5SAaron Conole direct_pool = NULL; 10106d63eb5SAaron Conole 10206d63eb5SAaron Conole return TEST_FAILED; 10306d63eb5SAaron Conole } 10406d63eb5SAaron Conole 10506d63eb5SAaron Conole static int testsuite_setup(void) 10606d63eb5SAaron Conole { 10706d63eb5SAaron Conole return setup_buf_pool(); 10806d63eb5SAaron Conole } 10906d63eb5SAaron Conole 11006d63eb5SAaron Conole static void testsuite_teardown(void) 11106d63eb5SAaron Conole { 11206d63eb5SAaron Conole rte_mempool_free(pkt_pool); 11306d63eb5SAaron Conole rte_mempool_free(direct_pool); 11406d63eb5SAaron Conole rte_mempool_free(indirect_pool); 11506d63eb5SAaron Conole 11606d63eb5SAaron Conole pkt_pool = NULL; 11706d63eb5SAaron Conole direct_pool = NULL; 11806d63eb5SAaron Conole indirect_pool = NULL; 11906d63eb5SAaron Conole } 12006d63eb5SAaron Conole 12106d63eb5SAaron Conole static int ut_setup(void) 12206d63eb5SAaron Conole { 12306d63eb5SAaron Conole return TEST_SUCCESS; 12406d63eb5SAaron Conole } 12506d63eb5SAaron Conole 12606d63eb5SAaron Conole static void ut_teardown(void) 12706d63eb5SAaron Conole { 12806d63eb5SAaron Conole } 12906d63eb5SAaron Conole 130b50a14a8SHuichao Cai static inline void 131b50a14a8SHuichao Cai test_get_ipv4_opt(bool is_first_frag, bool opt_copied, 132b50a14a8SHuichao Cai struct test_opt_data *expected_opt) 133b50a14a8SHuichao Cai { 134b50a14a8SHuichao Cai if (is_first_frag) { 135b50a14a8SHuichao Cai if (opt_copied) { 136b50a14a8SHuichao Cai expected_opt->len = 137b50a14a8SHuichao Cai sizeof(expected_first_frag_ipv4_opts_copied); 138e1522b32SHuichao Cai memcpy(expected_opt->data, 139b50a14a8SHuichao Cai expected_first_frag_ipv4_opts_copied, 140b50a14a8SHuichao Cai sizeof(expected_first_frag_ipv4_opts_copied)); 141b50a14a8SHuichao Cai } else { 142b50a14a8SHuichao Cai expected_opt->len = 143b50a14a8SHuichao Cai sizeof(expected_first_frag_ipv4_opts_nocopied); 144e1522b32SHuichao Cai memcpy(expected_opt->data, 145b50a14a8SHuichao Cai expected_first_frag_ipv4_opts_nocopied, 146b50a14a8SHuichao Cai sizeof(expected_first_frag_ipv4_opts_nocopied)); 147b50a14a8SHuichao Cai } 148b50a14a8SHuichao Cai } else { 149b50a14a8SHuichao Cai if (opt_copied) { 150b50a14a8SHuichao Cai expected_opt->len = 151b50a14a8SHuichao Cai sizeof(expected_sub_frag_ipv4_opts_copied); 152e1522b32SHuichao Cai memcpy(expected_opt->data, 153b50a14a8SHuichao Cai expected_sub_frag_ipv4_opts_copied, 154b50a14a8SHuichao Cai sizeof(expected_sub_frag_ipv4_opts_copied)); 155b50a14a8SHuichao Cai } else { 156b50a14a8SHuichao Cai expected_opt->len = 157b50a14a8SHuichao Cai sizeof(expected_sub_frag_ipv4_opts_nocopied); 158e1522b32SHuichao Cai memcpy(expected_opt->data, 159b50a14a8SHuichao Cai expected_sub_frag_ipv4_opts_nocopied, 160b50a14a8SHuichao Cai sizeof(expected_sub_frag_ipv4_opts_nocopied)); 161b50a14a8SHuichao Cai } 162b50a14a8SHuichao Cai } 163b50a14a8SHuichao Cai } 164b50a14a8SHuichao Cai 16506d63eb5SAaron Conole static void 166b50a14a8SHuichao Cai v4_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, 167b50a14a8SHuichao Cai int df, uint8_t mf, uint16_t off, uint8_t ttl, uint8_t proto, 168b50a14a8SHuichao Cai uint16_t pktid, bool have_opt, bool is_first_frag, bool opt_copied) 16906d63eb5SAaron Conole { 17006d63eb5SAaron Conole /* Create a packet, 2k bytes long */ 17106d63eb5SAaron Conole b->data_off = 0; 17206d63eb5SAaron Conole char *data = rte_pktmbuf_mtod(b, char *); 173b50a14a8SHuichao Cai rte_be16_t fragment_offset = 0; /* fragmentation offset */ 174b50a14a8SHuichao Cai uint16_t iph_len; 175b50a14a8SHuichao Cai struct test_opt_data opt; 17606d63eb5SAaron Conole 177b50a14a8SHuichao Cai opt.len = 0; 178b50a14a8SHuichao Cai 179b50a14a8SHuichao Cai if (have_opt) 180b50a14a8SHuichao Cai test_get_ipv4_opt(is_first_frag, opt_copied, &opt); 181b50a14a8SHuichao Cai 182b50a14a8SHuichao Cai iph_len = sizeof(struct rte_ipv4_hdr) + opt.len; 183b50a14a8SHuichao Cai memset(data, fill, iph_len + s); 18406d63eb5SAaron Conole 18506d63eb5SAaron Conole struct rte_ipv4_hdr *hdr = (struct rte_ipv4_hdr *)data; 18606d63eb5SAaron Conole 187b50a14a8SHuichao Cai hdr->version_ihl = 0x40; /* ipv4 */ 188b50a14a8SHuichao Cai hdr->version_ihl += (iph_len / 4); 18906d63eb5SAaron Conole hdr->type_of_service = 0; 190b50a14a8SHuichao Cai b->pkt_len = s + iph_len; 19106d63eb5SAaron Conole b->data_len = b->pkt_len; 19206d63eb5SAaron Conole hdr->total_length = rte_cpu_to_be_16(b->pkt_len); 19306d63eb5SAaron Conole hdr->packet_id = rte_cpu_to_be_16(pktid); 194e3999afdSHuichao Cai 19506d63eb5SAaron Conole if (df) 196e3999afdSHuichao Cai fragment_offset |= 0x4000; 197e3999afdSHuichao Cai 198e3999afdSHuichao Cai if (mf) 199e3999afdSHuichao Cai fragment_offset |= 0x2000; 200e3999afdSHuichao Cai 201e3999afdSHuichao Cai if (off) 202e3999afdSHuichao Cai fragment_offset |= off; 203e3999afdSHuichao Cai 204e3999afdSHuichao Cai hdr->fragment_offset = rte_cpu_to_be_16(fragment_offset); 20506d63eb5SAaron Conole 20606d63eb5SAaron Conole if (!ttl) 20706d63eb5SAaron Conole ttl = 64; /* default to 64 */ 20806d63eb5SAaron Conole 20906d63eb5SAaron Conole if (!proto) 21006d63eb5SAaron Conole proto = 1; /* icmp */ 21106d63eb5SAaron Conole 21206d63eb5SAaron Conole hdr->time_to_live = ttl; 21306d63eb5SAaron Conole hdr->next_proto_id = proto; 21406d63eb5SAaron Conole hdr->hdr_checksum = 0; 21506d63eb5SAaron Conole hdr->src_addr = rte_cpu_to_be_32(0x8080808); 21606d63eb5SAaron Conole hdr->dst_addr = rte_cpu_to_be_32(0x8080404); 217b50a14a8SHuichao Cai 218e1522b32SHuichao Cai memcpy(hdr + 1, opt.data, opt.len); 21906d63eb5SAaron Conole } 22006d63eb5SAaron Conole 22106d63eb5SAaron Conole static void 22206d63eb5SAaron Conole v6_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, uint8_t ttl, 22306d63eb5SAaron Conole uint8_t proto, uint16_t pktid) 22406d63eb5SAaron Conole { 22506d63eb5SAaron Conole /* Create a packet, 2k bytes long */ 22606d63eb5SAaron Conole b->data_off = 0; 22706d63eb5SAaron Conole char *data = rte_pktmbuf_mtod(b, char *); 22806d63eb5SAaron Conole 22906d63eb5SAaron Conole memset(data, fill, sizeof(struct rte_ipv6_hdr) + s); 23006d63eb5SAaron Conole 23106d63eb5SAaron Conole struct rte_ipv6_hdr *hdr = (struct rte_ipv6_hdr *)data; 23206d63eb5SAaron Conole b->pkt_len = s + sizeof(struct rte_ipv6_hdr); 23306d63eb5SAaron Conole b->data_len = b->pkt_len; 23406d63eb5SAaron Conole 23506d63eb5SAaron Conole /* basic v6 header */ 23606d63eb5SAaron Conole hdr->vtc_flow = rte_cpu_to_be_32(0x60 << 24 | pktid); 23706d63eb5SAaron Conole hdr->payload_len = rte_cpu_to_be_16(b->pkt_len); 23806d63eb5SAaron Conole hdr->proto = proto; 23906d63eb5SAaron Conole hdr->hop_limits = ttl; 24006d63eb5SAaron Conole 241*89b5642dSRobin Jarry memset(&hdr->src_addr, 0x08, sizeof(hdr->src_addr)); 242*89b5642dSRobin Jarry memset(&hdr->dst_addr, 0x04, sizeof(hdr->src_addr)); 24306d63eb5SAaron Conole } 24406d63eb5SAaron Conole 24506d63eb5SAaron Conole static inline void 24606d63eb5SAaron Conole test_free_fragments(struct rte_mbuf *mb[], uint32_t num) 24706d63eb5SAaron Conole { 24806d63eb5SAaron Conole uint32_t i; 24906d63eb5SAaron Conole for (i = 0; i < num; i++) 25006d63eb5SAaron Conole rte_pktmbuf_free(mb[i]); 25106d63eb5SAaron Conole } 25206d63eb5SAaron Conole 253e3999afdSHuichao Cai static inline void 254e3999afdSHuichao Cai test_get_offset(struct rte_mbuf **mb, int32_t len, 255e3999afdSHuichao Cai uint16_t *offset, int ipv) 256e3999afdSHuichao Cai { 257e3999afdSHuichao Cai int32_t i; 258e3999afdSHuichao Cai 259e3999afdSHuichao Cai for (i = 0; i < len; i++) { 260e3999afdSHuichao Cai if (ipv == 4) { 261e3999afdSHuichao Cai struct rte_ipv4_hdr *iph = 262e3999afdSHuichao Cai rte_pktmbuf_mtod(mb[i], struct rte_ipv4_hdr *); 263e3999afdSHuichao Cai offset[i] = iph->fragment_offset; 264e3999afdSHuichao Cai } else if (ipv == 6) { 265e3999afdSHuichao Cai struct ipv6_extension_fragment *fh = 266e3999afdSHuichao Cai rte_pktmbuf_mtod_offset( 267e3999afdSHuichao Cai mb[i], 268e3999afdSHuichao Cai struct ipv6_extension_fragment *, 269e3999afdSHuichao Cai sizeof(struct rte_ipv6_hdr)); 270e3999afdSHuichao Cai offset[i] = fh->frag_data; 271e3999afdSHuichao Cai } 272e3999afdSHuichao Cai } 273e3999afdSHuichao Cai } 274e3999afdSHuichao Cai 275b50a14a8SHuichao Cai static inline void 276b50a14a8SHuichao Cai test_get_frag_opt(struct rte_mbuf **mb, int32_t num, 277b50a14a8SHuichao Cai struct test_opt_data *opt, int ipv, bool opt_copied) 278b50a14a8SHuichao Cai { 279b50a14a8SHuichao Cai int32_t i; 280b50a14a8SHuichao Cai 281b50a14a8SHuichao Cai for (i = 0; i < num; i++) { 282b50a14a8SHuichao Cai if (ipv == 4) { 283b50a14a8SHuichao Cai struct rte_ipv4_hdr *iph = 284b50a14a8SHuichao Cai rte_pktmbuf_mtod(mb[i], struct rte_ipv4_hdr *); 285b50a14a8SHuichao Cai uint16_t header_len = (iph->version_ihl & 286b50a14a8SHuichao Cai RTE_IPV4_HDR_IHL_MASK) * 287b50a14a8SHuichao Cai RTE_IPV4_IHL_MULTIPLIER; 288b50a14a8SHuichao Cai uint16_t opt_len = header_len - 289b50a14a8SHuichao Cai sizeof(struct rte_ipv4_hdr); 290b50a14a8SHuichao Cai 291b50a14a8SHuichao Cai opt->opt_copied = opt_copied; 292b50a14a8SHuichao Cai 293b50a14a8SHuichao Cai if ((rte_be_to_cpu_16(iph->fragment_offset) & 294b50a14a8SHuichao Cai RTE_IPV4_HDR_OFFSET_MASK) == 0) 295b50a14a8SHuichao Cai opt->is_first_frag = true; 296b50a14a8SHuichao Cai else 297b50a14a8SHuichao Cai opt->is_first_frag = false; 298b50a14a8SHuichao Cai 299b50a14a8SHuichao Cai if (likely(opt_len <= RTE_IPV4_HDR_OPT_MAX_LEN)) { 300b50a14a8SHuichao Cai char *iph_opt = rte_pktmbuf_mtod_offset(mb[i], 301b50a14a8SHuichao Cai char *, sizeof(struct rte_ipv4_hdr)); 302b50a14a8SHuichao Cai opt->len = opt_len; 303e1522b32SHuichao Cai memcpy(opt->data, iph_opt, opt_len); 304b50a14a8SHuichao Cai } else { 305b50a14a8SHuichao Cai opt->len = RTE_IPV4_HDR_OPT_MAX_LEN; 306b50a14a8SHuichao Cai memset(opt->data, RTE_IPV4_HDR_OPT_EOL, 307b50a14a8SHuichao Cai sizeof(opt->data)); 308b50a14a8SHuichao Cai } 309b50a14a8SHuichao Cai opt++; 310b50a14a8SHuichao Cai } 311b50a14a8SHuichao Cai } 312b50a14a8SHuichao Cai } 313b50a14a8SHuichao Cai 31406d63eb5SAaron Conole static int 31506d63eb5SAaron Conole test_ip_frag(void) 31606d63eb5SAaron Conole { 31706d63eb5SAaron Conole static const uint16_t RND_ID = UINT16_MAX; 31806d63eb5SAaron Conole int result = TEST_SUCCESS; 319e3999afdSHuichao Cai size_t i, j; 32006d63eb5SAaron Conole 32106d63eb5SAaron Conole struct test_ip_frags { 32206d63eb5SAaron Conole int ipv; 32306d63eb5SAaron Conole size_t mtu_size; 32406d63eb5SAaron Conole size_t pkt_size; 32506d63eb5SAaron Conole int set_df; 326e3999afdSHuichao Cai uint8_t set_mf; 327e3999afdSHuichao Cai uint16_t set_of; 32806d63eb5SAaron Conole uint8_t ttl; 32906d63eb5SAaron Conole uint8_t proto; 33006d63eb5SAaron Conole uint16_t pkt_id; 33106d63eb5SAaron Conole int expected_frags; 332e3999afdSHuichao Cai uint16_t expected_fragment_offset[BURST]; 333b50a14a8SHuichao Cai bool have_opt; 334b50a14a8SHuichao Cai bool is_first_frag; 335b50a14a8SHuichao Cai bool opt_copied; 33606d63eb5SAaron Conole } tests[] = { 337e3999afdSHuichao Cai {4, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, 338b50a14a8SHuichao Cai {0x2000, 0x009D}, false}, 339e3999afdSHuichao Cai {4, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, 0, 2, 340b50a14a8SHuichao Cai {0x2000, 0x009D}, false}, 341e3999afdSHuichao Cai {4, 600, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 3, 342b50a14a8SHuichao Cai {0x2000, 0x2048, 0x0090}, false}, 343e3999afdSHuichao Cai {4, 4, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL}, 344e3999afdSHuichao Cai {4, 600, 1400, 1, 0, 0, 64, IPPROTO_ICMP, RND_ID, -ENOTSUP}, 345e3999afdSHuichao Cai {4, 600, 1400, 0, 0, 0, 0, IPPROTO_ICMP, RND_ID, 3, 346b50a14a8SHuichao Cai {0x2000, 0x2046, 0x008C}, true, true, true}, 347b50a14a8SHuichao Cai /* The first fragment */ 348b50a14a8SHuichao Cai {4, 68, 104, 0, 1, 0, 0, IPPROTO_ICMP, RND_ID, 5, 349b50a14a8SHuichao Cai {0x2000, 0x2003, 0x2006, 0x2009, 0x200C}, true, true, true}, 350b50a14a8SHuichao Cai /* The middle fragment */ 351e3999afdSHuichao Cai {4, 68, 104, 0, 1, 13, 0, IPPROTO_ICMP, RND_ID, 3, 352b50a14a8SHuichao Cai {0x200D, 0x2012, 0x2017}, true, false, true}, 353b50a14a8SHuichao Cai /* The last fragment */ 354b50a14a8SHuichao Cai {4, 68, 104, 0, 0, 26, 0, IPPROTO_ICMP, RND_ID, 3, 355b50a14a8SHuichao Cai {0x201A, 0x201F, 0x0024}, true, false, true}, 356b50a14a8SHuichao Cai /* The first fragment */ 357b50a14a8SHuichao Cai {4, 68, 104, 0, 1, 0, 0, IPPROTO_ICMP, RND_ID, 4, 358b50a14a8SHuichao Cai {0x2000, 0x2004, 0x2008, 0x200C}, true, true, false}, 359b50a14a8SHuichao Cai /* The middle fragment */ 360b50a14a8SHuichao Cai {4, 68, 104, 0, 1, 13, 0, IPPROTO_ICMP, RND_ID, 3, 361b50a14a8SHuichao Cai {0x200D, 0x2013, 0x2019}, true, false, false}, 362b50a14a8SHuichao Cai /* The last fragment */ 363b50a14a8SHuichao Cai {4, 68, 104, 0, 0, 26, 0, IPPROTO_ICMP, RND_ID, 3, 364b50a14a8SHuichao Cai {0x201A, 0x2020, 0x0026}, true, false, false}, 365e3999afdSHuichao Cai {6, 1280, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, 366b50a14a8SHuichao Cai {0x0001, 0x04D0}, false}, 367e3999afdSHuichao Cai {6, 1300, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, 2, 368b50a14a8SHuichao Cai {0x0001, 0x04E0}, false}, 369e3999afdSHuichao Cai {6, 4, 1400, 0, 0, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL}, 370e3999afdSHuichao Cai {6, 1300, 1400, 0, 0, 0, 0, IPPROTO_ICMP, RND_ID, 2, 371b50a14a8SHuichao Cai {0x0001, 0x04E0}, false}, 37206d63eb5SAaron Conole }; 37306d63eb5SAaron Conole 37406d63eb5SAaron Conole for (i = 0; i < RTE_DIM(tests); i++) { 37506d63eb5SAaron Conole int32_t len = 0; 376e3999afdSHuichao Cai uint16_t fragment_offset[BURST]; 377b50a14a8SHuichao Cai struct test_opt_data opt_res[BURST]; 378b50a14a8SHuichao Cai struct test_opt_data opt_exp; 37906d63eb5SAaron Conole uint16_t pktid = tests[i].pkt_id; 38006d63eb5SAaron Conole struct rte_mbuf *pkts_out[BURST]; 38106d63eb5SAaron Conole struct rte_mbuf *b = rte_pktmbuf_alloc(pkt_pool); 38206d63eb5SAaron Conole 38306d63eb5SAaron Conole RTE_TEST_ASSERT_NOT_EQUAL(b, NULL, 38406d63eb5SAaron Conole "Failed to allocate pkt."); 38506d63eb5SAaron Conole 38606d63eb5SAaron Conole if (tests[i].pkt_id == RND_ID) 38706d63eb5SAaron Conole pktid = rte_rand_max(UINT16_MAX); 38806d63eb5SAaron Conole 38906d63eb5SAaron Conole if (tests[i].ipv == 4) { 39006d63eb5SAaron Conole v4_allocate_packet_of(b, 0x41414141, 39106d63eb5SAaron Conole tests[i].pkt_size, 39206d63eb5SAaron Conole tests[i].set_df, 393e3999afdSHuichao Cai tests[i].set_mf, 394e3999afdSHuichao Cai tests[i].set_of, 39506d63eb5SAaron Conole tests[i].ttl, 39606d63eb5SAaron Conole tests[i].proto, 397b50a14a8SHuichao Cai pktid, 398b50a14a8SHuichao Cai tests[i].have_opt, 399b50a14a8SHuichao Cai tests[i].is_first_frag, 400b50a14a8SHuichao Cai tests[i].opt_copied); 40106d63eb5SAaron Conole } else if (tests[i].ipv == 6) { 40206d63eb5SAaron Conole v6_allocate_packet_of(b, 0x41414141, 40306d63eb5SAaron Conole tests[i].pkt_size, 40406d63eb5SAaron Conole tests[i].ttl, 40506d63eb5SAaron Conole tests[i].proto, 40606d63eb5SAaron Conole pktid); 40706d63eb5SAaron Conole } 40806d63eb5SAaron Conole 40906d63eb5SAaron Conole if (tests[i].ipv == 4) 4104aee6110SHuichao Cai if (i % 2) 41106d63eb5SAaron Conole len = rte_ipv4_fragment_packet(b, pkts_out, BURST, 41206d63eb5SAaron Conole tests[i].mtu_size, 41306d63eb5SAaron Conole direct_pool, 41406d63eb5SAaron Conole indirect_pool); 4154aee6110SHuichao Cai else 4164aee6110SHuichao Cai len = rte_ipv4_fragment_copy_nonseg_packet(b, 4174aee6110SHuichao Cai pkts_out, 4184aee6110SHuichao Cai BURST, 4194aee6110SHuichao Cai tests[i].mtu_size, 4204aee6110SHuichao Cai direct_pool); 42106d63eb5SAaron Conole else if (tests[i].ipv == 6) 42206d63eb5SAaron Conole len = rte_ipv6_fragment_packet(b, pkts_out, BURST, 42306d63eb5SAaron Conole tests[i].mtu_size, 42406d63eb5SAaron Conole direct_pool, 42506d63eb5SAaron Conole indirect_pool); 42606d63eb5SAaron Conole 42706d63eb5SAaron Conole rte_pktmbuf_free(b); 42806d63eb5SAaron Conole 429e3999afdSHuichao Cai if (len > 0) { 430e3999afdSHuichao Cai test_get_offset(pkts_out, len, 431e3999afdSHuichao Cai fragment_offset, tests[i].ipv); 432b50a14a8SHuichao Cai if (tests[i].have_opt) 433b50a14a8SHuichao Cai test_get_frag_opt(pkts_out, len, opt_res, 434b50a14a8SHuichao Cai tests[i].ipv, tests[i].opt_copied); 43506d63eb5SAaron Conole test_free_fragments(pkts_out, len); 436e3999afdSHuichao Cai } 43706d63eb5SAaron Conole 438b50a14a8SHuichao Cai printf("[check frag number]%zd: checking %d with %d\n", i, len, 43906d63eb5SAaron Conole tests[i].expected_frags); 44006d63eb5SAaron Conole RTE_TEST_ASSERT_EQUAL(len, tests[i].expected_frags, 44106d63eb5SAaron Conole "Failed case %zd.\n", i); 44206d63eb5SAaron Conole 443e3999afdSHuichao Cai if (len > 0) { 444e3999afdSHuichao Cai for (j = 0; j < (size_t)len; j++) { 445b50a14a8SHuichao Cai printf("[check offset]%zd-%zd: checking %d with %d\n", 446e3999afdSHuichao Cai i, j, fragment_offset[j], 447e3999afdSHuichao Cai rte_cpu_to_be_16( 448e3999afdSHuichao Cai tests[i].expected_fragment_offset[j])); 449e3999afdSHuichao Cai RTE_TEST_ASSERT_EQUAL(fragment_offset[j], 450e3999afdSHuichao Cai rte_cpu_to_be_16( 451e3999afdSHuichao Cai tests[i].expected_fragment_offset[j]), 452e3999afdSHuichao Cai "Failed case %zd.\n", i); 453e3999afdSHuichao Cai } 454b50a14a8SHuichao Cai 455b50a14a8SHuichao Cai if (tests[i].have_opt && (tests[i].ipv == 4)) { 456b50a14a8SHuichao Cai for (j = 0; j < (size_t)len; j++) { 457b50a14a8SHuichao Cai char opt_res_str[2 * 458b50a14a8SHuichao Cai RTE_IPV4_HDR_OPT_MAX_LEN + 1]; 459b50a14a8SHuichao Cai char opt_exp_str[2 * 460b50a14a8SHuichao Cai RTE_IPV4_HDR_OPT_MAX_LEN + 1]; 461b50a14a8SHuichao Cai 462b50a14a8SHuichao Cai test_get_ipv4_opt( 463b50a14a8SHuichao Cai opt_res[j].is_first_frag, 464b50a14a8SHuichao Cai opt_res[j].opt_copied, 465b50a14a8SHuichao Cai &opt_exp); 466b50a14a8SHuichao Cai hex_to_str(opt_res[j].data, 467b50a14a8SHuichao Cai opt_res[j].len, 468b50a14a8SHuichao Cai opt_res_str); 469b50a14a8SHuichao Cai hex_to_str(opt_exp.data, 470b50a14a8SHuichao Cai opt_exp.len, 471b50a14a8SHuichao Cai opt_exp_str); 472b50a14a8SHuichao Cai 473b50a14a8SHuichao Cai printf( 474b50a14a8SHuichao Cai "[check ipv4 option]%zd-%zd: checking (len:%u)%s with (len:%u)%s\n", 475b50a14a8SHuichao Cai i, j, 476b50a14a8SHuichao Cai opt_res[j].len, opt_res_str, 477b50a14a8SHuichao Cai opt_exp.len, opt_exp_str); 478b50a14a8SHuichao Cai RTE_TEST_ASSERT_SUCCESS( 479b50a14a8SHuichao Cai strcmp(opt_res_str, 480b50a14a8SHuichao Cai opt_exp_str), 481b50a14a8SHuichao Cai "Failed case %zd.\n", i); 482b50a14a8SHuichao Cai } 483b50a14a8SHuichao Cai } 484e3999afdSHuichao Cai } 485e3999afdSHuichao Cai 48606d63eb5SAaron Conole } 48706d63eb5SAaron Conole 48806d63eb5SAaron Conole return result; 48906d63eb5SAaron Conole } 49006d63eb5SAaron Conole 49106d63eb5SAaron Conole static struct unit_test_suite ipfrag_testsuite = { 49206d63eb5SAaron Conole .suite_name = "IP Frag Unit Test Suite", 49306d63eb5SAaron Conole .setup = testsuite_setup, 49406d63eb5SAaron Conole .teardown = testsuite_teardown, 49506d63eb5SAaron Conole .unit_test_cases = { 49606d63eb5SAaron Conole TEST_CASE_ST(ut_setup, ut_teardown, 49706d63eb5SAaron Conole test_ip_frag), 49806d63eb5SAaron Conole 49906d63eb5SAaron Conole TEST_CASES_END() /**< NULL terminate unit test array */ 50006d63eb5SAaron Conole } 50106d63eb5SAaron Conole }; 50206d63eb5SAaron Conole 50306d63eb5SAaron Conole static int 50406d63eb5SAaron Conole test_ipfrag(void) 50506d63eb5SAaron Conole { 50606d63eb5SAaron Conole rte_log_set_global_level(RTE_LOG_DEBUG); 50706d63eb5SAaron Conole rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG); 50806d63eb5SAaron Conole 50906d63eb5SAaron Conole return unit_test_suite_runner(&ipfrag_testsuite); 51006d63eb5SAaron Conole } 51106d63eb5SAaron Conole 5123c60274cSJie Zhou 513e0a8442cSBruce Richardson REGISTER_FAST_TEST(ipfrag_autotest, false, true, test_ipfrag); 514