1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdint.h> 8 #include <inttypes.h> 9 #include <sys/types.h> 10 #include <string.h> 11 #include <sys/queue.h> 12 #include <stdarg.h> 13 #include <errno.h> 14 #include <getopt.h> 15 16 #include <rte_common.h> 17 #include <rte_byteorder.h> 18 #include <rte_log.h> 19 #include <rte_memory.h> 20 #include <rte_memcpy.h> 21 #include <rte_eal.h> 22 #include <rte_launch.h> 23 #include <rte_cycles.h> 24 #include <rte_prefetch.h> 25 #include <rte_lcore.h> 26 #include <rte_per_lcore.h> 27 #include <rte_branch_prediction.h> 28 #include <rte_interrupts.h> 29 #include <rte_random.h> 30 #include <rte_debug.h> 31 #include <rte_ether.h> 32 #include <rte_ethdev.h> 33 #include <rte_mempool.h> 34 #include <rte_mbuf.h> 35 #include <rte_ip.h> 36 #include <rte_tcp.h> 37 #include <rte_udp.h> 38 #include <rte_string_fns.h> 39 #include <rte_acl.h> 40 41 #include <cmdline_parse.h> 42 #include <cmdline_parse_etheraddr.h> 43 44 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG 45 #define L3FWDACL_DEBUG 46 #endif 47 #define DO_RFC_1812_CHECKS 48 49 #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 50 51 #define MAX_JUMBO_PKT_LEN 9600 52 53 #define MEMPOOL_CACHE_SIZE 256 54 55 /* 56 * This expression is used to calculate the number of mbufs needed 57 * depending on user input, taking into account memory for rx and tx hardware 58 * rings, cache per lcore and mtable per port per lcore. 59 * RTE_MAX is used to ensure that NB_MBUF never goes below a 60 * minimum value of 8192 61 */ 62 63 #define NB_MBUF RTE_MAX(\ 64 (nb_ports * nb_rx_queue * nb_rxd + \ 65 nb_ports * nb_lcores * MAX_PKT_BURST + \ 66 nb_ports * n_tx_queue * nb_txd + \ 67 nb_lcores * MEMPOOL_CACHE_SIZE), \ 68 (unsigned)8192) 69 70 #define MAX_PKT_BURST 32 71 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 72 73 #define NB_SOCKETS 8 74 75 /* Configure how many packets ahead to prefetch, when reading packets */ 76 #define PREFETCH_OFFSET 3 77 78 /* 79 * Configurable number of RX/TX ring descriptors 80 */ 81 #define RTE_TEST_RX_DESC_DEFAULT 1024 82 #define RTE_TEST_TX_DESC_DEFAULT 1024 83 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 84 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 85 86 /* mask of enabled ports */ 87 static uint32_t enabled_port_mask; 88 static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */ 89 static int numa_on = 1; /**< NUMA is enabled by default. */ 90 91 struct lcore_rx_queue { 92 uint16_t port_id; 93 uint8_t queue_id; 94 } __rte_cache_aligned; 95 96 #define MAX_RX_QUEUE_PER_LCORE 16 97 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 98 #define MAX_RX_QUEUE_PER_PORT 128 99 100 #define MAX_LCORE_PARAMS 1024 101 struct lcore_params { 102 uint16_t port_id; 103 uint8_t queue_id; 104 uint8_t lcore_id; 105 } __rte_cache_aligned; 106 107 static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 108 static struct lcore_params lcore_params_array_default[] = { 109 {0, 0, 2}, 110 {0, 1, 2}, 111 {0, 2, 2}, 112 {1, 0, 2}, 113 {1, 1, 2}, 114 {1, 2, 2}, 115 {2, 0, 2}, 116 {3, 0, 3}, 117 {3, 1, 3}, 118 }; 119 120 static struct lcore_params *lcore_params = lcore_params_array_default; 121 static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / 122 sizeof(lcore_params_array_default[0]); 123 124 static struct rte_eth_conf port_conf = { 125 .rxmode = { 126 .mq_mode = RTE_ETH_MQ_RX_RSS, 127 .split_hdr_size = 0, 128 .offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM, 129 }, 130 .rx_adv_conf = { 131 .rss_conf = { 132 .rss_key = NULL, 133 .rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | 134 RTE_ETH_RSS_TCP | RTE_ETH_RSS_SCTP, 135 }, 136 }, 137 .txmode = { 138 .mq_mode = RTE_ETH_MQ_TX_NONE, 139 }, 140 }; 141 142 static uint32_t max_pkt_len; 143 144 static struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; 145 146 /* ethernet addresses of ports */ 147 static struct rte_ether_hdr port_l2hdr[RTE_MAX_ETHPORTS]; 148 149 static const struct { 150 const char *name; 151 enum rte_acl_classify_alg alg; 152 } acl_alg[] = { 153 { 154 .name = "scalar", 155 .alg = RTE_ACL_CLASSIFY_SCALAR, 156 }, 157 { 158 .name = "sse", 159 .alg = RTE_ACL_CLASSIFY_SSE, 160 }, 161 { 162 .name = "avx2", 163 .alg = RTE_ACL_CLASSIFY_AVX2, 164 }, 165 { 166 .name = "neon", 167 .alg = RTE_ACL_CLASSIFY_NEON, 168 }, 169 { 170 .name = "altivec", 171 .alg = RTE_ACL_CLASSIFY_ALTIVEC, 172 }, 173 { 174 .name = "avx512x16", 175 .alg = RTE_ACL_CLASSIFY_AVX512X16, 176 }, 177 { 178 .name = "avx512x32", 179 .alg = RTE_ACL_CLASSIFY_AVX512X32, 180 }, 181 }; 182 183 /***********************start of ACL part******************************/ 184 #ifdef DO_RFC_1812_CHECKS 185 static inline int 186 is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len); 187 #endif 188 static inline void 189 send_single_packet(struct rte_mbuf *m, uint16_t port); 190 191 #define MAX_ACL_RULE_NUM 100000 192 #define DEFAULT_MAX_CATEGORIES 1 193 #define L3FWD_ACL_IPV4_NAME "l3fwd-acl-ipv4" 194 #define L3FWD_ACL_IPV6_NAME "l3fwd-acl-ipv6" 195 #define ACL_LEAD_CHAR ('@') 196 #define ROUTE_LEAD_CHAR ('R') 197 #define COMMENT_LEAD_CHAR ('#') 198 199 enum { 200 #define OPT_CONFIG "config" 201 OPT_CONFIG_NUM = 256, 202 #define OPT_NONUMA "no-numa" 203 OPT_NONUMA_NUM, 204 #define OPT_MAX_PKT_LEN "max-pkt-len" 205 OPT_MAX_PKT_LEN_NUM, 206 #define OPT_RULE_IPV4 "rule_ipv4" 207 OPT_RULE_IPV4_NUM, 208 #define OPT_RULE_IPV6 "rule_ipv6" 209 OPT_RULE_IPV6_NUM, 210 #define OPT_ALG "alg" 211 OPT_ALG_NUM, 212 #define OPT_ETH_DEST "eth-dest" 213 OPT_ETH_DEST_NUM, 214 }; 215 216 #define ACL_DENY_SIGNATURE 0xf0000000 217 #define RTE_LOGTYPE_L3FWDACL RTE_LOGTYPE_USER3 218 #define acl_log(format, ...) RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__) 219 #define uint32_t_to_char(ip, a, b, c, d) do {\ 220 *a = (unsigned char)(ip >> 24 & 0xff);\ 221 *b = (unsigned char)(ip >> 16 & 0xff);\ 222 *c = (unsigned char)(ip >> 8 & 0xff);\ 223 *d = (unsigned char)(ip & 0xff);\ 224 } while (0) 225 #define OFF_ETHHEAD (sizeof(struct rte_ether_hdr)) 226 #define OFF_IPV42PROTO (offsetof(struct rte_ipv4_hdr, next_proto_id)) 227 #define OFF_IPV62PROTO (offsetof(struct rte_ipv6_hdr, proto)) 228 #define MBUF_IPV4_2PROTO(m) \ 229 rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO) 230 #define MBUF_IPV6_2PROTO(m) \ 231 rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO) 232 233 #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ 234 unsigned long val; \ 235 char *end; \ 236 errno = 0; \ 237 val = strtoul((in), &end, (base)); \ 238 if (errno != 0 || end[0] != (dlm) || val > (lim)) \ 239 return -EINVAL; \ 240 (fd) = (typeof(fd))val; \ 241 (in) = end + 1; \ 242 } while (0) 243 244 /* 245 * ACL rules should have higher priorities than route ones to ensure ACL rule 246 * always be found when input packets have multi-matches in the database. 247 * A exception case is performance measure, which can define route rules with 248 * higher priority and route rules will always be returned in each lookup. 249 * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to 250 * RTE_ACL_MAX_PRIORITY for route entries in performance measure 251 */ 252 #define ACL_RULE_PRIORITY_MAX 0x10000000 253 254 /* 255 * Forward port info save in ACL lib starts from 1 256 * since ACL assume 0 is invalid. 257 * So, need add 1 when saving and minus 1 when forwarding packets. 258 */ 259 #define FWD_PORT_SHIFT 1 260 261 /* 262 * Rule and trace formats definitions. 263 */ 264 265 enum { 266 PROTO_FIELD_IPV4, 267 SRC_FIELD_IPV4, 268 DST_FIELD_IPV4, 269 SRCP_FIELD_IPV4, 270 DSTP_FIELD_IPV4, 271 NUM_FIELDS_IPV4 272 }; 273 274 /* 275 * That effectively defines order of IPV4VLAN classifications: 276 * - PROTO 277 * - VLAN (TAG and DOMAIN) 278 * - SRC IP ADDRESS 279 * - DST IP ADDRESS 280 * - PORTS (SRC and DST) 281 */ 282 enum { 283 RTE_ACL_IPV4VLAN_PROTO, 284 RTE_ACL_IPV4VLAN_VLAN, 285 RTE_ACL_IPV4VLAN_SRC, 286 RTE_ACL_IPV4VLAN_DST, 287 RTE_ACL_IPV4VLAN_PORTS, 288 RTE_ACL_IPV4VLAN_NUM 289 }; 290 291 struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { 292 { 293 .type = RTE_ACL_FIELD_TYPE_BITMASK, 294 .size = sizeof(uint8_t), 295 .field_index = PROTO_FIELD_IPV4, 296 .input_index = RTE_ACL_IPV4VLAN_PROTO, 297 .offset = 0, 298 }, 299 { 300 .type = RTE_ACL_FIELD_TYPE_MASK, 301 .size = sizeof(uint32_t), 302 .field_index = SRC_FIELD_IPV4, 303 .input_index = RTE_ACL_IPV4VLAN_SRC, 304 .offset = offsetof(struct rte_ipv4_hdr, src_addr) - 305 offsetof(struct rte_ipv4_hdr, next_proto_id), 306 }, 307 { 308 .type = RTE_ACL_FIELD_TYPE_MASK, 309 .size = sizeof(uint32_t), 310 .field_index = DST_FIELD_IPV4, 311 .input_index = RTE_ACL_IPV4VLAN_DST, 312 .offset = offsetof(struct rte_ipv4_hdr, dst_addr) - 313 offsetof(struct rte_ipv4_hdr, next_proto_id), 314 }, 315 { 316 .type = RTE_ACL_FIELD_TYPE_RANGE, 317 .size = sizeof(uint16_t), 318 .field_index = SRCP_FIELD_IPV4, 319 .input_index = RTE_ACL_IPV4VLAN_PORTS, 320 .offset = sizeof(struct rte_ipv4_hdr) - 321 offsetof(struct rte_ipv4_hdr, next_proto_id), 322 }, 323 { 324 .type = RTE_ACL_FIELD_TYPE_RANGE, 325 .size = sizeof(uint16_t), 326 .field_index = DSTP_FIELD_IPV4, 327 .input_index = RTE_ACL_IPV4VLAN_PORTS, 328 .offset = sizeof(struct rte_ipv4_hdr) - 329 offsetof(struct rte_ipv4_hdr, next_proto_id) + 330 sizeof(uint16_t), 331 }, 332 }; 333 334 #define IPV6_ADDR_LEN 16 335 #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) 336 #define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) 337 338 enum { 339 PROTO_FIELD_IPV6, 340 SRC1_FIELD_IPV6, 341 SRC2_FIELD_IPV6, 342 SRC3_FIELD_IPV6, 343 SRC4_FIELD_IPV6, 344 DST1_FIELD_IPV6, 345 DST2_FIELD_IPV6, 346 DST3_FIELD_IPV6, 347 DST4_FIELD_IPV6, 348 SRCP_FIELD_IPV6, 349 DSTP_FIELD_IPV6, 350 NUM_FIELDS_IPV6 351 }; 352 353 struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { 354 { 355 .type = RTE_ACL_FIELD_TYPE_BITMASK, 356 .size = sizeof(uint8_t), 357 .field_index = PROTO_FIELD_IPV6, 358 .input_index = PROTO_FIELD_IPV6, 359 .offset = 0, 360 }, 361 { 362 .type = RTE_ACL_FIELD_TYPE_MASK, 363 .size = sizeof(uint32_t), 364 .field_index = SRC1_FIELD_IPV6, 365 .input_index = SRC1_FIELD_IPV6, 366 .offset = offsetof(struct rte_ipv6_hdr, src_addr) - 367 offsetof(struct rte_ipv6_hdr, proto), 368 }, 369 { 370 .type = RTE_ACL_FIELD_TYPE_MASK, 371 .size = sizeof(uint32_t), 372 .field_index = SRC2_FIELD_IPV6, 373 .input_index = SRC2_FIELD_IPV6, 374 .offset = offsetof(struct rte_ipv6_hdr, src_addr) - 375 offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t), 376 }, 377 { 378 .type = RTE_ACL_FIELD_TYPE_MASK, 379 .size = sizeof(uint32_t), 380 .field_index = SRC3_FIELD_IPV6, 381 .input_index = SRC3_FIELD_IPV6, 382 .offset = offsetof(struct rte_ipv6_hdr, src_addr) - 383 offsetof(struct rte_ipv6_hdr, proto) + 384 2 * sizeof(uint32_t), 385 }, 386 { 387 .type = RTE_ACL_FIELD_TYPE_MASK, 388 .size = sizeof(uint32_t), 389 .field_index = SRC4_FIELD_IPV6, 390 .input_index = SRC4_FIELD_IPV6, 391 .offset = offsetof(struct rte_ipv6_hdr, src_addr) - 392 offsetof(struct rte_ipv6_hdr, proto) + 393 3 * sizeof(uint32_t), 394 }, 395 { 396 .type = RTE_ACL_FIELD_TYPE_MASK, 397 .size = sizeof(uint32_t), 398 .field_index = DST1_FIELD_IPV6, 399 .input_index = DST1_FIELD_IPV6, 400 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) 401 - offsetof(struct rte_ipv6_hdr, proto), 402 }, 403 { 404 .type = RTE_ACL_FIELD_TYPE_MASK, 405 .size = sizeof(uint32_t), 406 .field_index = DST2_FIELD_IPV6, 407 .input_index = DST2_FIELD_IPV6, 408 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) - 409 offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t), 410 }, 411 { 412 .type = RTE_ACL_FIELD_TYPE_MASK, 413 .size = sizeof(uint32_t), 414 .field_index = DST3_FIELD_IPV6, 415 .input_index = DST3_FIELD_IPV6, 416 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) - 417 offsetof(struct rte_ipv6_hdr, proto) + 418 2 * sizeof(uint32_t), 419 }, 420 { 421 .type = RTE_ACL_FIELD_TYPE_MASK, 422 .size = sizeof(uint32_t), 423 .field_index = DST4_FIELD_IPV6, 424 .input_index = DST4_FIELD_IPV6, 425 .offset = offsetof(struct rte_ipv6_hdr, dst_addr) - 426 offsetof(struct rte_ipv6_hdr, proto) + 427 3 * sizeof(uint32_t), 428 }, 429 { 430 .type = RTE_ACL_FIELD_TYPE_RANGE, 431 .size = sizeof(uint16_t), 432 .field_index = SRCP_FIELD_IPV6, 433 .input_index = SRCP_FIELD_IPV6, 434 .offset = sizeof(struct rte_ipv6_hdr) - 435 offsetof(struct rte_ipv6_hdr, proto), 436 }, 437 { 438 .type = RTE_ACL_FIELD_TYPE_RANGE, 439 .size = sizeof(uint16_t), 440 .field_index = DSTP_FIELD_IPV6, 441 .input_index = SRCP_FIELD_IPV6, 442 .offset = sizeof(struct rte_ipv6_hdr) - 443 offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint16_t), 444 }, 445 }; 446 447 enum { 448 CB_FLD_SRC_ADDR, 449 CB_FLD_DST_ADDR, 450 CB_FLD_SRC_PORT_LOW, 451 CB_FLD_SRC_PORT_DLM, 452 CB_FLD_SRC_PORT_HIGH, 453 CB_FLD_DST_PORT_LOW, 454 CB_FLD_DST_PORT_DLM, 455 CB_FLD_DST_PORT_HIGH, 456 CB_FLD_PROTO, 457 CB_FLD_USERDATA, 458 CB_FLD_NUM, 459 }; 460 461 RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs)); 462 RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs)); 463 464 struct acl_search_t { 465 const uint8_t *data_ipv4[MAX_PKT_BURST]; 466 struct rte_mbuf *m_ipv4[MAX_PKT_BURST]; 467 uint32_t res_ipv4[MAX_PKT_BURST]; 468 int num_ipv4; 469 470 const uint8_t *data_ipv6[MAX_PKT_BURST]; 471 struct rte_mbuf *m_ipv6[MAX_PKT_BURST]; 472 uint32_t res_ipv6[MAX_PKT_BURST]; 473 int num_ipv6; 474 }; 475 476 static struct { 477 char mapped[NB_SOCKETS]; 478 struct rte_acl_ctx *acx_ipv4[NB_SOCKETS]; 479 struct rte_acl_ctx *acx_ipv6[NB_SOCKETS]; 480 #ifdef L3FWDACL_DEBUG 481 struct acl4_rule *rule_ipv4; 482 struct acl6_rule *rule_ipv6; 483 #endif 484 } acl_config; 485 486 static struct{ 487 const char *rule_ipv4_name; 488 const char *rule_ipv6_name; 489 enum rte_acl_classify_alg alg; 490 } parm_config; 491 492 const char cb_port_delim[] = ":"; 493 494 static inline void 495 print_one_ipv4_rule(struct acl4_rule *rule, int extra) 496 { 497 unsigned char a, b, c, d; 498 499 uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32, 500 &a, &b, &c, &d); 501 printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d, 502 rule->field[SRC_FIELD_IPV4].mask_range.u32); 503 uint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32, 504 &a, &b, &c, &d); 505 printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d, 506 rule->field[DST_FIELD_IPV4].mask_range.u32); 507 printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", 508 rule->field[SRCP_FIELD_IPV4].value.u16, 509 rule->field[SRCP_FIELD_IPV4].mask_range.u16, 510 rule->field[DSTP_FIELD_IPV4].value.u16, 511 rule->field[DSTP_FIELD_IPV4].mask_range.u16, 512 rule->field[PROTO_FIELD_IPV4].value.u8, 513 rule->field[PROTO_FIELD_IPV4].mask_range.u8); 514 if (extra) 515 printf("0x%x-0x%x-0x%x ", 516 rule->data.category_mask, 517 rule->data.priority, 518 rule->data.userdata); 519 } 520 521 static inline void 522 print_one_ipv6_rule(struct acl6_rule *rule, int extra) 523 { 524 unsigned char a, b, c, d; 525 526 uint32_t_to_char(rule->field[SRC1_FIELD_IPV6].value.u32, 527 &a, &b, &c, &d); 528 printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 529 uint32_t_to_char(rule->field[SRC2_FIELD_IPV6].value.u32, 530 &a, &b, &c, &d); 531 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 532 uint32_t_to_char(rule->field[SRC3_FIELD_IPV6].value.u32, 533 &a, &b, &c, &d); 534 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 535 uint32_t_to_char(rule->field[SRC4_FIELD_IPV6].value.u32, 536 &a, &b, &c, &d); 537 printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 538 rule->field[SRC1_FIELD_IPV6].mask_range.u32 539 + rule->field[SRC2_FIELD_IPV6].mask_range.u32 540 + rule->field[SRC3_FIELD_IPV6].mask_range.u32 541 + rule->field[SRC4_FIELD_IPV6].mask_range.u32); 542 543 uint32_t_to_char(rule->field[DST1_FIELD_IPV6].value.u32, 544 &a, &b, &c, &d); 545 printf("%.2x%.2x:%.2x%.2x", a, b, c, d); 546 uint32_t_to_char(rule->field[DST2_FIELD_IPV6].value.u32, 547 &a, &b, &c, &d); 548 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 549 uint32_t_to_char(rule->field[DST3_FIELD_IPV6].value.u32, 550 &a, &b, &c, &d); 551 printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); 552 uint32_t_to_char(rule->field[DST4_FIELD_IPV6].value.u32, 553 &a, &b, &c, &d); 554 printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, 555 rule->field[DST1_FIELD_IPV6].mask_range.u32 556 + rule->field[DST2_FIELD_IPV6].mask_range.u32 557 + rule->field[DST3_FIELD_IPV6].mask_range.u32 558 + rule->field[DST4_FIELD_IPV6].mask_range.u32); 559 560 printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", 561 rule->field[SRCP_FIELD_IPV6].value.u16, 562 rule->field[SRCP_FIELD_IPV6].mask_range.u16, 563 rule->field[DSTP_FIELD_IPV6].value.u16, 564 rule->field[DSTP_FIELD_IPV6].mask_range.u16, 565 rule->field[PROTO_FIELD_IPV6].value.u8, 566 rule->field[PROTO_FIELD_IPV6].mask_range.u8); 567 if (extra) 568 printf("0x%x-0x%x-0x%x ", 569 rule->data.category_mask, 570 rule->data.priority, 571 rule->data.userdata); 572 } 573 574 /* Bypass comment and empty lines */ 575 static inline int 576 is_bypass_line(char *buff) 577 { 578 int i = 0; 579 580 /* comment line */ 581 if (buff[0] == COMMENT_LEAD_CHAR) 582 return 1; 583 /* empty line */ 584 while (buff[i] != '\0') { 585 if (!isspace(buff[i])) 586 return 0; 587 i++; 588 } 589 return 1; 590 } 591 592 #ifdef L3FWDACL_DEBUG 593 static inline void 594 dump_acl4_rule(struct rte_mbuf *m, uint32_t sig) 595 { 596 uint32_t offset = sig & ~ACL_DENY_SIGNATURE; 597 unsigned char a, b, c, d; 598 struct rte_ipv4_hdr *ipv4_hdr = 599 rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, 600 sizeof(struct rte_ether_hdr)); 601 602 uint32_t_to_char(rte_bswap32(ipv4_hdr->src_addr), &a, &b, &c, &d); 603 printf("Packet Src:%hhu.%hhu.%hhu.%hhu ", a, b, c, d); 604 uint32_t_to_char(rte_bswap32(ipv4_hdr->dst_addr), &a, &b, &c, &d); 605 printf("Dst:%hhu.%hhu.%hhu.%hhu ", a, b, c, d); 606 607 printf("Src port:%hu,Dst port:%hu ", 608 rte_bswap16(*(uint16_t *)(ipv4_hdr + 1)), 609 rte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1))); 610 printf("hit ACL %d - ", offset); 611 612 print_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1); 613 614 printf("\n\n"); 615 } 616 617 static inline void 618 dump_acl6_rule(struct rte_mbuf *m, uint32_t sig) 619 { 620 unsigned i; 621 uint32_t offset = sig & ~ACL_DENY_SIGNATURE; 622 struct rte_ipv6_hdr *ipv6_hdr = 623 rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, 624 sizeof(struct rte_ether_hdr)); 625 626 printf("Packet Src"); 627 for (i = 0; i < RTE_DIM(ipv6_hdr->src_addr); i += sizeof(uint16_t)) 628 printf(":%.2x%.2x", 629 ipv6_hdr->src_addr[i], ipv6_hdr->src_addr[i + 1]); 630 631 printf("\nDst"); 632 for (i = 0; i < RTE_DIM(ipv6_hdr->dst_addr); i += sizeof(uint16_t)) 633 printf(":%.2x%.2x", 634 ipv6_hdr->dst_addr[i], ipv6_hdr->dst_addr[i + 1]); 635 636 printf("\nSrc port:%hu,Dst port:%hu ", 637 rte_bswap16(*(uint16_t *)(ipv6_hdr + 1)), 638 rte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1))); 639 printf("hit ACL %d - ", offset); 640 641 print_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1); 642 643 printf("\n\n"); 644 } 645 #endif /* L3FWDACL_DEBUG */ 646 647 static inline void 648 dump_ipv4_rules(struct acl4_rule *rule, int num, int extra) 649 { 650 int i; 651 652 for (i = 0; i < num; i++, rule++) { 653 printf("\t%d:", i + 1); 654 print_one_ipv4_rule(rule, extra); 655 printf("\n"); 656 } 657 } 658 659 static inline void 660 dump_ipv6_rules(struct acl6_rule *rule, int num, int extra) 661 { 662 int i; 663 664 for (i = 0; i < num; i++, rule++) { 665 printf("\t%d:", i + 1); 666 print_one_ipv6_rule(rule, extra); 667 printf("\n"); 668 } 669 } 670 671 #ifdef DO_RFC_1812_CHECKS 672 static inline void 673 prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl, 674 int index) 675 { 676 struct rte_ipv4_hdr *ipv4_hdr; 677 struct rte_mbuf *pkt = pkts_in[index]; 678 679 if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { 680 ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *, 681 sizeof(struct rte_ether_hdr)); 682 683 /* Check to make sure the packet is valid (RFC1812) */ 684 if (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) { 685 686 /* Update time to live and header checksum */ 687 --(ipv4_hdr->time_to_live); 688 ++(ipv4_hdr->hdr_checksum); 689 690 /* Fill acl structure */ 691 acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt); 692 acl->m_ipv4[(acl->num_ipv4)++] = pkt; 693 694 } else { 695 /* Not a valid IPv4 packet */ 696 rte_pktmbuf_free(pkt); 697 } 698 } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { 699 /* Fill acl structure */ 700 acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt); 701 acl->m_ipv6[(acl->num_ipv6)++] = pkt; 702 703 } else { 704 /* Unknown type, drop the packet */ 705 rte_pktmbuf_free(pkt); 706 } 707 } 708 709 #else 710 static inline void 711 prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl, 712 int index) 713 { 714 struct rte_mbuf *pkt = pkts_in[index]; 715 716 if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { 717 /* Fill acl structure */ 718 acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt); 719 acl->m_ipv4[(acl->num_ipv4)++] = pkt; 720 721 } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { 722 /* Fill acl structure */ 723 acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt); 724 acl->m_ipv6[(acl->num_ipv6)++] = pkt; 725 } else { 726 /* Unknown type, drop the packet */ 727 rte_pktmbuf_free(pkt); 728 } 729 } 730 #endif /* DO_RFC_1812_CHECKS */ 731 732 static inline void 733 prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_search_t *acl, 734 int nb_rx) 735 { 736 int i; 737 738 acl->num_ipv4 = 0; 739 acl->num_ipv6 = 0; 740 741 /* Prefetch first packets */ 742 for (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) { 743 rte_prefetch0(rte_pktmbuf_mtod( 744 pkts_in[i], void *)); 745 } 746 747 for (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) { 748 rte_prefetch0(rte_pktmbuf_mtod(pkts_in[ 749 i + PREFETCH_OFFSET], void *)); 750 prepare_one_packet(pkts_in, acl, i); 751 } 752 753 /* Process left packets */ 754 for (; i < nb_rx; i++) 755 prepare_one_packet(pkts_in, acl, i); 756 } 757 758 static inline void 759 send_one_packet(struct rte_mbuf *m, uint32_t res) 760 { 761 if (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) { 762 /* forward packets */ 763 send_single_packet(m, 764 (uint8_t)(res - FWD_PORT_SHIFT)); 765 } else{ 766 /* in the ACL list, drop it */ 767 #ifdef L3FWDACL_DEBUG 768 if ((res & ACL_DENY_SIGNATURE) != 0) { 769 if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) 770 dump_acl4_rule(m, res); 771 else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) 772 dump_acl6_rule(m, res); 773 } 774 #endif 775 rte_pktmbuf_free(m); 776 } 777 } 778 779 780 781 static inline void 782 send_packets(struct rte_mbuf **m, uint32_t *res, int num) 783 { 784 int i; 785 786 /* Prefetch first packets */ 787 for (i = 0; i < PREFETCH_OFFSET && i < num; i++) { 788 rte_prefetch0(rte_pktmbuf_mtod( 789 m[i], void *)); 790 } 791 792 for (i = 0; i < (num - PREFETCH_OFFSET); i++) { 793 rte_prefetch0(rte_pktmbuf_mtod(m[ 794 i + PREFETCH_OFFSET], void *)); 795 send_one_packet(m[i], res[i]); 796 } 797 798 /* Process left packets */ 799 for (; i < num; i++) 800 send_one_packet(m[i], res[i]); 801 } 802 803 /* 804 * Parse IPv6 address, expects the following format: 805 * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X is a hexadecimal digit). 806 */ 807 static int 808 parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32], 809 char dlm) 810 { 811 uint32_t addr[IPV6_ADDR_U16]; 812 813 GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':'); 814 GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':'); 815 GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':'); 816 GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':'); 817 GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':'); 818 GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':'); 819 GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':'); 820 GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm); 821 822 *end = in; 823 824 v[0] = (addr[0] << 16) + addr[1]; 825 v[1] = (addr[2] << 16) + addr[3]; 826 v[2] = (addr[4] << 16) + addr[5]; 827 v[3] = (addr[6] << 16) + addr[7]; 828 829 return 0; 830 } 831 832 static int 833 parse_ipv6_net(const char *in, struct rte_acl_field field[4]) 834 { 835 int32_t rc; 836 const char *mp; 837 uint32_t i, m, v[4]; 838 const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; 839 840 /* get address. */ 841 rc = parse_ipv6_addr(in, &mp, v, '/'); 842 if (rc != 0) 843 return rc; 844 845 /* get mask. */ 846 GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); 847 848 /* put all together. */ 849 for (i = 0; i != RTE_DIM(v); i++) { 850 if (m >= (i + 1) * nbu32) 851 field[i].mask_range.u32 = nbu32; 852 else 853 field[i].mask_range.u32 = m > (i * nbu32) ? 854 m - (i * 32) : 0; 855 856 field[i].value.u32 = v[i]; 857 } 858 859 return 0; 860 } 861 862 static int 863 parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata) 864 { 865 int i, rc; 866 char *s, *sp, *in[CB_FLD_NUM]; 867 static const char *dlm = " \t\n"; 868 int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; 869 s = str; 870 871 for (i = 0; i != dim; i++, s = NULL) { 872 in[i] = strtok_r(s, dlm, &sp); 873 if (in[i] == NULL) 874 return -EINVAL; 875 } 876 877 rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); 878 if (rc != 0) { 879 acl_log("failed to read source address/mask: %s\n", 880 in[CB_FLD_SRC_ADDR]); 881 return rc; 882 } 883 884 rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); 885 if (rc != 0) { 886 acl_log("failed to read destination address/mask: %s\n", 887 in[CB_FLD_DST_ADDR]); 888 return rc; 889 } 890 891 /* source port. */ 892 GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], 893 v->field[SRCP_FIELD_IPV6].value.u16, 894 0, UINT16_MAX, 0); 895 GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], 896 v->field[SRCP_FIELD_IPV6].mask_range.u16, 897 0, UINT16_MAX, 0); 898 899 if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, 900 sizeof(cb_port_delim)) != 0) 901 return -EINVAL; 902 903 /* destination port. */ 904 GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], 905 v->field[DSTP_FIELD_IPV6].value.u16, 906 0, UINT16_MAX, 0); 907 GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], 908 v->field[DSTP_FIELD_IPV6].mask_range.u16, 909 0, UINT16_MAX, 0); 910 911 if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, 912 sizeof(cb_port_delim)) != 0) 913 return -EINVAL; 914 915 if (v->field[SRCP_FIELD_IPV6].mask_range.u16 916 < v->field[SRCP_FIELD_IPV6].value.u16 917 || v->field[DSTP_FIELD_IPV6].mask_range.u16 918 < v->field[DSTP_FIELD_IPV6].value.u16) 919 return -EINVAL; 920 921 GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8, 922 0, UINT8_MAX, '/'); 923 GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8, 924 0, UINT8_MAX, 0); 925 926 if (has_userdata) 927 GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 928 0, UINT32_MAX, 0); 929 930 return 0; 931 } 932 933 /* 934 * Parse ClassBench rules file. 935 * Expected format: 936 * '@'<src_ipv4_addr>'/'<masklen> <space> \ 937 * <dst_ipv4_addr>'/'<masklen> <space> \ 938 * <src_port_low> <space> ":" <src_port_high> <space> \ 939 * <dst_port_low> <space> ":" <dst_port_high> <space> \ 940 * <proto>'/'<mask> 941 */ 942 static int 943 parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) 944 { 945 uint8_t a, b, c, d, m; 946 947 GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); 948 GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); 949 GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); 950 GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); 951 GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); 952 953 addr[0] = RTE_IPV4(a, b, c, d); 954 mask_len[0] = m; 955 956 return 0; 957 } 958 959 static int 960 parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata) 961 { 962 int i, rc; 963 char *s, *sp, *in[CB_FLD_NUM]; 964 static const char *dlm = " \t\n"; 965 int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; 966 s = str; 967 968 for (i = 0; i != dim; i++, s = NULL) { 969 in[i] = strtok_r(s, dlm, &sp); 970 if (in[i] == NULL) 971 return -EINVAL; 972 } 973 974 rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], 975 &v->field[SRC_FIELD_IPV4].value.u32, 976 &v->field[SRC_FIELD_IPV4].mask_range.u32); 977 if (rc != 0) { 978 acl_log("failed to read source address/mask: %s\n", 979 in[CB_FLD_SRC_ADDR]); 980 return rc; 981 } 982 983 rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], 984 &v->field[DST_FIELD_IPV4].value.u32, 985 &v->field[DST_FIELD_IPV4].mask_range.u32); 986 if (rc != 0) { 987 acl_log("failed to read destination address/mask: %s\n", 988 in[CB_FLD_DST_ADDR]); 989 return rc; 990 } 991 992 GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], 993 v->field[SRCP_FIELD_IPV4].value.u16, 994 0, UINT16_MAX, 0); 995 GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], 996 v->field[SRCP_FIELD_IPV4].mask_range.u16, 997 0, UINT16_MAX, 0); 998 999 if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, 1000 sizeof(cb_port_delim)) != 0) 1001 return -EINVAL; 1002 1003 GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], 1004 v->field[DSTP_FIELD_IPV4].value.u16, 1005 0, UINT16_MAX, 0); 1006 GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], 1007 v->field[DSTP_FIELD_IPV4].mask_range.u16, 1008 0, UINT16_MAX, 0); 1009 1010 if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, 1011 sizeof(cb_port_delim)) != 0) 1012 return -EINVAL; 1013 1014 if (v->field[SRCP_FIELD_IPV4].mask_range.u16 1015 < v->field[SRCP_FIELD_IPV4].value.u16 1016 || v->field[DSTP_FIELD_IPV4].mask_range.u16 1017 < v->field[DSTP_FIELD_IPV4].value.u16) 1018 return -EINVAL; 1019 1020 GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8, 1021 0, UINT8_MAX, '/'); 1022 GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8, 1023 0, UINT8_MAX, 0); 1024 1025 if (has_userdata) 1026 GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0, 1027 UINT32_MAX, 0); 1028 1029 return 0; 1030 } 1031 1032 static int 1033 add_rules(const char *rule_path, 1034 struct rte_acl_rule **proute_base, 1035 unsigned int *proute_num, 1036 struct rte_acl_rule **pacl_base, 1037 unsigned int *pacl_num, uint32_t rule_size, 1038 int (*parser)(char *, struct rte_acl_rule*, int)) 1039 { 1040 uint8_t *acl_rules, *route_rules; 1041 struct rte_acl_rule *next; 1042 unsigned int acl_num = 0, route_num = 0, total_num = 0; 1043 unsigned int acl_cnt = 0, route_cnt = 0; 1044 char buff[LINE_MAX]; 1045 FILE *fh = fopen(rule_path, "rb"); 1046 unsigned int i = 0; 1047 int val; 1048 1049 if (fh == NULL) 1050 rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__, 1051 rule_path); 1052 1053 while ((fgets(buff, LINE_MAX, fh) != NULL)) { 1054 if (buff[0] == ROUTE_LEAD_CHAR) 1055 route_num++; 1056 else if (buff[0] == ACL_LEAD_CHAR) 1057 acl_num++; 1058 } 1059 1060 if (0 == route_num) 1061 rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n", 1062 rule_path); 1063 1064 val = fseek(fh, 0, SEEK_SET); 1065 if (val < 0) { 1066 rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n", 1067 __func__); 1068 } 1069 1070 acl_rules = calloc(acl_num, rule_size); 1071 1072 if (NULL == acl_rules) 1073 rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", 1074 __func__); 1075 1076 route_rules = calloc(route_num, rule_size); 1077 1078 if (NULL == route_rules) 1079 rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", 1080 __func__); 1081 1082 i = 0; 1083 while (fgets(buff, LINE_MAX, fh) != NULL) { 1084 i++; 1085 1086 if (is_bypass_line(buff)) 1087 continue; 1088 1089 char s = buff[0]; 1090 1091 /* Route entry */ 1092 if (s == ROUTE_LEAD_CHAR) 1093 next = (struct rte_acl_rule *)(route_rules + 1094 route_cnt * rule_size); 1095 1096 /* ACL entry */ 1097 else if (s == ACL_LEAD_CHAR) 1098 next = (struct rte_acl_rule *)(acl_rules + 1099 acl_cnt * rule_size); 1100 1101 /* Illegal line */ 1102 else 1103 rte_exit(EXIT_FAILURE, 1104 "%s Line %u: should start with leading " 1105 "char %c or %c\n", 1106 rule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR); 1107 1108 if (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0) 1109 rte_exit(EXIT_FAILURE, 1110 "%s Line %u: parse rules error\n", 1111 rule_path, i); 1112 1113 if (s == ROUTE_LEAD_CHAR) { 1114 /* Check the forwarding port number */ 1115 if ((enabled_port_mask & (1 << next->data.userdata)) == 1116 0) 1117 rte_exit(EXIT_FAILURE, 1118 "%s Line %u: fwd number illegal:%u\n", 1119 rule_path, i, next->data.userdata); 1120 next->data.userdata += FWD_PORT_SHIFT; 1121 route_cnt++; 1122 } else { 1123 next->data.userdata = ACL_DENY_SIGNATURE + acl_cnt; 1124 acl_cnt++; 1125 } 1126 1127 next->data.priority = RTE_ACL_MAX_PRIORITY - total_num; 1128 next->data.category_mask = -1; 1129 total_num++; 1130 } 1131 1132 fclose(fh); 1133 1134 *pacl_base = (struct rte_acl_rule *)acl_rules; 1135 *pacl_num = acl_num; 1136 *proute_base = (struct rte_acl_rule *)route_rules; 1137 *proute_num = route_cnt; 1138 1139 return 0; 1140 } 1141 1142 static int 1143 usage_acl_alg(char *buf, size_t sz) 1144 { 1145 uint32_t i, n, rc, tn; 1146 1147 n = 0; 1148 tn = 0; 1149 for (i = 0; i < RTE_DIM(acl_alg); i++) { 1150 rc = snprintf(buf + n, sz - n, 1151 i == RTE_DIM(acl_alg) - 1 ? "%s" : "%s|", 1152 acl_alg[i].name); 1153 tn += rc; 1154 if (rc < sz - n) 1155 n += rc; 1156 } 1157 1158 return tn; 1159 } 1160 1161 static const char * 1162 str_acl_alg(enum rte_acl_classify_alg alg) 1163 { 1164 uint32_t i; 1165 1166 for (i = 0; i != RTE_DIM(acl_alg); i++) { 1167 if (alg == acl_alg[i].alg) 1168 return acl_alg[i].name; 1169 } 1170 1171 return "default"; 1172 } 1173 1174 static enum rte_acl_classify_alg 1175 parse_acl_alg(const char *alg) 1176 { 1177 uint32_t i; 1178 1179 for (i = 0; i != RTE_DIM(acl_alg); i++) { 1180 if (strcmp(alg, acl_alg[i].name) == 0) 1181 return acl_alg[i].alg; 1182 } 1183 1184 return RTE_ACL_CLASSIFY_DEFAULT; 1185 } 1186 1187 static void 1188 dump_acl_config(void) 1189 { 1190 printf("ACL option are:\n"); 1191 printf(OPT_RULE_IPV4": %s\n", parm_config.rule_ipv4_name); 1192 printf(OPT_RULE_IPV6": %s\n", parm_config.rule_ipv6_name); 1193 printf(OPT_ALG": %s\n", str_acl_alg(parm_config.alg)); 1194 } 1195 1196 static int 1197 check_acl_config(void) 1198 { 1199 if (parm_config.rule_ipv4_name == NULL) { 1200 acl_log("ACL IPv4 rule file not specified\n"); 1201 return -1; 1202 } else if (parm_config.rule_ipv6_name == NULL) { 1203 acl_log("ACL IPv6 rule file not specified\n"); 1204 return -1; 1205 } 1206 1207 return 0; 1208 } 1209 1210 static struct rte_acl_ctx* 1211 setup_acl(struct rte_acl_rule *route_base, 1212 struct rte_acl_rule *acl_base, unsigned int route_num, 1213 unsigned int acl_num, int ipv6, int socketid) 1214 { 1215 char name[PATH_MAX]; 1216 struct rte_acl_param acl_param; 1217 struct rte_acl_config acl_build_param; 1218 struct rte_acl_ctx *context; 1219 int dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs); 1220 1221 /* Create ACL contexts */ 1222 snprintf(name, sizeof(name), "%s%d", 1223 ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME, 1224 socketid); 1225 1226 acl_param.name = name; 1227 acl_param.socket_id = socketid; 1228 acl_param.rule_size = RTE_ACL_RULE_SZ(dim); 1229 acl_param.max_rule_num = MAX_ACL_RULE_NUM; 1230 1231 if ((context = rte_acl_create(&acl_param)) == NULL) 1232 rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); 1233 1234 if (parm_config.alg != RTE_ACL_CLASSIFY_DEFAULT && 1235 rte_acl_set_ctx_classify(context, parm_config.alg) != 0) 1236 rte_exit(EXIT_FAILURE, 1237 "Failed to setup classify method for ACL context\n"); 1238 1239 if (rte_acl_add_rules(context, route_base, route_num) < 0) 1240 rte_exit(EXIT_FAILURE, "add rules failed\n"); 1241 1242 if (rte_acl_add_rules(context, acl_base, acl_num) < 0) 1243 rte_exit(EXIT_FAILURE, "add rules failed\n"); 1244 1245 /* Perform builds */ 1246 memset(&acl_build_param, 0, sizeof(acl_build_param)); 1247 1248 acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; 1249 acl_build_param.num_fields = dim; 1250 memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs, 1251 ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs)); 1252 1253 if (rte_acl_build(context, &acl_build_param) != 0) 1254 rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); 1255 1256 rte_acl_dump(context); 1257 1258 return context; 1259 } 1260 1261 static int 1262 app_acl_init(void) 1263 { 1264 unsigned lcore_id; 1265 unsigned int i; 1266 int socketid; 1267 struct rte_acl_rule *acl_base_ipv4, *route_base_ipv4, 1268 *acl_base_ipv6, *route_base_ipv6; 1269 unsigned int acl_num_ipv4 = 0, route_num_ipv4 = 0, 1270 acl_num_ipv6 = 0, route_num_ipv6 = 0; 1271 1272 if (check_acl_config() != 0) 1273 rte_exit(EXIT_FAILURE, "Failed to get valid ACL options\n"); 1274 1275 dump_acl_config(); 1276 1277 /* Load rules from the input file */ 1278 if (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4, 1279 &route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4, 1280 sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0) 1281 rte_exit(EXIT_FAILURE, "Failed to add rules\n"); 1282 1283 acl_log("IPv4 Route entries %u:\n", route_num_ipv4); 1284 dump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1); 1285 1286 acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4); 1287 dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1); 1288 1289 if (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6, 1290 &route_num_ipv6, 1291 &acl_base_ipv6, &acl_num_ipv6, 1292 sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0) 1293 rte_exit(EXIT_FAILURE, "Failed to add rules\n"); 1294 1295 acl_log("IPv6 Route entries %u:\n", route_num_ipv6); 1296 dump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1); 1297 1298 acl_log("IPv6 ACL entries %u:\n", acl_num_ipv6); 1299 dump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1); 1300 1301 memset(&acl_config, 0, sizeof(acl_config)); 1302 1303 /* Check sockets a context should be created on */ 1304 if (!numa_on) 1305 acl_config.mapped[0] = 1; 1306 else { 1307 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 1308 if (rte_lcore_is_enabled(lcore_id) == 0) 1309 continue; 1310 1311 socketid = rte_lcore_to_socket_id(lcore_id); 1312 if (socketid >= NB_SOCKETS) { 1313 acl_log("Socket %d of lcore %u is out " 1314 "of range %d\n", 1315 socketid, lcore_id, NB_SOCKETS); 1316 free(route_base_ipv4); 1317 free(route_base_ipv6); 1318 free(acl_base_ipv4); 1319 free(acl_base_ipv6); 1320 return -1; 1321 } 1322 1323 acl_config.mapped[socketid] = 1; 1324 } 1325 } 1326 1327 for (i = 0; i < NB_SOCKETS; i++) { 1328 if (acl_config.mapped[i]) { 1329 acl_config.acx_ipv4[i] = setup_acl(route_base_ipv4, 1330 acl_base_ipv4, route_num_ipv4, acl_num_ipv4, 1331 0, i); 1332 1333 acl_config.acx_ipv6[i] = setup_acl(route_base_ipv6, 1334 acl_base_ipv6, route_num_ipv6, acl_num_ipv6, 1335 1, i); 1336 } 1337 } 1338 1339 free(route_base_ipv4); 1340 free(route_base_ipv6); 1341 1342 #ifdef L3FWDACL_DEBUG 1343 acl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4; 1344 acl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6; 1345 #else 1346 free(acl_base_ipv4); 1347 free(acl_base_ipv6); 1348 #endif 1349 1350 return 0; 1351 } 1352 1353 /***********************end of ACL part******************************/ 1354 1355 struct lcore_conf { 1356 uint16_t n_rx_queue; 1357 struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 1358 uint16_t n_tx_port; 1359 uint16_t tx_port_id[RTE_MAX_ETHPORTS]; 1360 uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 1361 struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 1362 } __rte_cache_aligned; 1363 1364 static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 1365 1366 /* Enqueue a single packet, and send burst if queue is filled */ 1367 static inline void 1368 send_single_packet(struct rte_mbuf *m, uint16_t port) 1369 { 1370 uint32_t lcore_id; 1371 struct lcore_conf *qconf; 1372 struct rte_ether_hdr *eh; 1373 1374 lcore_id = rte_lcore_id(); 1375 1376 /* update src and dst mac*/ 1377 eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 1378 memcpy(eh, &port_l2hdr[port], 1379 sizeof(eh->dst_addr) + sizeof(eh->src_addr)); 1380 1381 qconf = &lcore_conf[lcore_id]; 1382 rte_eth_tx_buffer(port, qconf->tx_queue_id[port], 1383 qconf->tx_buffer[port], m); 1384 } 1385 1386 #ifdef DO_RFC_1812_CHECKS 1387 static inline int 1388 is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len) 1389 { 1390 /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ 1391 /* 1392 * 1. The packet length reported by the Link Layer must be large 1393 * enough to hold the minimum length legal IP datagram (20 bytes). 1394 */ 1395 if (link_len < sizeof(struct rte_ipv4_hdr)) 1396 return -1; 1397 1398 /* 2. The IP checksum must be correct. */ 1399 /* this is checked in H/W */ 1400 1401 /* 1402 * 3. The IP version number must be 4. If the version number is not 4 1403 * then the packet may be another version of IP, such as IPng or 1404 * ST-II. 1405 */ 1406 if (((pkt->version_ihl) >> 4) != 4) 1407 return -3; 1408 /* 1409 * 4. The IP header length field must be large enough to hold the 1410 * minimum length legal IP datagram (20 bytes = 5 words). 1411 */ 1412 if ((pkt->version_ihl & 0xf) < 5) 1413 return -4; 1414 1415 /* 1416 * 5. The IP total length field must be large enough to hold the IP 1417 * datagram header, whose length is specified in the IP header length 1418 * field. 1419 */ 1420 if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) 1421 return -5; 1422 1423 return 0; 1424 } 1425 #endif 1426 1427 /* main processing loop */ 1428 static int 1429 main_loop(__rte_unused void *dummy) 1430 { 1431 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1432 unsigned lcore_id; 1433 uint64_t prev_tsc, diff_tsc, cur_tsc; 1434 int i, nb_rx; 1435 uint16_t portid; 1436 uint8_t queueid; 1437 struct lcore_conf *qconf; 1438 int socketid; 1439 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) 1440 / US_PER_S * BURST_TX_DRAIN_US; 1441 1442 prev_tsc = 0; 1443 lcore_id = rte_lcore_id(); 1444 qconf = &lcore_conf[lcore_id]; 1445 socketid = rte_lcore_to_socket_id(lcore_id); 1446 1447 if (qconf->n_rx_queue == 0) { 1448 RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); 1449 return 0; 1450 } 1451 1452 RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); 1453 1454 for (i = 0; i < qconf->n_rx_queue; i++) { 1455 1456 portid = qconf->rx_queue_list[i].port_id; 1457 queueid = qconf->rx_queue_list[i].queue_id; 1458 RTE_LOG(INFO, L3FWD, 1459 " -- lcoreid=%u portid=%u rxqueueid=%hhu\n", 1460 lcore_id, portid, queueid); 1461 } 1462 1463 while (1) { 1464 1465 cur_tsc = rte_rdtsc(); 1466 1467 /* 1468 * TX burst queue drain 1469 */ 1470 diff_tsc = cur_tsc - prev_tsc; 1471 if (unlikely(diff_tsc > drain_tsc)) { 1472 for (i = 0; i < qconf->n_tx_port; ++i) { 1473 portid = qconf->tx_port_id[i]; 1474 rte_eth_tx_buffer_flush(portid, 1475 qconf->tx_queue_id[portid], 1476 qconf->tx_buffer[portid]); 1477 } 1478 prev_tsc = cur_tsc; 1479 } 1480 1481 /* 1482 * Read packet from RX queues 1483 */ 1484 for (i = 0; i < qconf->n_rx_queue; ++i) { 1485 1486 portid = qconf->rx_queue_list[i].port_id; 1487 queueid = qconf->rx_queue_list[i].queue_id; 1488 nb_rx = rte_eth_rx_burst(portid, queueid, 1489 pkts_burst, MAX_PKT_BURST); 1490 1491 if (nb_rx > 0) { 1492 struct acl_search_t acl_search; 1493 1494 prepare_acl_parameter(pkts_burst, &acl_search, 1495 nb_rx); 1496 1497 if (acl_search.num_ipv4) { 1498 rte_acl_classify( 1499 acl_config.acx_ipv4[socketid], 1500 acl_search.data_ipv4, 1501 acl_search.res_ipv4, 1502 acl_search.num_ipv4, 1503 DEFAULT_MAX_CATEGORIES); 1504 1505 send_packets(acl_search.m_ipv4, 1506 acl_search.res_ipv4, 1507 acl_search.num_ipv4); 1508 } 1509 1510 if (acl_search.num_ipv6) { 1511 rte_acl_classify( 1512 acl_config.acx_ipv6[socketid], 1513 acl_search.data_ipv6, 1514 acl_search.res_ipv6, 1515 acl_search.num_ipv6, 1516 DEFAULT_MAX_CATEGORIES); 1517 1518 send_packets(acl_search.m_ipv6, 1519 acl_search.res_ipv6, 1520 acl_search.num_ipv6); 1521 } 1522 } 1523 } 1524 } 1525 } 1526 1527 static int 1528 check_lcore_params(void) 1529 { 1530 uint8_t queue, lcore; 1531 uint16_t i; 1532 int socketid; 1533 1534 for (i = 0; i < nb_lcore_params; ++i) { 1535 queue = lcore_params[i].queue_id; 1536 if (queue >= MAX_RX_QUEUE_PER_PORT) { 1537 printf("invalid queue number: %hhu\n", queue); 1538 return -1; 1539 } 1540 lcore = lcore_params[i].lcore_id; 1541 if (!rte_lcore_is_enabled(lcore)) { 1542 printf("error: lcore %hhu is not enabled in " 1543 "lcore mask\n", lcore); 1544 return -1; 1545 } 1546 socketid = rte_lcore_to_socket_id(lcore); 1547 if (socketid != 0 && numa_on == 0) { 1548 printf("warning: lcore %hhu is on socket %d " 1549 "with numa off\n", 1550 lcore, socketid); 1551 } 1552 } 1553 return 0; 1554 } 1555 1556 static int 1557 check_port_config(void) 1558 { 1559 unsigned portid; 1560 uint16_t i; 1561 1562 for (i = 0; i < nb_lcore_params; ++i) { 1563 portid = lcore_params[i].port_id; 1564 1565 if ((enabled_port_mask & (1 << portid)) == 0) { 1566 printf("port %u is not enabled in port mask\n", portid); 1567 return -1; 1568 } 1569 if (!rte_eth_dev_is_valid_port(portid)) { 1570 printf("port %u is not present on the board\n", portid); 1571 return -1; 1572 } 1573 } 1574 return 0; 1575 } 1576 1577 static uint8_t 1578 get_port_n_rx_queues(const uint16_t port) 1579 { 1580 int queue = -1; 1581 uint16_t i; 1582 1583 for (i = 0; i < nb_lcore_params; ++i) { 1584 if (lcore_params[i].port_id == port && 1585 lcore_params[i].queue_id > queue) 1586 queue = lcore_params[i].queue_id; 1587 } 1588 return (uint8_t)(++queue); 1589 } 1590 1591 static int 1592 init_lcore_rx_queues(void) 1593 { 1594 uint16_t i, nb_rx_queue; 1595 uint8_t lcore; 1596 1597 for (i = 0; i < nb_lcore_params; ++i) { 1598 lcore = lcore_params[i].lcore_id; 1599 nb_rx_queue = lcore_conf[lcore].n_rx_queue; 1600 if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 1601 printf("error: too many queues (%u) for lcore: %u\n", 1602 (unsigned)nb_rx_queue + 1, (unsigned)lcore); 1603 return -1; 1604 } else { 1605 lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 1606 lcore_params[i].port_id; 1607 lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 1608 lcore_params[i].queue_id; 1609 lcore_conf[lcore].n_rx_queue++; 1610 } 1611 } 1612 return 0; 1613 } 1614 1615 /* display usage */ 1616 static void 1617 print_usage(const char *prgname) 1618 { 1619 char alg[PATH_MAX]; 1620 1621 usage_acl_alg(alg, sizeof(alg)); 1622 printf("%s [EAL options] -- -p PORTMASK -P" 1623 " --"OPT_RULE_IPV4"=FILE" 1624 " --"OPT_RULE_IPV6"=FILE" 1625 " [--"OPT_CONFIG" (port,queue,lcore)[,(port,queue,lcore]]" 1626 " [--"OPT_MAX_PKT_LEN" PKTLEN]\n" 1627 " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 1628 " -P: enable promiscuous mode\n" 1629 " --"OPT_CONFIG" (port,queue,lcore): rx queues configuration\n" 1630 " --"OPT_NONUMA": optional, disable numa awareness\n" 1631 " --"OPT_MAX_PKT_LEN" PKTLEN: maximum packet length in decimal (64-9600)\n" 1632 " --"OPT_RULE_IPV4"=FILE: specify the ipv4 rules entries file. " 1633 "Each rule occupy one line. " 1634 "2 kinds of rules are supported. " 1635 "One is ACL entry at while line leads with character '%c', " 1636 "another is route entry at while line leads with character '%c'.\n" 1637 " --"OPT_RULE_IPV6"=FILE: specify the ipv6 rules entries file.\n" 1638 " --"OPT_ALG": ACL classify method to use, one of: %s\n", 1639 prgname, ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg); 1640 } 1641 1642 static int 1643 parse_max_pkt_len(const char *pktlen) 1644 { 1645 char *end = NULL; 1646 unsigned long len; 1647 1648 /* parse decimal string */ 1649 len = strtoul(pktlen, &end, 10); 1650 if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) 1651 return -1; 1652 1653 if (len == 0) 1654 return -1; 1655 1656 return len; 1657 } 1658 1659 static int 1660 parse_portmask(const char *portmask) 1661 { 1662 char *end = NULL; 1663 unsigned long pm; 1664 1665 /* parse hexadecimal string */ 1666 pm = strtoul(portmask, &end, 16); 1667 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 1668 return 0; 1669 1670 return pm; 1671 } 1672 1673 static int 1674 parse_config(const char *q_arg) 1675 { 1676 char s[256]; 1677 const char *p, *p0 = q_arg; 1678 char *end; 1679 enum fieldnames { 1680 FLD_PORT = 0, 1681 FLD_QUEUE, 1682 FLD_LCORE, 1683 _NUM_FLD 1684 }; 1685 unsigned long int_fld[_NUM_FLD]; 1686 char *str_fld[_NUM_FLD]; 1687 int i; 1688 unsigned size; 1689 1690 nb_lcore_params = 0; 1691 1692 while ((p = strchr(p0, '(')) != NULL) { 1693 ++p; 1694 if ((p0 = strchr(p, ')')) == NULL) 1695 return -1; 1696 1697 size = p0 - p; 1698 if (size >= sizeof(s)) 1699 return -1; 1700 1701 snprintf(s, sizeof(s), "%.*s", size, p); 1702 if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 1703 _NUM_FLD) 1704 return -1; 1705 for (i = 0; i < _NUM_FLD; i++) { 1706 errno = 0; 1707 int_fld[i] = strtoul(str_fld[i], &end, 0); 1708 if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) 1709 return -1; 1710 } 1711 if (nb_lcore_params >= MAX_LCORE_PARAMS) { 1712 printf("exceeded max number of lcore params: %hu\n", 1713 nb_lcore_params); 1714 return -1; 1715 } 1716 lcore_params_array[nb_lcore_params].port_id = 1717 (uint8_t)int_fld[FLD_PORT]; 1718 lcore_params_array[nb_lcore_params].queue_id = 1719 (uint8_t)int_fld[FLD_QUEUE]; 1720 lcore_params_array[nb_lcore_params].lcore_id = 1721 (uint8_t)int_fld[FLD_LCORE]; 1722 ++nb_lcore_params; 1723 } 1724 lcore_params = lcore_params_array; 1725 return 0; 1726 } 1727 1728 static const char * 1729 parse_eth_dest(const char *optarg) 1730 { 1731 unsigned long portid; 1732 char *port_end; 1733 1734 errno = 0; 1735 portid = strtoul(optarg, &port_end, 0); 1736 if (errno != 0 || port_end == optarg || *port_end++ != ',') 1737 return "Invalid format"; 1738 else if (portid >= RTE_MAX_ETHPORTS) 1739 return "port value exceeds RTE_MAX_ETHPORTS(" 1740 RTE_STR(RTE_MAX_ETHPORTS) ")"; 1741 1742 if (cmdline_parse_etheraddr(NULL, port_end, 1743 &port_l2hdr[portid].dst_addr, 1744 sizeof(port_l2hdr[portid].dst_addr)) < 0) 1745 return "Invalid ethernet address"; 1746 return NULL; 1747 } 1748 1749 /* Parse the argument given in the command line of the application */ 1750 static int 1751 parse_args(int argc, char **argv) 1752 { 1753 int opt, ret; 1754 char **argvopt; 1755 int option_index; 1756 char *prgname = argv[0]; 1757 static struct option lgopts[] = { 1758 {OPT_CONFIG, 1, NULL, OPT_CONFIG_NUM }, 1759 {OPT_NONUMA, 0, NULL, OPT_NONUMA_NUM }, 1760 {OPT_MAX_PKT_LEN, 1, NULL, OPT_MAX_PKT_LEN_NUM }, 1761 {OPT_RULE_IPV4, 1, NULL, OPT_RULE_IPV4_NUM }, 1762 {OPT_RULE_IPV6, 1, NULL, OPT_RULE_IPV6_NUM }, 1763 {OPT_ALG, 1, NULL, OPT_ALG_NUM }, 1764 {OPT_ETH_DEST, 1, NULL, OPT_ETH_DEST_NUM }, 1765 {NULL, 0, 0, 0 } 1766 }; 1767 1768 argvopt = argv; 1769 1770 while ((opt = getopt_long(argc, argvopt, "p:P", 1771 lgopts, &option_index)) != EOF) { 1772 1773 switch (opt) { 1774 /* portmask */ 1775 case 'p': 1776 enabled_port_mask = parse_portmask(optarg); 1777 if (enabled_port_mask == 0) { 1778 printf("invalid portmask\n"); 1779 print_usage(prgname); 1780 return -1; 1781 } 1782 break; 1783 1784 case 'P': 1785 printf("Promiscuous mode selected\n"); 1786 promiscuous_on = 1; 1787 break; 1788 1789 /* long options */ 1790 case OPT_CONFIG_NUM: 1791 ret = parse_config(optarg); 1792 if (ret) { 1793 printf("invalid config\n"); 1794 print_usage(prgname); 1795 return -1; 1796 } 1797 break; 1798 1799 case OPT_NONUMA_NUM: 1800 printf("numa is disabled\n"); 1801 numa_on = 0; 1802 break; 1803 1804 case OPT_MAX_PKT_LEN_NUM: 1805 printf("Custom frame size is configured\n"); 1806 max_pkt_len = parse_max_pkt_len(optarg); 1807 break; 1808 1809 case OPT_RULE_IPV4_NUM: 1810 parm_config.rule_ipv4_name = optarg; 1811 break; 1812 1813 case OPT_RULE_IPV6_NUM: 1814 parm_config.rule_ipv6_name = optarg; 1815 break; 1816 1817 case OPT_ALG_NUM: 1818 parm_config.alg = parse_acl_alg(optarg); 1819 if (parm_config.alg == 1820 RTE_ACL_CLASSIFY_DEFAULT) { 1821 printf("unknown %s value:\"%s\"\n", 1822 OPT_ALG, optarg); 1823 print_usage(prgname); 1824 return -1; 1825 } 1826 break; 1827 1828 case OPT_ETH_DEST_NUM: 1829 { 1830 const char *serr = parse_eth_dest(optarg); 1831 if (serr != NULL) { 1832 printf("invalid %s value:\"%s\": %s\n", 1833 OPT_ETH_DEST, optarg, serr); 1834 print_usage(prgname); 1835 return -1; 1836 } 1837 break; 1838 } 1839 default: 1840 print_usage(prgname); 1841 return -1; 1842 } 1843 } 1844 1845 if (optind >= 0) 1846 argv[optind-1] = prgname; 1847 1848 ret = optind-1; 1849 optind = 1; /* reset getopt lib */ 1850 return ret; 1851 } 1852 1853 static void 1854 print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 1855 { 1856 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 1857 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 1858 printf("%s%s", name, buf); 1859 } 1860 1861 static int 1862 init_mem(unsigned nb_mbuf) 1863 { 1864 int socketid; 1865 unsigned lcore_id; 1866 char s[64]; 1867 1868 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 1869 if (rte_lcore_is_enabled(lcore_id) == 0) 1870 continue; 1871 1872 if (numa_on) 1873 socketid = rte_lcore_to_socket_id(lcore_id); 1874 else 1875 socketid = 0; 1876 1877 if (socketid >= NB_SOCKETS) { 1878 rte_exit(EXIT_FAILURE, 1879 "Socket %d of lcore %u is out of range %d\n", 1880 socketid, lcore_id, NB_SOCKETS); 1881 } 1882 if (pktmbuf_pool[socketid] == NULL) { 1883 snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 1884 pktmbuf_pool[socketid] = 1885 rte_pktmbuf_pool_create(s, nb_mbuf, 1886 MEMPOOL_CACHE_SIZE, 0, 1887 RTE_MBUF_DEFAULT_BUF_SIZE, 1888 socketid); 1889 if (pktmbuf_pool[socketid] == NULL) 1890 rte_exit(EXIT_FAILURE, 1891 "Cannot init mbuf pool on socket %d\n", 1892 socketid); 1893 else 1894 printf("Allocated mbuf pool on socket %d\n", 1895 socketid); 1896 } 1897 } 1898 return 0; 1899 } 1900 1901 /* Check the link status of all ports in up to 9s, and print them finally */ 1902 static void 1903 check_all_ports_link_status(uint32_t port_mask) 1904 { 1905 #define CHECK_INTERVAL 100 /* 100ms */ 1906 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1907 uint16_t portid; 1908 uint8_t count, all_ports_up, print_flag = 0; 1909 struct rte_eth_link link; 1910 int ret; 1911 char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 1912 1913 printf("\nChecking link status"); 1914 fflush(stdout); 1915 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1916 all_ports_up = 1; 1917 RTE_ETH_FOREACH_DEV(portid) { 1918 if ((port_mask & (1 << portid)) == 0) 1919 continue; 1920 memset(&link, 0, sizeof(link)); 1921 ret = rte_eth_link_get_nowait(portid, &link); 1922 if (ret < 0) { 1923 all_ports_up = 0; 1924 if (print_flag == 1) 1925 printf("Port %u link get failed: %s\n", 1926 portid, rte_strerror(-ret)); 1927 continue; 1928 } 1929 /* print link status if flag set */ 1930 if (print_flag == 1) { 1931 rte_eth_link_to_str(link_status_text, 1932 sizeof(link_status_text), &link); 1933 printf("Port %d %s\n", portid, 1934 link_status_text); 1935 continue; 1936 } 1937 /* clear all_ports_up flag if any link down */ 1938 if (link.link_status == RTE_ETH_LINK_DOWN) { 1939 all_ports_up = 0; 1940 break; 1941 } 1942 } 1943 /* after finally printing all link status, get out */ 1944 if (print_flag == 1) 1945 break; 1946 1947 if (all_ports_up == 0) { 1948 printf("."); 1949 fflush(stdout); 1950 rte_delay_ms(CHECK_INTERVAL); 1951 } 1952 1953 /* set the print_flag if all ports up or timeout */ 1954 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1955 print_flag = 1; 1956 printf("done\n"); 1957 } 1958 } 1959 } 1960 1961 /* 1962 * build-up default values for dest MACs. 1963 */ 1964 static void 1965 set_default_dest_mac(void) 1966 { 1967 uint32_t i; 1968 1969 for (i = 0; i != RTE_DIM(port_l2hdr); i++) { 1970 port_l2hdr[i].dst_addr.addr_bytes[0] = 1971 RTE_ETHER_LOCAL_ADMIN_ADDR; 1972 port_l2hdr[i].dst_addr.addr_bytes[5] = i; 1973 } 1974 } 1975 1976 static uint32_t 1977 eth_dev_get_overhead_len(uint32_t max_rx_pktlen, uint16_t max_mtu) 1978 { 1979 uint32_t overhead_len; 1980 1981 if (max_mtu != UINT16_MAX && max_rx_pktlen > max_mtu) 1982 overhead_len = max_rx_pktlen - max_mtu; 1983 else 1984 overhead_len = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN; 1985 1986 return overhead_len; 1987 } 1988 1989 static int 1990 config_port_max_pkt_len(struct rte_eth_conf *conf, 1991 struct rte_eth_dev_info *dev_info) 1992 { 1993 uint32_t overhead_len; 1994 1995 if (max_pkt_len == 0) 1996 return 0; 1997 1998 if (max_pkt_len < RTE_ETHER_MIN_LEN || max_pkt_len > MAX_JUMBO_PKT_LEN) 1999 return -1; 2000 2001 overhead_len = eth_dev_get_overhead_len(dev_info->max_rx_pktlen, 2002 dev_info->max_mtu); 2003 conf->rxmode.mtu = max_pkt_len - overhead_len; 2004 2005 if (conf->rxmode.mtu > RTE_ETHER_MTU) 2006 conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 2007 2008 return 0; 2009 } 2010 2011 int 2012 main(int argc, char **argv) 2013 { 2014 struct lcore_conf *qconf; 2015 struct rte_eth_dev_info dev_info; 2016 struct rte_eth_txconf *txconf; 2017 int ret; 2018 unsigned nb_ports; 2019 uint16_t queueid; 2020 unsigned lcore_id; 2021 uint32_t n_tx_queue, nb_lcores; 2022 uint16_t portid; 2023 uint8_t nb_rx_queue, queue, socketid; 2024 2025 /* init EAL */ 2026 ret = rte_eal_init(argc, argv); 2027 if (ret < 0) 2028 rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 2029 argc -= ret; 2030 argv += ret; 2031 2032 set_default_dest_mac(); 2033 2034 /* parse application arguments (after the EAL ones) */ 2035 ret = parse_args(argc, argv); 2036 if (ret < 0) 2037 rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); 2038 2039 if (check_lcore_params() < 0) 2040 rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); 2041 2042 ret = init_lcore_rx_queues(); 2043 if (ret < 0) 2044 rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); 2045 2046 nb_ports = rte_eth_dev_count_avail(); 2047 2048 if (check_port_config() < 0) 2049 rte_exit(EXIT_FAILURE, "check_port_config failed\n"); 2050 2051 /* Add ACL rules and route entries, build trie */ 2052 if (app_acl_init() < 0) 2053 rte_exit(EXIT_FAILURE, "app_acl_init failed\n"); 2054 2055 nb_lcores = rte_lcore_count(); 2056 2057 /* initialize all ports */ 2058 RTE_ETH_FOREACH_DEV(portid) { 2059 struct rte_eth_conf local_port_conf = port_conf; 2060 2061 /* skip ports that are not enabled */ 2062 if ((enabled_port_mask & (1 << portid)) == 0) { 2063 printf("\nSkipping disabled port %d\n", portid); 2064 continue; 2065 } 2066 2067 /* init port */ 2068 printf("Initializing port %d ... ", portid); 2069 fflush(stdout); 2070 2071 nb_rx_queue = get_port_n_rx_queues(portid); 2072 n_tx_queue = nb_lcores; 2073 if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) 2074 n_tx_queue = MAX_TX_QUEUE_PER_PORT; 2075 printf("Creating queues: nb_rxq=%d nb_txq=%u... ", 2076 nb_rx_queue, (unsigned)n_tx_queue); 2077 2078 ret = rte_eth_dev_info_get(portid, &dev_info); 2079 if (ret != 0) 2080 rte_exit(EXIT_FAILURE, 2081 "Error during getting device (port %u) info: %s\n", 2082 portid, strerror(-ret)); 2083 2084 ret = config_port_max_pkt_len(&local_port_conf, &dev_info); 2085 if (ret != 0) 2086 rte_exit(EXIT_FAILURE, 2087 "Invalid max packet length: %u (port %u)\n", 2088 max_pkt_len, portid); 2089 2090 if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) 2091 local_port_conf.txmode.offloads |= 2092 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 2093 2094 local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 2095 dev_info.flow_type_rss_offloads; 2096 if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 2097 port_conf.rx_adv_conf.rss_conf.rss_hf) { 2098 printf("Port %u modified RSS hash function based on hardware support," 2099 "requested:%#"PRIx64" configured:%#"PRIx64"\n", 2100 portid, 2101 port_conf.rx_adv_conf.rss_conf.rss_hf, 2102 local_port_conf.rx_adv_conf.rss_conf.rss_hf); 2103 } 2104 2105 ret = rte_eth_dev_configure(portid, nb_rx_queue, 2106 (uint16_t)n_tx_queue, &local_port_conf); 2107 if (ret < 0) 2108 rte_exit(EXIT_FAILURE, 2109 "Cannot configure device: err=%d, port=%d\n", 2110 ret, portid); 2111 2112 ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 2113 &nb_txd); 2114 if (ret < 0) 2115 rte_exit(EXIT_FAILURE, 2116 "rte_eth_dev_adjust_nb_rx_tx_desc: err=%d, port=%d\n", 2117 ret, portid); 2118 2119 ret = rte_eth_macaddr_get(portid, &port_l2hdr[portid].src_addr); 2120 if (ret < 0) 2121 rte_exit(EXIT_FAILURE, 2122 "rte_eth_macaddr_get: err=%d, port=%d\n", 2123 ret, portid); 2124 2125 print_ethaddr("Dst MAC:", &port_l2hdr[portid].dst_addr); 2126 print_ethaddr(", Src MAC:", &port_l2hdr[portid].src_addr); 2127 printf(", "); 2128 2129 /* init memory */ 2130 ret = init_mem(NB_MBUF); 2131 if (ret < 0) 2132 rte_exit(EXIT_FAILURE, "init_mem failed\n"); 2133 2134 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2135 if (rte_lcore_is_enabled(lcore_id) == 0) 2136 continue; 2137 2138 /* Initialize TX buffers */ 2139 qconf = &lcore_conf[lcore_id]; 2140 qconf->tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", 2141 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, 2142 rte_eth_dev_socket_id(portid)); 2143 if (qconf->tx_buffer[portid] == NULL) 2144 rte_exit(EXIT_FAILURE, "Can't allocate tx buffer for port %u\n", 2145 (unsigned) portid); 2146 2147 rte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST); 2148 } 2149 2150 /* init one TX queue per couple (lcore,port) */ 2151 queueid = 0; 2152 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2153 if (rte_lcore_is_enabled(lcore_id) == 0) 2154 continue; 2155 2156 if (numa_on) 2157 socketid = (uint8_t) 2158 rte_lcore_to_socket_id(lcore_id); 2159 else 2160 socketid = 0; 2161 2162 printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); 2163 fflush(stdout); 2164 2165 ret = rte_eth_dev_info_get(portid, &dev_info); 2166 if (ret != 0) 2167 rte_exit(EXIT_FAILURE, 2168 "Error during getting device (port %u) info: %s\n", 2169 portid, strerror(-ret)); 2170 2171 txconf = &dev_info.default_txconf; 2172 txconf->offloads = local_port_conf.txmode.offloads; 2173 ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 2174 socketid, txconf); 2175 if (ret < 0) 2176 rte_exit(EXIT_FAILURE, 2177 "rte_eth_tx_queue_setup: err=%d, " 2178 "port=%d\n", ret, portid); 2179 2180 qconf = &lcore_conf[lcore_id]; 2181 qconf->tx_queue_id[portid] = queueid; 2182 queueid++; 2183 2184 qconf->tx_port_id[qconf->n_tx_port] = portid; 2185 qconf->n_tx_port++; 2186 } 2187 printf("\n"); 2188 } 2189 2190 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2191 if (rte_lcore_is_enabled(lcore_id) == 0) 2192 continue; 2193 qconf = &lcore_conf[lcore_id]; 2194 printf("\nInitializing rx queues on lcore %u ... ", lcore_id); 2195 fflush(stdout); 2196 /* init RX queues */ 2197 for (queue = 0; queue < qconf->n_rx_queue; ++queue) { 2198 struct rte_eth_rxconf rxq_conf; 2199 2200 portid = qconf->rx_queue_list[queue].port_id; 2201 queueid = qconf->rx_queue_list[queue].queue_id; 2202 2203 if (numa_on) 2204 socketid = (uint8_t) 2205 rte_lcore_to_socket_id(lcore_id); 2206 else 2207 socketid = 0; 2208 2209 printf("rxq=%d,%d,%d ", portid, queueid, socketid); 2210 fflush(stdout); 2211 2212 ret = rte_eth_dev_info_get(portid, &dev_info); 2213 if (ret != 0) 2214 rte_exit(EXIT_FAILURE, 2215 "Error during getting device (port %u) info: %s\n", 2216 portid, strerror(-ret)); 2217 2218 rxq_conf = dev_info.default_rxconf; 2219 rxq_conf.offloads = port_conf.rxmode.offloads; 2220 ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, 2221 socketid, &rxq_conf, 2222 pktmbuf_pool[socketid]); 2223 if (ret < 0) 2224 rte_exit(EXIT_FAILURE, 2225 "rte_eth_rx_queue_setup: err=%d," 2226 "port=%d\n", ret, portid); 2227 } 2228 } 2229 2230 printf("\n"); 2231 2232 /* start ports */ 2233 RTE_ETH_FOREACH_DEV(portid) { 2234 if ((enabled_port_mask & (1 << portid)) == 0) 2235 continue; 2236 2237 /* Start device */ 2238 ret = rte_eth_dev_start(portid); 2239 if (ret < 0) 2240 rte_exit(EXIT_FAILURE, 2241 "rte_eth_dev_start: err=%d, port=%d\n", 2242 ret, portid); 2243 2244 /* 2245 * If enabled, put device in promiscuous mode. 2246 * This allows IO forwarding mode to forward packets 2247 * to itself through 2 cross-connected ports of the 2248 * target machine. 2249 */ 2250 if (promiscuous_on) { 2251 ret = rte_eth_promiscuous_enable(portid); 2252 if (ret != 0) 2253 rte_exit(EXIT_FAILURE, 2254 "rte_eth_promiscuous_enable: err=%s, port=%u\n", 2255 rte_strerror(-ret), portid); 2256 } 2257 } 2258 2259 check_all_ports_link_status(enabled_port_mask); 2260 2261 /* launch per-lcore init on every lcore */ 2262 rte_eal_mp_remote_launch(main_loop, NULL, CALL_MAIN); 2263 RTE_LCORE_FOREACH_WORKER(lcore_id) { 2264 if (rte_eal_wait_lcore(lcore_id) < 0) 2265 return -1; 2266 } 2267 2268 /* clean up the EAL */ 2269 rte_eal_cleanup(); 2270 2271 return 0; 2272 } 2273