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