1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <rte_hexdump.h> 6 #include "test_table.h" 7 #include "test_table_acl.h" 8 9 #define IPv4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \ 10 (((b) & 0xff) << 16) | \ 11 (((c) & 0xff) << 8) | \ 12 ((d) & 0xff)) 13 14 /* 15 * Rule and trace formats definitions. 16 **/ 17 18 struct ipv4_5tuple { 19 uint8_t proto; 20 uint32_t ip_src; 21 uint32_t ip_dst; 22 uint16_t port_src; 23 uint16_t port_dst; 24 }; 25 26 enum { 27 PROTO_FIELD_IPV4, 28 SRC_FIELD_IPV4, 29 DST_FIELD_IPV4, 30 SRCP_FIELD_IPV4, 31 DSTP_FIELD_IPV4, 32 NUM_FIELDS_IPV4 33 }; 34 35 struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { 36 { 37 .type = RTE_ACL_FIELD_TYPE_BITMASK, 38 .size = sizeof(uint8_t), 39 .field_index = PROTO_FIELD_IPV4, 40 .input_index = PROTO_FIELD_IPV4, 41 .offset = offsetof(struct ipv4_5tuple, proto), 42 }, 43 { 44 .type = RTE_ACL_FIELD_TYPE_MASK, 45 .size = sizeof(uint32_t), 46 .field_index = SRC_FIELD_IPV4, 47 .input_index = SRC_FIELD_IPV4, 48 .offset = offsetof(struct ipv4_5tuple, ip_src), 49 }, 50 { 51 .type = RTE_ACL_FIELD_TYPE_MASK, 52 .size = sizeof(uint32_t), 53 .field_index = DST_FIELD_IPV4, 54 .input_index = DST_FIELD_IPV4, 55 .offset = offsetof(struct ipv4_5tuple, ip_dst), 56 }, 57 { 58 .type = RTE_ACL_FIELD_TYPE_RANGE, 59 .size = sizeof(uint16_t), 60 .field_index = SRCP_FIELD_IPV4, 61 .input_index = SRCP_FIELD_IPV4, 62 .offset = offsetof(struct ipv4_5tuple, port_src), 63 }, 64 { 65 .type = RTE_ACL_FIELD_TYPE_RANGE, 66 .size = sizeof(uint16_t), 67 .field_index = DSTP_FIELD_IPV4, 68 .input_index = SRCP_FIELD_IPV4, 69 .offset = offsetof(struct ipv4_5tuple, port_dst), 70 }, 71 }; 72 73 struct rte_table_acl_rule_add_params table_acl_IPv4_rule; 74 75 typedef int (*parse_5tuple)(char *text, 76 struct rte_table_acl_rule_add_params *rule); 77 78 /* 79 * The order of the fields in the rule string after the initial '@' 80 */ 81 enum { 82 CB_FLD_SRC_ADDR, 83 CB_FLD_DST_ADDR, 84 CB_FLD_SRC_PORT_RANGE, 85 CB_FLD_DST_PORT_RANGE, 86 CB_FLD_PROTO, 87 CB_FLD_NUM, 88 }; 89 90 91 #define GET_CB_FIELD(in, fd, base, lim, dlm) \ 92 do { \ 93 unsigned long val; \ 94 char *end; \ 95 \ 96 errno = 0; \ 97 val = strtoul((in), &end, (base)); \ 98 if (errno != 0 || end[0] != (dlm) || val > (lim)) \ 99 return -EINVAL; \ 100 (fd) = (typeof(fd)) val; \ 101 (in) = end + 1; \ 102 } while (0) 103 104 105 106 107 static int 108 parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) 109 { 110 uint8_t a, b, c, d, m; 111 112 GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); 113 GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); 114 GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); 115 GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); 116 GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); 117 118 addr[0] = IPv4(a, b, c, d); 119 mask_len[0] = m; 120 121 return 0; 122 } 123 124 static int 125 parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high) 126 { 127 uint16_t a, b; 128 129 GET_CB_FIELD(in, a, 0, UINT16_MAX, ':'); 130 GET_CB_FIELD(in, b, 0, UINT16_MAX, 0); 131 132 port_low[0] = a; 133 port_high[0] = b; 134 135 return 0; 136 } 137 138 static int 139 parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v) 140 { 141 int i, rc; 142 char *s, *sp, *in[CB_FLD_NUM]; 143 static const char *dlm = " \t\n"; 144 145 /* 146 ** Skip leading '@' 147 */ 148 if (strchr(str, '@') != str) 149 return -EINVAL; 150 151 s = str + 1; 152 153 /* 154 * Populate the 'in' array with the location of each 155 * field in the string we're parsing 156 */ 157 for (i = 0; i != DIM(in); i++) { 158 in[i] = strtok_r(s, dlm, &sp); 159 if (in[i] == NULL) 160 return -EINVAL; 161 s = NULL; 162 } 163 164 /* Parse x.x.x.x/x */ 165 rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], 166 &v->field_value[SRC_FIELD_IPV4].value.u32, 167 &v->field_value[SRC_FIELD_IPV4].mask_range.u32); 168 if (rc != 0) { 169 RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n", 170 in[CB_FLD_SRC_ADDR]); 171 return rc; 172 } 173 174 printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32, 175 v->field_value[SRC_FIELD_IPV4].mask_range.u32); 176 177 /* Parse x.x.x.x/x */ 178 rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], 179 &v->field_value[DST_FIELD_IPV4].value.u32, 180 &v->field_value[DST_FIELD_IPV4].mask_range.u32); 181 if (rc != 0) { 182 RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n", 183 in[CB_FLD_DST_ADDR]); 184 return rc; 185 } 186 187 printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32, 188 v->field_value[DST_FIELD_IPV4].mask_range.u32); 189 /* Parse n:n */ 190 rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE], 191 &v->field_value[SRCP_FIELD_IPV4].value.u16, 192 &v->field_value[SRCP_FIELD_IPV4].mask_range.u16); 193 if (rc != 0) { 194 RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n", 195 in[CB_FLD_SRC_PORT_RANGE]); 196 return rc; 197 } 198 199 printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16, 200 v->field_value[SRCP_FIELD_IPV4].mask_range.u16); 201 /* Parse n:n */ 202 rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE], 203 &v->field_value[DSTP_FIELD_IPV4].value.u16, 204 &v->field_value[DSTP_FIELD_IPV4].mask_range.u16); 205 if (rc != 0) { 206 RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n", 207 in[CB_FLD_DST_PORT_RANGE]); 208 return rc; 209 } 210 211 printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16, 212 v->field_value[DSTP_FIELD_IPV4].mask_range.u16); 213 /* parse 0/0xnn */ 214 GET_CB_FIELD(in[CB_FLD_PROTO], 215 v->field_value[PROTO_FIELD_IPV4].value.u8, 216 0, UINT8_MAX, '/'); 217 GET_CB_FIELD(in[CB_FLD_PROTO], 218 v->field_value[PROTO_FIELD_IPV4].mask_range.u8, 219 0, UINT8_MAX, 0); 220 221 printf("V=%u, mask=%u\n", 222 (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8, 223 v->field_value[PROTO_FIELD_IPV4].mask_range.u8); 224 return 0; 225 } 226 227 static int 228 parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v) 229 { 230 int i, rc; 231 char *s, *sp, *in[CB_FLD_NUM]; 232 static const char *dlm = " \t\n"; 233 234 /* 235 ** Skip leading '@' 236 */ 237 if (strchr(str, '@') != str) 238 return -EINVAL; 239 240 s = str + 1; 241 242 /* 243 * Populate the 'in' array with the location of each 244 * field in the string we're parsing 245 */ 246 for (i = 0; i != DIM(in); i++) { 247 in[i] = strtok_r(s, dlm, &sp); 248 if (in[i] == NULL) 249 return -EINVAL; 250 s = NULL; 251 } 252 253 /* Parse x.x.x.x/x */ 254 rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], 255 &v->field_value[SRC_FIELD_IPV4].value.u32, 256 &v->field_value[SRC_FIELD_IPV4].mask_range.u32); 257 if (rc != 0) { 258 RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n", 259 in[CB_FLD_SRC_ADDR]); 260 return rc; 261 } 262 263 printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32, 264 v->field_value[SRC_FIELD_IPV4].mask_range.u32); 265 266 /* Parse x.x.x.x/x */ 267 rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], 268 &v->field_value[DST_FIELD_IPV4].value.u32, 269 &v->field_value[DST_FIELD_IPV4].mask_range.u32); 270 if (rc != 0) { 271 RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n", 272 in[CB_FLD_DST_ADDR]); 273 return rc; 274 } 275 276 printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32, 277 v->field_value[DST_FIELD_IPV4].mask_range.u32); 278 /* Parse n:n */ 279 rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE], 280 &v->field_value[SRCP_FIELD_IPV4].value.u16, 281 &v->field_value[SRCP_FIELD_IPV4].mask_range.u16); 282 if (rc != 0) { 283 RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n", 284 in[CB_FLD_SRC_PORT_RANGE]); 285 return rc; 286 } 287 288 printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16, 289 v->field_value[SRCP_FIELD_IPV4].mask_range.u16); 290 /* Parse n:n */ 291 rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE], 292 &v->field_value[DSTP_FIELD_IPV4].value.u16, 293 &v->field_value[DSTP_FIELD_IPV4].mask_range.u16); 294 if (rc != 0) { 295 RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n", 296 in[CB_FLD_DST_PORT_RANGE]); 297 return rc; 298 } 299 300 printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16, 301 v->field_value[DSTP_FIELD_IPV4].mask_range.u16); 302 /* parse 0/0xnn */ 303 GET_CB_FIELD(in[CB_FLD_PROTO], 304 v->field_value[PROTO_FIELD_IPV4].value.u8, 305 0, UINT8_MAX, '/'); 306 GET_CB_FIELD(in[CB_FLD_PROTO], 307 v->field_value[PROTO_FIELD_IPV4].mask_range.u8, 308 0, UINT8_MAX, 0); 309 310 printf("V=%u, mask=%u\n", 311 (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8, 312 v->field_value[PROTO_FIELD_IPV4].mask_range.u8); 313 return 0; 314 } 315 316 /* 317 * The format for these rules DO NOT need the port ranges to be 318 * separated by ' : ', just ':'. It's a lot more readable and 319 * cleaner, IMO. 320 */ 321 char lines[][128] = { 322 "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */ 323 "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */ 324 "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */ 325 "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */ 326 "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */ 327 }; 328 329 char line[128]; 330 331 332 static int 333 setup_acl_pipeline(void) 334 { 335 int ret; 336 int i; 337 struct rte_pipeline_params pipeline_params = { 338 .name = "PIPELINE", 339 .socket_id = 0, 340 }; 341 uint32_t n; 342 struct rte_table_acl_rule_add_params rule_params; 343 struct rte_pipeline_table_acl_rule_delete_params *delete_params; 344 parse_5tuple parser; 345 char acl_name[64]; 346 347 /* Pipeline configuration */ 348 p = rte_pipeline_create(&pipeline_params); 349 if (p == NULL) { 350 RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n", 351 __func__); 352 goto fail; 353 } 354 355 /* Input port configuration */ 356 for (i = 0; i < N_PORTS; i++) { 357 struct rte_port_ring_reader_params port_ring_params = { 358 .ring = rings_rx[i], 359 }; 360 361 struct rte_pipeline_port_in_params port_params = { 362 .ops = &rte_port_ring_reader_ops, 363 .arg_create = (void *) &port_ring_params, 364 .f_action = NULL, 365 .burst_size = BURST_SIZE, 366 }; 367 368 /* Put in action for some ports */ 369 if (i) 370 port_params.f_action = port_in_action; 371 372 ret = rte_pipeline_port_in_create(p, &port_params, 373 &port_in_id[i]); 374 if (ret) { 375 rte_panic("Unable to configure input port %d, ret:%d\n", 376 i, ret); 377 goto fail; 378 } 379 } 380 381 /* output Port configuration */ 382 for (i = 0; i < N_PORTS; i++) { 383 struct rte_port_ring_writer_params port_ring_params = { 384 .ring = rings_tx[i], 385 .tx_burst_sz = BURST_SIZE, 386 }; 387 388 struct rte_pipeline_port_out_params port_params = { 389 .ops = &rte_port_ring_writer_ops, 390 .arg_create = (void *) &port_ring_params, 391 .f_action = NULL, 392 .arg_ah = NULL, 393 }; 394 395 396 if (rte_pipeline_port_out_create(p, &port_params, 397 &port_out_id[i])) { 398 rte_panic("Unable to configure output port %d\n", i); 399 goto fail; 400 } 401 } 402 403 /* Table configuration */ 404 for (i = 0; i < N_PORTS; i++) { 405 struct rte_pipeline_table_params table_params; 406 407 /* Set up defaults for stub */ 408 table_params.ops = &rte_table_stub_ops; 409 table_params.arg_create = NULL; 410 table_params.f_action_hit = action_handler_hit; 411 table_params.f_action_miss = NULL; 412 table_params.action_data_size = 0; 413 414 RTE_LOG(INFO, PIPELINE, "miss_action=%x\n", 415 table_entry_miss_action); 416 417 printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs), 418 RTE_ACL_RULE_SZ(DIM(ipv4_defs))); 419 420 struct rte_table_acl_params acl_params; 421 422 acl_params.n_rules = 1 << 5; 423 acl_params.n_rule_fields = DIM(ipv4_defs); 424 snprintf(acl_name, sizeof(acl_name), "ACL%d", i); 425 acl_params.name = acl_name; 426 memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs)); 427 428 table_params.ops = &rte_table_acl_ops; 429 table_params.arg_create = &acl_params; 430 431 if (rte_pipeline_table_create(p, &table_params, &table_id[i])) { 432 rte_panic("Unable to configure table %u\n", i); 433 goto fail; 434 } 435 436 if (connect_miss_action_to_table) { 437 if (rte_pipeline_table_create(p, &table_params, 438 &table_id[i+2])) { 439 rte_panic("Unable to configure table %u\n", i); 440 goto fail; 441 } 442 } 443 } 444 445 for (i = 0; i < N_PORTS; i++) { 446 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], 447 table_id[i])) { 448 rte_panic("Unable to connect input port %u to " 449 "table %u\n", 450 port_in_id[i], table_id[i]); 451 goto fail; 452 } 453 } 454 455 /* Add bulk entries to tables */ 456 for (i = 0; i < N_PORTS; i++) { 457 struct rte_table_acl_rule_add_params keys[5]; 458 struct rte_pipeline_table_entry entries[5]; 459 struct rte_table_acl_rule_add_params *key_array[5]; 460 struct rte_pipeline_table_entry *table_entries[5]; 461 int key_found[5]; 462 struct rte_pipeline_table_entry *table_entries_ptr[5]; 463 struct rte_pipeline_table_entry entries_ptr[5]; 464 465 parser = parse_cb_ipv4_rule; 466 for (n = 0; n < 5; n++) { 467 memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params)); 468 key_array[n] = &keys[n]; 469 470 snprintf(line, sizeof(line), "%s", lines[n]); 471 printf("PARSING [%s]\n", line); 472 473 ret = parser(line, &keys[n]); 474 if (ret != 0) { 475 RTE_LOG(ERR, PIPELINE, 476 "line %u: parse_cb_ipv4vlan_rule" 477 " failed, error code: %d (%s)\n", 478 n, ret, strerror(-ret)); 479 return ret; 480 } 481 482 keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1; 483 484 entries[n].action = RTE_PIPELINE_ACTION_PORT; 485 entries[n].port_id = port_out_id[i^1]; 486 table_entries[n] = &entries[n]; 487 table_entries_ptr[n] = &entries_ptr[n]; 488 } 489 490 ret = rte_pipeline_table_entry_add_bulk(p, table_id[i], 491 (void **)key_array, table_entries, 5, key_found, table_entries_ptr); 492 if (ret < 0) { 493 rte_panic("Add entry bulk to table %u failed (%d)\n", 494 table_id[i], ret); 495 goto fail; 496 } 497 } 498 499 /* Delete bulk entries from tables */ 500 for (i = 0; i < N_PORTS; i++) { 501 struct rte_table_acl_rule_delete_params keys[5]; 502 struct rte_table_acl_rule_delete_params *key_array[5]; 503 struct rte_pipeline_table_entry *table_entries[5]; 504 int key_found[5]; 505 506 memset(table_entries, 0, sizeof(table_entries)); 507 508 for (n = 0; n < 5; n++) { 509 memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params)); 510 key_array[n] = &keys[n]; 511 512 snprintf(line, sizeof(line), "%s", lines[n]); 513 printf("PARSING [%s]\n", line); 514 515 ret = parse_cb_ipv4_rule_del(line, &keys[n]); 516 if (ret != 0) { 517 RTE_LOG(ERR, PIPELINE, 518 "line %u: parse_cb_ipv4vlan_rule" 519 " failed, error code: %d (%s)\n", 520 n, ret, strerror(-ret)); 521 return ret; 522 } 523 } 524 525 ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i], 526 (void **)key_array, 5, key_found, table_entries); 527 if (ret < 0) { 528 rte_panic("Delete bulk entries from table %u failed (%d)\n", 529 table_id[i], ret); 530 goto fail; 531 } else 532 printf("Bulk deleted rules.\n"); 533 } 534 535 /* Add entries to tables */ 536 for (i = 0; i < N_PORTS; i++) { 537 struct rte_pipeline_table_entry table_entry = { 538 .action = RTE_PIPELINE_ACTION_PORT, 539 {.port_id = port_out_id[i^1]}, 540 }; 541 int key_found; 542 struct rte_pipeline_table_entry *entry_ptr; 543 544 memset(&rule_params, 0, sizeof(rule_params)); 545 parser = parse_cb_ipv4_rule; 546 547 for (n = 1; n <= 5; n++) { 548 snprintf(line, sizeof(line), "%s", lines[n-1]); 549 printf("PARSING [%s]\n", line); 550 551 ret = parser(line, &rule_params); 552 if (ret != 0) { 553 RTE_LOG(ERR, PIPELINE, 554 "line %u: parse_cb_ipv4vlan_rule" 555 " failed, error code: %d (%s)\n", 556 n, ret, strerror(-ret)); 557 return ret; 558 } 559 560 rule_params.priority = RTE_ACL_MAX_PRIORITY - n; 561 562 ret = rte_pipeline_table_entry_add(p, table_id[i], 563 &rule_params, 564 &table_entry, &key_found, &entry_ptr); 565 if (ret < 0) { 566 rte_panic("Add entry to table %u failed (%d)\n", 567 table_id[i], ret); 568 goto fail; 569 } 570 } 571 572 /* delete a few rules */ 573 for (n = 2; n <= 3; n++) { 574 snprintf(line, sizeof(line), "%s", lines[n-1]); 575 printf("PARSING [%s]\n", line); 576 577 ret = parser(line, &rule_params); 578 if (ret != 0) { 579 RTE_LOG(ERR, PIPELINE, "line %u: parse rule " 580 " failed, error code: %d (%s)\n", 581 n, ret, strerror(-ret)); 582 return ret; 583 } 584 585 delete_params = (struct 586 rte_pipeline_table_acl_rule_delete_params *) 587 &(rule_params.field_value[0]); 588 ret = rte_pipeline_table_entry_delete(p, table_id[i], 589 delete_params, &key_found, NULL); 590 if (ret < 0) { 591 rte_panic("Add entry to table %u failed (%d)\n", 592 table_id[i], ret); 593 goto fail; 594 } else 595 printf("Deleted Rule.\n"); 596 } 597 598 599 /* Try to add duplicates */ 600 for (n = 1; n <= 5; n++) { 601 snprintf(line, sizeof(line), "%s", lines[n-1]); 602 printf("PARSING [%s]\n", line); 603 604 ret = parser(line, &rule_params); 605 if (ret != 0) { 606 RTE_LOG(ERR, PIPELINE, "line %u: parse rule" 607 " failed, error code: %d (%s)\n", 608 n, ret, strerror(-ret)); 609 return ret; 610 } 611 612 rule_params.priority = RTE_ACL_MAX_PRIORITY - n; 613 614 ret = rte_pipeline_table_entry_add(p, table_id[i], 615 &rule_params, 616 &table_entry, &key_found, &entry_ptr); 617 if (ret < 0) { 618 rte_panic("Add entry to table %u failed (%d)\n", 619 table_id[i], ret); 620 goto fail; 621 } 622 } 623 } 624 625 /* Enable input ports */ 626 for (i = 0; i < N_PORTS ; i++) 627 if (rte_pipeline_port_in_enable(p, port_in_id[i])) 628 rte_panic("Unable to enable input port %u\n", 629 port_in_id[i]); 630 631 /* Check pipeline consistency */ 632 if (rte_pipeline_check(p) < 0) { 633 rte_panic("Pipeline consistency check failed\n"); 634 goto fail; 635 } 636 637 return 0; 638 fail: 639 640 return -1; 641 } 642 643 static int 644 test_pipeline_single_filter(int expected_count) 645 { 646 int i, j, ret, tx_count; 647 struct ipv4_5tuple five_tuple; 648 649 /* Allocate a few mbufs and manually insert into the rings. */ 650 for (i = 0; i < N_PORTS; i++) { 651 for (j = 0; j < 8; j++) { 652 struct rte_mbuf *mbuf; 653 654 mbuf = rte_pktmbuf_alloc(pool); 655 if (mbuf == NULL) 656 /* this will cause test failure after cleanup 657 * of already enqueued mbufs, as the mbuf 658 * counts won't match */ 659 break; 660 memset(rte_pktmbuf_mtod(mbuf, char *), 0x00, 661 sizeof(struct ipv4_5tuple)); 662 663 five_tuple.proto = j; 664 five_tuple.ip_src = rte_bswap32(IPv4(192, 168, j, 1)); 665 five_tuple.ip_dst = rte_bswap32(IPv4(10, 4, j, 1)); 666 five_tuple.port_src = rte_bswap16(100 + j); 667 five_tuple.port_dst = rte_bswap16(200 + j); 668 669 memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple, 670 sizeof(struct ipv4_5tuple)); 671 RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n", 672 __func__, i); 673 rte_ring_enqueue(rings_rx[i], mbuf); 674 } 675 } 676 677 /* Run pipeline once */ 678 for (i = 0; i< N_PORTS; i++) 679 rte_pipeline_run(p); 680 681 rte_pipeline_flush(p); 682 683 tx_count = 0; 684 685 for (i = 0; i < N_PORTS; i++) { 686 void *objs[RING_TX_SIZE]; 687 struct rte_mbuf *mbuf; 688 689 ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL); 690 if (ret <= 0) { 691 printf("Got no objects from ring %d - error code %d\n", 692 i, ret); 693 } else { 694 printf("Got %d object(s) from ring %d!\n", ret, i); 695 for (j = 0; j < ret; j++) { 696 mbuf = objs[j]; 697 rte_hexdump(stdout, "mbuf", 698 rte_pktmbuf_mtod(mbuf, char *), 64); 699 rte_pktmbuf_free(mbuf); 700 } 701 tx_count += ret; 702 } 703 } 704 705 if (tx_count != expected_count) { 706 RTE_LOG(INFO, PIPELINE, 707 "%s: Unexpected packets for ACL test, " 708 "expected %d, got %d\n", 709 __func__, expected_count, tx_count); 710 goto fail; 711 } 712 713 rte_pipeline_free(p); 714 715 return 0; 716 fail: 717 return -1; 718 719 } 720 721 int 722 test_table_acl(void) 723 { 724 725 726 override_hit_mask = 0xFF; /* All packets are a hit */ 727 728 setup_acl_pipeline(); 729 if (test_pipeline_single_filter(10) < 0) 730 return -1; 731 732 return 0; 733 } 734