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