1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <errno.h> 7 8 #include "test.h" 9 10 #include <rte_string_fns.h> 11 #include <rte_mbuf.h> 12 #include <rte_byteorder.h> 13 #include <rte_ip.h> 14 #include <rte_acl.h> 15 #include <rte_common.h> 16 #include <rte_table_acl.h> 17 #include <rte_flow.h> 18 #include <rte_flow_classify.h> 19 20 #include "packet_burst_generator.h" 21 #include "test_flow_classify.h" 22 23 24 #define FLOW_CLASSIFY_MAX_RULE_NUM 100 25 #define MAX_PKT_BURST 32 26 #define NB_SOCKETS 1 27 #define MEMPOOL_CACHE_SIZE 256 28 #define MBUF_SIZE 512 29 #define NB_MBUF 512 30 31 /* test UDP, TCP and SCTP packets */ 32 static struct rte_mempool *mbufpool[NB_SOCKETS]; 33 static struct rte_mbuf *bufs[MAX_PKT_BURST]; 34 35 static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { 36 /* first input field - always one byte long. */ 37 { 38 .type = RTE_ACL_FIELD_TYPE_BITMASK, 39 .size = sizeof(uint8_t), 40 .field_index = PROTO_FIELD_IPV4, 41 .input_index = PROTO_INPUT_IPV4, 42 .offset = sizeof(struct rte_ether_hdr) + 43 offsetof(struct rte_ipv4_hdr, next_proto_id), 44 }, 45 /* next input field (IPv4 source address) - 4 consecutive bytes. */ 46 { 47 /* rte_flow uses a bit mask for IPv4 addresses */ 48 .type = RTE_ACL_FIELD_TYPE_BITMASK, 49 .size = sizeof(uint32_t), 50 .field_index = SRC_FIELD_IPV4, 51 .input_index = SRC_INPUT_IPV4, 52 .offset = sizeof(struct rte_ether_hdr) + 53 offsetof(struct rte_ipv4_hdr, src_addr), 54 }, 55 /* next input field (IPv4 destination address) - 4 consecutive bytes. */ 56 { 57 /* rte_flow uses a bit mask for IPv4 addresses */ 58 .type = RTE_ACL_FIELD_TYPE_BITMASK, 59 .size = sizeof(uint32_t), 60 .field_index = DST_FIELD_IPV4, 61 .input_index = DST_INPUT_IPV4, 62 .offset = sizeof(struct rte_ether_hdr) + 63 offsetof(struct rte_ipv4_hdr, dst_addr), 64 }, 65 /* 66 * Next 2 fields (src & dst ports) form 4 consecutive bytes. 67 * They share the same input index. 68 */ 69 { 70 /* rte_flow uses a bit mask for protocol ports */ 71 .type = RTE_ACL_FIELD_TYPE_BITMASK, 72 .size = sizeof(uint16_t), 73 .field_index = SRCP_FIELD_IPV4, 74 .input_index = SRCP_DESTP_INPUT_IPV4, 75 .offset = sizeof(struct rte_ether_hdr) + 76 sizeof(struct rte_ipv4_hdr) + 77 offsetof(struct rte_tcp_hdr, src_port), 78 }, 79 { 80 /* rte_flow uses a bit mask for protocol ports */ 81 .type = RTE_ACL_FIELD_TYPE_BITMASK, 82 .size = sizeof(uint16_t), 83 .field_index = DSTP_FIELD_IPV4, 84 .input_index = SRCP_DESTP_INPUT_IPV4, 85 .offset = sizeof(struct rte_ether_hdr) + 86 sizeof(struct rte_ipv4_hdr) + 87 offsetof(struct rte_tcp_hdr, dst_port), 88 }, 89 }; 90 91 /* parameters for rte_flow_classify_validate and rte_flow_classify_create */ 92 93 /* test UDP pattern: 94 * "eth / ipv4 src spec 2.2.2.3 src mask 255.255.255.00 dst spec 2.2.2.7 95 * dst mask 255.255.255.00 / udp src is 32 dst is 33 / end" 96 */ 97 static struct rte_flow_item_ipv4 ipv4_udp_spec_1 = { 98 { 0, 0, 0, 0, 0, 0, IPPROTO_UDP, 0, 99 RTE_IPV4(2, 2, 2, 3), RTE_IPV4(2, 2, 2, 7)} 100 }; 101 static const struct rte_flow_item_ipv4 ipv4_mask_24 = { 102 .hdr = { 103 .next_proto_id = 0xff, 104 .src_addr = 0xffffff00, 105 .dst_addr = 0xffffff00, 106 }, 107 }; 108 static struct rte_flow_item_udp udp_spec_1 = { 109 { 32, 33, 0, 0 } 110 }; 111 112 static struct rte_flow_item eth_item = { RTE_FLOW_ITEM_TYPE_ETH, 113 0, 0, 0 }; 114 static struct rte_flow_item eth_item_bad = { -1, 0, 0, 0 }; 115 116 static struct rte_flow_item ipv4_udp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4, 117 &ipv4_udp_spec_1, 0, &ipv4_mask_24}; 118 static struct rte_flow_item ipv4_udp_item_bad = { RTE_FLOW_ITEM_TYPE_IPV4, 119 NULL, 0, NULL}; 120 121 static struct rte_flow_item udp_item_1 = { RTE_FLOW_ITEM_TYPE_UDP, 122 &udp_spec_1, 0, &rte_flow_item_udp_mask}; 123 static struct rte_flow_item udp_item_bad = { RTE_FLOW_ITEM_TYPE_UDP, 124 NULL, 0, NULL}; 125 126 static struct rte_flow_item end_item = { RTE_FLOW_ITEM_TYPE_END, 127 0, 0, 0 }; 128 static struct rte_flow_item end_item_bad = { -1, 0, 0, 0 }; 129 130 /* test TCP pattern: 131 * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8 132 * dst mask 255.255.255.00 / tcp src is 16 dst is 17 / end" 133 */ 134 static struct rte_flow_item_ipv4 ipv4_tcp_spec_1 = { 135 { 0, 0, 0, 0, 0, 0, IPPROTO_TCP, 0, 136 RTE_IPV4(1, 2, 3, 4), RTE_IPV4(5, 6, 7, 8)} 137 }; 138 139 static struct rte_flow_item_tcp tcp_spec_1 = { 140 { 16, 17, 0, 0, 0, 0, 0, 0, 0} 141 }; 142 143 static struct rte_flow_item ipv4_tcp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4, 144 &ipv4_tcp_spec_1, 0, &ipv4_mask_24}; 145 146 static struct rte_flow_item tcp_item_1 = { RTE_FLOW_ITEM_TYPE_TCP, 147 &tcp_spec_1, 0, &rte_flow_item_tcp_mask}; 148 149 /* test SCTP pattern: 150 * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8 151 * dst mask 255.255.255.00 / sctp src is 16 dst is 17/ end" 152 */ 153 static struct rte_flow_item_ipv4 ipv4_sctp_spec_1 = { 154 { 0, 0, 0, 0, 0, 0, IPPROTO_SCTP, 0, RTE_IPV4(11, 12, 13, 14), 155 RTE_IPV4(15, 16, 17, 18)} 156 }; 157 158 static struct rte_flow_item_sctp sctp_spec_1 = { 159 { 10, 11, 0, 0} 160 }; 161 162 static struct rte_flow_item ipv4_sctp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4, 163 &ipv4_sctp_spec_1, 0, &ipv4_mask_24}; 164 165 static struct rte_flow_item sctp_item_1 = { RTE_FLOW_ITEM_TYPE_SCTP, 166 &sctp_spec_1, 0, &rte_flow_item_sctp_mask}; 167 168 169 /* test actions: 170 * "actions count / end" 171 */ 172 static struct rte_flow_query_count count = { 173 .reset = 1, 174 .hits_set = 1, 175 .bytes_set = 1, 176 .hits = 0, 177 .bytes = 0, 178 }; 179 static struct rte_flow_action count_action = { RTE_FLOW_ACTION_TYPE_COUNT, 180 &count}; 181 static struct rte_flow_action count_action_bad = { -1, 0}; 182 183 static struct rte_flow_action end_action = { RTE_FLOW_ACTION_TYPE_END, 0}; 184 static struct rte_flow_action end_action_bad = { -1, 0}; 185 186 static struct rte_flow_action actions[2]; 187 188 /* test attributes */ 189 static struct rte_flow_attr attr; 190 191 /* test error */ 192 static struct rte_flow_error error; 193 194 /* test pattern */ 195 static struct rte_flow_item pattern[4]; 196 197 /* flow classify data for UDP burst */ 198 static struct rte_flow_classify_ipv4_5tuple_stats udp_ntuple_stats; 199 static struct rte_flow_classify_stats udp_classify_stats = { 200 .stats = (void *)&udp_ntuple_stats 201 }; 202 203 /* flow classify data for TCP burst */ 204 static struct rte_flow_classify_ipv4_5tuple_stats tcp_ntuple_stats; 205 static struct rte_flow_classify_stats tcp_classify_stats = { 206 .stats = (void *)&tcp_ntuple_stats 207 }; 208 209 /* flow classify data for SCTP burst */ 210 static struct rte_flow_classify_ipv4_5tuple_stats sctp_ntuple_stats; 211 static struct rte_flow_classify_stats sctp_classify_stats = { 212 .stats = (void *)&sctp_ntuple_stats 213 }; 214 215 struct flow_classifier_acl *cls; 216 217 struct flow_classifier_acl { 218 struct rte_flow_classifier *cls; 219 } __rte_cache_aligned; 220 221 /* 222 * test functions by passing invalid or 223 * non-workable parameters. 224 */ 225 static int 226 test_invalid_parameters(void) 227 { 228 struct rte_flow_classify_rule *rule; 229 int ret; 230 231 ret = rte_flow_classify_validate(NULL, NULL, NULL, NULL, NULL); 232 if (!ret) { 233 printf("Line %i: rte_flow_classify_validate", 234 __LINE__); 235 printf(" with NULL param should have failed!\n"); 236 return -1; 237 } 238 239 rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL, 240 NULL, NULL); 241 if (rule) { 242 printf("Line %i: flow_classifier_table_entry_add", __LINE__); 243 printf(" with NULL param should have failed!\n"); 244 return -1; 245 } 246 247 ret = rte_flow_classify_table_entry_delete(NULL, NULL); 248 if (!ret) { 249 printf("Line %i: rte_flow_classify_table_entry_delete", 250 __LINE__); 251 printf(" with NULL param should have failed!\n"); 252 return -1; 253 } 254 255 ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL); 256 if (!ret) { 257 printf("Line %i: flow_classifier_query", __LINE__); 258 printf(" with NULL param should have failed!\n"); 259 return -1; 260 } 261 262 rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL, 263 NULL, &error); 264 if (rule) { 265 printf("Line %i: flow_classify_table_entry_add ", __LINE__); 266 printf("with NULL param should have failed!\n"); 267 return -1; 268 } 269 270 ret = rte_flow_classify_table_entry_delete(NULL, NULL); 271 if (!ret) { 272 printf("Line %i: rte_flow_classify_table_entry_delete", 273 __LINE__); 274 printf("with NULL param should have failed!\n"); 275 return -1; 276 } 277 278 ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL); 279 if (!ret) { 280 printf("Line %i: flow_classifier_query", __LINE__); 281 printf(" with NULL param should have failed!\n"); 282 return -1; 283 } 284 return 0; 285 } 286 287 static int 288 test_valid_parameters(void) 289 { 290 struct rte_flow_classify_rule *rule; 291 int ret; 292 int key_found; 293 294 /* 295 * set up parameters for rte_flow_classify_validate, 296 * rte_flow_classify_table_entry_add and 297 * rte_flow_classify_table_entry_delete 298 */ 299 300 attr.ingress = 1; 301 attr.priority = 1; 302 pattern[0] = eth_item; 303 pattern[1] = ipv4_udp_item_1; 304 pattern[2] = udp_item_1; 305 pattern[3] = end_item; 306 actions[0] = count_action; 307 actions[1] = end_action; 308 309 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 310 actions, &error); 311 if (ret) { 312 printf("Line %i: rte_flow_classify_validate", 313 __LINE__); 314 printf(" should not have failed!\n"); 315 return -1; 316 } 317 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 318 actions, &key_found, &error); 319 320 if (!rule) { 321 printf("Line %i: flow_classify_table_entry_add", __LINE__); 322 printf(" should not have failed!\n"); 323 return -1; 324 } 325 326 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 327 if (ret) { 328 printf("Line %i: rte_flow_classify_table_entry_delete", 329 __LINE__); 330 printf(" should not have failed!\n"); 331 return -1; 332 } 333 return 0; 334 } 335 336 static int 337 test_invalid_patterns(void) 338 { 339 struct rte_flow_classify_rule *rule; 340 int ret; 341 int key_found; 342 343 /* 344 * set up parameters for rte_flow_classify_validate, 345 * rte_flow_classify_table_entry_add and 346 * rte_flow_classify_table_entry_delete 347 */ 348 349 attr.ingress = 1; 350 attr.priority = 1; 351 pattern[0] = eth_item_bad; 352 pattern[1] = ipv4_udp_item_1; 353 pattern[2] = udp_item_1; 354 pattern[3] = end_item; 355 actions[0] = count_action; 356 actions[1] = end_action; 357 358 pattern[0] = eth_item; 359 pattern[1] = ipv4_udp_item_bad; 360 361 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 362 actions, &error); 363 if (!ret) { 364 printf("Line %i: rte_flow_classify_validate", __LINE__); 365 printf(" should have failed!\n"); 366 return -1; 367 } 368 369 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 370 actions, &key_found, &error); 371 if (rule) { 372 printf("Line %i: flow_classify_table_entry_add", __LINE__); 373 printf(" should have failed!\n"); 374 return -1; 375 } 376 377 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 378 if (!ret) { 379 printf("Line %i: rte_flow_classify_table_entry_delete", 380 __LINE__); 381 printf(" should have failed!\n"); 382 return -1; 383 } 384 385 pattern[1] = ipv4_udp_item_1; 386 pattern[2] = udp_item_bad; 387 pattern[3] = end_item_bad; 388 389 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 390 actions, &error); 391 if (!ret) { 392 printf("Line %i: rte_flow_classify_validate", __LINE__); 393 printf(" should have failed!\n"); 394 return -1; 395 } 396 397 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 398 actions, &key_found, &error); 399 if (rule) { 400 printf("Line %i: flow_classify_table_entry_add", __LINE__); 401 printf(" should have failed!\n"); 402 return -1; 403 } 404 405 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 406 if (!ret) { 407 printf("Line %i: rte_flow_classify_table_entry_delete", 408 __LINE__); 409 printf(" should have failed!\n"); 410 return -1; 411 } 412 return 0; 413 } 414 415 static int 416 test_invalid_actions(void) 417 { 418 struct rte_flow_classify_rule *rule; 419 int ret; 420 int key_found; 421 422 /* 423 * set up parameters for rte_flow_classify_validate, 424 * rte_flow_classify_table_entry_add and 425 * rte_flow_classify_table_entry_delete 426 */ 427 428 attr.ingress = 1; 429 attr.priority = 1; 430 pattern[0] = eth_item; 431 pattern[1] = ipv4_udp_item_1; 432 pattern[2] = udp_item_1; 433 pattern[3] = end_item; 434 actions[0] = count_action_bad; 435 actions[1] = end_action; 436 437 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 438 actions, &error); 439 if (!ret) { 440 printf("Line %i: rte_flow_classify_validate", __LINE__); 441 printf(" should have failed!\n"); 442 return -1; 443 } 444 445 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 446 actions, &key_found, &error); 447 if (rule) { 448 printf("Line %i: flow_classify_table_entry_add", __LINE__); 449 printf(" should have failed!\n"); 450 return -1; 451 } 452 453 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 454 if (!ret) { 455 printf("Line %i: rte_flow_classify_table_entry_delete", 456 __LINE__); 457 printf(" should have failed!\n"); 458 return -1; 459 } 460 461 actions[0] = count_action; 462 actions[1] = end_action_bad; 463 464 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 465 actions, &error); 466 if (!ret) { 467 printf("Line %i: rte_flow_classify_validate", __LINE__); 468 printf(" should have failed!\n"); 469 return -1; 470 } 471 472 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 473 actions, &key_found, &error); 474 if (rule) { 475 printf("Line %i: flow_classify_table_entry_add", __LINE__); 476 printf(" should have failed!\n"); 477 return -1; 478 } 479 480 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 481 if (!ret) { 482 printf("Line %i: rte_flow_classify_table_entry_delete", 483 __LINE__); 484 printf("should have failed!\n"); 485 return -1; 486 } 487 return 0; 488 } 489 490 static int 491 init_ipv4_udp_traffic(struct rte_mempool *mp, 492 struct rte_mbuf **pkts_burst, uint32_t burst_size) 493 { 494 struct rte_ether_hdr pkt_eth_hdr; 495 struct rte_ipv4_hdr pkt_ipv4_hdr; 496 struct rte_udp_hdr pkt_udp_hdr; 497 uint32_t src_addr = IPV4_ADDR(2, 2, 2, 3); 498 uint32_t dst_addr = IPV4_ADDR(2, 2, 2, 7); 499 uint16_t src_port = 32; 500 uint16_t dst_port = 33; 501 uint16_t pktlen; 502 503 static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; 504 static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; 505 506 printf("Set up IPv4 UDP traffic\n"); 507 initialize_eth_header(&pkt_eth_hdr, 508 (struct rte_ether_addr *)src_mac, 509 (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0); 510 pktlen = (uint16_t)(sizeof(struct rte_ether_hdr)); 511 printf("ETH pktlen %u\n", pktlen); 512 513 pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, src_addr, dst_addr, 514 pktlen); 515 printf("ETH + IPv4 pktlen %u\n", pktlen); 516 517 pktlen = initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 518 pktlen); 519 printf("ETH + IPv4 + UDP pktlen %u\n\n", pktlen); 520 521 return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr, 522 0, &pkt_ipv4_hdr, 1, 523 &pkt_udp_hdr, burst_size, 524 PACKET_BURST_GEN_PKT_LEN, 1); 525 } 526 527 static int 528 init_ipv4_tcp_traffic(struct rte_mempool *mp, 529 struct rte_mbuf **pkts_burst, uint32_t burst_size) 530 { 531 struct rte_ether_hdr pkt_eth_hdr; 532 struct rte_ipv4_hdr pkt_ipv4_hdr; 533 struct rte_tcp_hdr pkt_tcp_hdr; 534 uint32_t src_addr = IPV4_ADDR(1, 2, 3, 4); 535 uint32_t dst_addr = IPV4_ADDR(5, 6, 7, 8); 536 uint16_t src_port = 16; 537 uint16_t dst_port = 17; 538 uint16_t pktlen; 539 540 static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; 541 static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; 542 543 printf("Set up IPv4 TCP traffic\n"); 544 initialize_eth_header(&pkt_eth_hdr, 545 (struct rte_ether_addr *)src_mac, 546 (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0); 547 pktlen = (uint16_t)(sizeof(struct rte_ether_hdr)); 548 printf("ETH pktlen %u\n", pktlen); 549 550 pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr, 551 dst_addr, pktlen, IPPROTO_TCP); 552 printf("ETH + IPv4 pktlen %u\n", pktlen); 553 554 pktlen = initialize_tcp_header(&pkt_tcp_hdr, src_port, dst_port, 555 pktlen); 556 printf("ETH + IPv4 + TCP pktlen %u\n\n", pktlen); 557 558 return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr, 559 0, &pkt_ipv4_hdr, 1, IPPROTO_TCP, 560 &pkt_tcp_hdr, burst_size, 561 PACKET_BURST_GEN_PKT_LEN, 1); 562 } 563 564 static int 565 init_ipv4_sctp_traffic(struct rte_mempool *mp, 566 struct rte_mbuf **pkts_burst, uint32_t burst_size) 567 { 568 struct rte_ether_hdr pkt_eth_hdr; 569 struct rte_ipv4_hdr pkt_ipv4_hdr; 570 struct rte_sctp_hdr pkt_sctp_hdr; 571 uint32_t src_addr = IPV4_ADDR(11, 12, 13, 14); 572 uint32_t dst_addr = IPV4_ADDR(15, 16, 17, 18); 573 uint16_t src_port = 10; 574 uint16_t dst_port = 11; 575 uint16_t pktlen; 576 577 static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; 578 static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; 579 580 printf("Set up IPv4 SCTP traffic\n"); 581 initialize_eth_header(&pkt_eth_hdr, 582 (struct rte_ether_addr *)src_mac, 583 (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0); 584 pktlen = (uint16_t)(sizeof(struct rte_ether_hdr)); 585 printf("ETH pktlen %u\n", pktlen); 586 587 pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr, 588 dst_addr, pktlen, IPPROTO_SCTP); 589 printf("ETH + IPv4 pktlen %u\n", pktlen); 590 591 pktlen = initialize_sctp_header(&pkt_sctp_hdr, src_port, dst_port, 592 pktlen); 593 printf("ETH + IPv4 + SCTP pktlen %u\n\n", pktlen); 594 595 return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr, 596 0, &pkt_ipv4_hdr, 1, IPPROTO_SCTP, 597 &pkt_sctp_hdr, burst_size, 598 PACKET_BURST_GEN_PKT_LEN, 1); 599 } 600 601 static int 602 init_mbufpool(void) 603 { 604 int socketid; 605 int ret = 0; 606 unsigned int lcore_id; 607 char s[64]; 608 609 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 610 if (rte_lcore_is_enabled(lcore_id) == 0) 611 continue; 612 613 socketid = rte_lcore_to_socket_id(lcore_id); 614 if (socketid >= NB_SOCKETS) { 615 printf( 616 "Socket %d of lcore %u is out of range %d\n", 617 socketid, lcore_id, NB_SOCKETS); 618 ret = -1; 619 break; 620 } 621 if (mbufpool[socketid] == NULL) { 622 snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 623 mbufpool[socketid] = 624 rte_pktmbuf_pool_create(s, NB_MBUF, 625 MEMPOOL_CACHE_SIZE, 0, MBUF_SIZE, 626 socketid); 627 if (mbufpool[socketid]) { 628 printf("Allocated mbuf pool on socket %d\n", 629 socketid); 630 } else { 631 printf("Cannot init mbuf pool on socket %d\n", 632 socketid); 633 ret = -ENOMEM; 634 break; 635 } 636 } 637 } 638 return ret; 639 } 640 641 static int 642 test_query_udp(void) 643 { 644 struct rte_flow_error error; 645 struct rte_flow_classify_rule *rule; 646 int ret; 647 int i; 648 int key_found; 649 650 ret = init_ipv4_udp_traffic(mbufpool[0], bufs, MAX_PKT_BURST); 651 if (ret != MAX_PKT_BURST) { 652 printf("Line %i: init_udp_ipv4_traffic has failed!\n", 653 __LINE__); 654 return -1; 655 } 656 657 for (i = 0; i < MAX_PKT_BURST; i++) 658 bufs[i]->packet_type = RTE_PTYPE_L3_IPV4; 659 660 /* 661 * set up parameters for rte_flow_classify_validate, 662 * rte_flow_classify_table_entry_add and 663 * rte_flow_classify_table_entry_delete 664 */ 665 666 attr.ingress = 1; 667 attr.priority = 1; 668 pattern[0] = eth_item; 669 pattern[1] = ipv4_udp_item_1; 670 pattern[2] = udp_item_1; 671 pattern[3] = end_item; 672 actions[0] = count_action; 673 actions[1] = end_action; 674 675 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 676 actions, &error); 677 if (ret) { 678 printf("Line %i: rte_flow_classify_validate", __LINE__); 679 printf(" should not have failed!\n"); 680 return -1; 681 } 682 683 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 684 actions, &key_found, &error); 685 if (!rule) { 686 printf("Line %i: flow_classify_table_entry_add", __LINE__); 687 printf(" should not have failed!\n"); 688 return -1; 689 } 690 691 ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST, 692 rule, &udp_classify_stats); 693 if (ret) { 694 printf("Line %i: flow_classifier_query", __LINE__); 695 printf(" should not have failed!\n"); 696 return -1; 697 } 698 699 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 700 if (ret) { 701 printf("Line %i: rte_flow_classify_table_entry_delete", 702 __LINE__); 703 printf(" should not have failed!\n"); 704 return -1; 705 } 706 return 0; 707 } 708 709 static int 710 test_query_tcp(void) 711 { 712 struct rte_flow_classify_rule *rule; 713 int ret; 714 int i; 715 int key_found; 716 717 ret = init_ipv4_tcp_traffic(mbufpool[0], bufs, MAX_PKT_BURST); 718 if (ret != MAX_PKT_BURST) { 719 printf("Line %i: init_ipv4_tcp_traffic has failed!\n", 720 __LINE__); 721 return -1; 722 } 723 724 for (i = 0; i < MAX_PKT_BURST; i++) 725 bufs[i]->packet_type = RTE_PTYPE_L3_IPV4; 726 727 /* 728 * set up parameters for rte_flow_classify_validate, 729 * rte_flow_classify_table_entry_add and 730 * rte_flow_classify_table_entry_delete 731 */ 732 733 attr.ingress = 1; 734 attr.priority = 1; 735 pattern[0] = eth_item; 736 pattern[1] = ipv4_tcp_item_1; 737 pattern[2] = tcp_item_1; 738 pattern[3] = end_item; 739 actions[0] = count_action; 740 actions[1] = end_action; 741 742 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 743 actions, &error); 744 if (ret) { 745 printf("Line %i: flow_classifier_query", __LINE__); 746 printf(" should not have failed!\n"); 747 return -1; 748 } 749 750 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 751 actions, &key_found, &error); 752 if (!rule) { 753 printf("Line %i: flow_classify_table_entry_add", __LINE__); 754 printf(" should not have failed!\n"); 755 return -1; 756 } 757 758 ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST, 759 rule, &tcp_classify_stats); 760 if (ret) { 761 printf("Line %i: flow_classifier_query", __LINE__); 762 printf(" should not have failed!\n"); 763 return -1; 764 } 765 766 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 767 if (ret) { 768 printf("Line %i: rte_flow_classify_table_entry_delete", 769 __LINE__); 770 printf(" should not have failed!\n"); 771 return -1; 772 } 773 return 0; 774 } 775 776 static int 777 test_query_sctp(void) 778 { 779 struct rte_flow_classify_rule *rule; 780 int ret; 781 int i; 782 int key_found; 783 784 ret = init_ipv4_sctp_traffic(mbufpool[0], bufs, MAX_PKT_BURST); 785 if (ret != MAX_PKT_BURST) { 786 printf("Line %i: init_ipv4_tcp_traffic has failed!\n", 787 __LINE__); 788 return -1; 789 } 790 791 for (i = 0; i < MAX_PKT_BURST; i++) 792 bufs[i]->packet_type = RTE_PTYPE_L3_IPV4; 793 794 /* 795 * set up parameters rte_flow_classify_validate, 796 * rte_flow_classify_table_entry_add and 797 * rte_flow_classify_table_entry_delete 798 */ 799 800 attr.ingress = 1; 801 attr.priority = 1; 802 pattern[0] = eth_item; 803 pattern[1] = ipv4_sctp_item_1; 804 pattern[2] = sctp_item_1; 805 pattern[3] = end_item; 806 actions[0] = count_action; 807 actions[1] = end_action; 808 809 ret = rte_flow_classify_validate(cls->cls, &attr, pattern, 810 actions, &error); 811 if (ret) { 812 printf("Line %i: flow_classifier_query", __LINE__); 813 printf(" should not have failed!\n"); 814 return -1; 815 } 816 817 rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern, 818 actions, &key_found, &error); 819 if (!rule) { 820 printf("Line %i: flow_classify_table_entry_add", __LINE__); 821 printf(" should not have failed!\n"); 822 return -1; 823 } 824 825 ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST, 826 rule, &sctp_classify_stats); 827 if (ret) { 828 printf("Line %i: flow_classifier_query", __LINE__); 829 printf(" should not have failed!\n"); 830 return -1; 831 } 832 833 ret = rte_flow_classify_table_entry_delete(cls->cls, rule); 834 if (ret) { 835 printf("Line %i: rte_flow_classify_table_entry_delete", 836 __LINE__); 837 printf(" should not have failed!\n"); 838 return -1; 839 } 840 return 0; 841 } 842 843 static int 844 test_flow_classify(void) 845 { 846 struct rte_table_acl_params table_acl_params; 847 struct rte_flow_classify_table_params cls_table_params; 848 struct rte_flow_classifier_params cls_params; 849 int ret; 850 uint32_t size; 851 852 /* Memory allocation */ 853 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl)); 854 cls = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); 855 856 cls_params.name = "flow_classifier"; 857 cls_params.socket_id = 0; 858 cls->cls = rte_flow_classifier_create(&cls_params); 859 860 /* initialise ACL table params */ 861 table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs); 862 table_acl_params.name = "table_acl_ipv4_5tuple"; 863 table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM; 864 memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs)); 865 866 /* initialise table create params */ 867 cls_table_params.ops = &rte_table_acl_ops; 868 cls_table_params.arg_create = &table_acl_params; 869 cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; 870 871 ret = rte_flow_classify_table_create(cls->cls, &cls_table_params); 872 if (ret) { 873 printf("Line %i: f_create has failed!\n", __LINE__); 874 rte_flow_classifier_free(cls->cls); 875 rte_free(cls); 876 return TEST_FAILED; 877 } 878 printf("Created table_acl for for IPv4 five tuple packets\n"); 879 880 ret = init_mbufpool(); 881 if (ret) { 882 printf("Line %i: init_mbufpool has failed!\n", __LINE__); 883 return TEST_FAILED; 884 } 885 886 if (test_invalid_parameters() < 0) 887 return TEST_FAILED; 888 if (test_valid_parameters() < 0) 889 return TEST_FAILED; 890 if (test_invalid_patterns() < 0) 891 return TEST_FAILED; 892 if (test_invalid_actions() < 0) 893 return TEST_FAILED; 894 if (test_query_udp() < 0) 895 return TEST_FAILED; 896 if (test_query_tcp() < 0) 897 return TEST_FAILED; 898 if (test_query_sctp() < 0) 899 return TEST_FAILED; 900 901 return TEST_SUCCESS; 902 } 903 904 REGISTER_TEST_COMMAND(flow_classify_autotest, test_flow_classify); 905