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