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