1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2015-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 <time.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <stdint.h> 39 #include <inttypes.h> 40 #include <sys/types.h> 41 #include <sys/queue.h> 42 #include <netinet/in.h> 43 #include <setjmp.h> 44 #include <stdarg.h> 45 #include <ctype.h> 46 #include <errno.h> 47 #include <getopt.h> 48 49 #include <rte_atomic.h> 50 #include <rte_branch_prediction.h> 51 #include <rte_common.h> 52 #include <rte_cryptodev.h> 53 #include <rte_cycles.h> 54 #include <rte_debug.h> 55 #include <rte_eal.h> 56 #include <rte_ether.h> 57 #include <rte_ethdev.h> 58 #include <rte_interrupts.h> 59 #include <rte_ip.h> 60 #include <rte_launch.h> 61 #include <rte_lcore.h> 62 #include <rte_log.h> 63 #include <rte_malloc.h> 64 #include <rte_mbuf.h> 65 #include <rte_mbuf_offload.h> 66 #include <rte_memcpy.h> 67 #include <rte_memory.h> 68 #include <rte_mempool.h> 69 #include <rte_memzone.h> 70 #include <rte_pci.h> 71 #include <rte_per_lcore.h> 72 #include <rte_prefetch.h> 73 #include <rte_random.h> 74 #include <rte_ring.h> 75 76 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 77 78 #define NB_MBUF 8192 79 80 #define MAX_PKT_BURST 32 81 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 82 83 /* 84 * Configurable number of RX/TX ring descriptors 85 */ 86 #define RTE_TEST_RX_DESC_DEFAULT 128 87 #define RTE_TEST_TX_DESC_DEFAULT 512 88 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 89 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 90 91 /* ethernet addresses of ports */ 92 static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; 93 94 /* mask of enabled ports */ 95 static uint64_t l2fwd_enabled_port_mask; 96 static uint64_t l2fwd_enabled_crypto_mask; 97 98 /* list of enabled ports */ 99 static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; 100 101 102 struct pkt_buffer { 103 unsigned len; 104 struct rte_mbuf *buffer[MAX_PKT_BURST]; 105 }; 106 107 #define MAX_RX_QUEUE_PER_LCORE 16 108 #define MAX_TX_QUEUE_PER_PORT 16 109 110 enum l2fwd_crypto_xform_chain { 111 L2FWD_CRYPTO_CIPHER_HASH, 112 L2FWD_CRYPTO_HASH_CIPHER 113 }; 114 115 /** l2fwd crypto application command line options */ 116 struct l2fwd_crypto_options { 117 unsigned portmask; 118 unsigned nb_ports_per_lcore; 119 unsigned refresh_period; 120 unsigned single_lcore:1; 121 122 enum rte_cryptodev_type cdev_type; 123 unsigned sessionless:1; 124 125 enum l2fwd_crypto_xform_chain xform_chain; 126 127 struct rte_crypto_sym_xform cipher_xform; 128 uint8_t ckey_data[32]; 129 130 struct rte_crypto_key iv_key; 131 uint8_t ivkey_data[16]; 132 133 struct rte_crypto_sym_xform auth_xform; 134 uint8_t akey_data[128]; 135 }; 136 137 /** l2fwd crypto lcore params */ 138 struct l2fwd_crypto_params { 139 uint8_t dev_id; 140 uint8_t qp_id; 141 142 unsigned digest_length; 143 unsigned block_size; 144 struct rte_crypto_key iv_key; 145 struct rte_cryptodev_sym_session *session; 146 }; 147 148 /** lcore configuration */ 149 struct lcore_queue_conf { 150 unsigned nb_rx_ports; 151 unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; 152 153 unsigned nb_crypto_devs; 154 unsigned cryptodev_list[MAX_RX_QUEUE_PER_LCORE]; 155 156 struct pkt_buffer crypto_pkt_buf[RTE_MAX_ETHPORTS]; 157 struct pkt_buffer tx_pkt_buf[RTE_MAX_ETHPORTS]; 158 } __rte_cache_aligned; 159 160 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; 161 162 static const struct rte_eth_conf port_conf = { 163 .rxmode = { 164 .split_hdr_size = 0, 165 .header_split = 0, /**< Header Split disabled */ 166 .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 167 .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 168 .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 169 .hw_strip_crc = 0, /**< CRC stripped by hardware */ 170 }, 171 .txmode = { 172 .mq_mode = ETH_MQ_TX_NONE, 173 }, 174 }; 175 176 struct rte_mempool *l2fwd_pktmbuf_pool; 177 struct rte_mempool *l2fwd_mbuf_ol_pool; 178 179 /* Per-port statistics struct */ 180 struct l2fwd_port_statistics { 181 uint64_t tx; 182 uint64_t rx; 183 184 uint64_t crypto_enqueued; 185 uint64_t crypto_dequeued; 186 187 uint64_t dropped; 188 } __rte_cache_aligned; 189 190 struct l2fwd_crypto_statistics { 191 uint64_t enqueued; 192 uint64_t dequeued; 193 194 uint64_t errors; 195 } __rte_cache_aligned; 196 197 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; 198 struct l2fwd_crypto_statistics crypto_statistics[RTE_MAX_ETHPORTS]; 199 200 /* A tsc-based timer responsible for triggering statistics printout */ 201 #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ 202 #define MAX_TIMER_PERIOD 86400 /* 1 day max */ 203 204 /* default period is 10 seconds */ 205 static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; 206 207 /* Print out statistics on packets dropped */ 208 static void 209 print_stats(void) 210 { 211 uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; 212 uint64_t total_packets_enqueued, total_packets_dequeued, 213 total_packets_errors; 214 unsigned portid; 215 uint64_t cdevid; 216 217 total_packets_dropped = 0; 218 total_packets_tx = 0; 219 total_packets_rx = 0; 220 total_packets_enqueued = 0; 221 total_packets_dequeued = 0; 222 total_packets_errors = 0; 223 224 const char clr[] = { 27, '[', '2', 'J', '\0' }; 225 const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 226 227 /* Clear screen and move to top left */ 228 printf("%s%s", clr, topLeft); 229 230 printf("\nPort statistics ===================================="); 231 232 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 233 /* skip disabled ports */ 234 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 235 continue; 236 printf("\nStatistics for port %u ------------------------------" 237 "\nPackets sent: %32"PRIu64 238 "\nPackets received: %28"PRIu64 239 "\nPackets dropped: %29"PRIu64, 240 portid, 241 port_statistics[portid].tx, 242 port_statistics[portid].rx, 243 port_statistics[portid].dropped); 244 245 total_packets_dropped += port_statistics[portid].dropped; 246 total_packets_tx += port_statistics[portid].tx; 247 total_packets_rx += port_statistics[portid].rx; 248 } 249 printf("\nCrypto statistics =================================="); 250 251 for (cdevid = 0; cdevid < RTE_CRYPTO_MAX_DEVS; cdevid++) { 252 /* skip disabled ports */ 253 if ((l2fwd_enabled_crypto_mask & (1lu << cdevid)) == 0) 254 continue; 255 printf("\nStatistics for cryptodev %"PRIu64 256 " -------------------------" 257 "\nPackets enqueued: %28"PRIu64 258 "\nPackets dequeued: %28"PRIu64 259 "\nPackets errors: %30"PRIu64, 260 cdevid, 261 crypto_statistics[cdevid].enqueued, 262 crypto_statistics[cdevid].dequeued, 263 crypto_statistics[cdevid].errors); 264 265 total_packets_enqueued += crypto_statistics[cdevid].enqueued; 266 total_packets_dequeued += crypto_statistics[cdevid].dequeued; 267 total_packets_errors += crypto_statistics[cdevid].errors; 268 } 269 printf("\nAggregate statistics ===============================" 270 "\nTotal packets received: %22"PRIu64 271 "\nTotal packets enqueued: %22"PRIu64 272 "\nTotal packets dequeued: %22"PRIu64 273 "\nTotal packets sent: %26"PRIu64 274 "\nTotal packets dropped: %23"PRIu64 275 "\nTotal packets crypto errors: %17"PRIu64, 276 total_packets_rx, 277 total_packets_enqueued, 278 total_packets_dequeued, 279 total_packets_tx, 280 total_packets_dropped, 281 total_packets_errors); 282 printf("\n====================================================\n"); 283 } 284 285 286 287 static int 288 l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n, 289 struct l2fwd_crypto_params *cparams) 290 { 291 struct rte_mbuf **pkt_buffer; 292 unsigned ret; 293 294 pkt_buffer = (struct rte_mbuf **) 295 qconf->crypto_pkt_buf[cparams->dev_id].buffer; 296 297 ret = rte_cryptodev_enqueue_burst(cparams->dev_id, cparams->qp_id, 298 pkt_buffer, (uint16_t) n); 299 crypto_statistics[cparams->dev_id].enqueued += ret; 300 if (unlikely(ret < n)) { 301 crypto_statistics[cparams->dev_id].errors += (n - ret); 302 do { 303 rte_pktmbuf_offload_free(pkt_buffer[ret]->offload_ops); 304 rte_pktmbuf_free(pkt_buffer[ret]); 305 } while (++ret < n); 306 } 307 308 return 0; 309 } 310 311 static int 312 l2fwd_crypto_enqueue(struct rte_mbuf *m, struct l2fwd_crypto_params *cparams) 313 { 314 unsigned lcore_id, len; 315 struct lcore_queue_conf *qconf; 316 317 lcore_id = rte_lcore_id(); 318 319 qconf = &lcore_queue_conf[lcore_id]; 320 len = qconf->crypto_pkt_buf[cparams->dev_id].len; 321 qconf->crypto_pkt_buf[cparams->dev_id].buffer[len] = m; 322 len++; 323 324 /* enough pkts to be sent */ 325 if (len == MAX_PKT_BURST) { 326 l2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams); 327 len = 0; 328 } 329 330 qconf->crypto_pkt_buf[cparams->dev_id].len = len; 331 return 0; 332 } 333 334 static int 335 l2fwd_simple_crypto_enqueue(struct rte_mbuf *m, 336 struct rte_mbuf_offload *ol, 337 struct l2fwd_crypto_params *cparams) 338 { 339 struct ether_hdr *eth_hdr; 340 struct ipv4_hdr *ip_hdr; 341 342 unsigned ipdata_offset, pad_len, data_len; 343 char *padding; 344 345 eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); 346 347 if (eth_hdr->ether_type != rte_cpu_to_be_16(ETHER_TYPE_IPv4)) 348 return -1; 349 350 ipdata_offset = sizeof(struct ether_hdr); 351 352 ip_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(m, char *) + 353 ipdata_offset); 354 355 ipdata_offset += (ip_hdr->version_ihl & IPV4_HDR_IHL_MASK) 356 * IPV4_IHL_MULTIPLIER; 357 358 359 /* Zero pad data to be crypto'd so it is block aligned */ 360 data_len = rte_pktmbuf_data_len(m) - ipdata_offset; 361 pad_len = data_len % cparams->block_size ? cparams->block_size - 362 (data_len % cparams->block_size) : 0; 363 364 if (pad_len) { 365 padding = rte_pktmbuf_append(m, pad_len); 366 if (unlikely(!padding)) 367 return -1; 368 369 data_len += pad_len; 370 memset(padding, 0, pad_len); 371 } 372 373 /* Set crypto operation data parameters */ 374 rte_crypto_sym_op_attach_session(&ol->op.crypto, cparams->session); 375 376 /* Append space for digest to end of packet */ 377 ol->op.crypto.digest.data = (uint8_t *)rte_pktmbuf_append(m, 378 cparams->digest_length); 379 ol->op.crypto.digest.phys_addr = rte_pktmbuf_mtophys_offset(m, 380 rte_pktmbuf_pkt_len(m) - cparams->digest_length); 381 ol->op.crypto.digest.length = cparams->digest_length; 382 383 ol->op.crypto.iv.data = cparams->iv_key.data; 384 ol->op.crypto.iv.phys_addr = cparams->iv_key.phys_addr; 385 ol->op.crypto.iv.length = cparams->iv_key.length; 386 387 ol->op.crypto.data.to_cipher.offset = ipdata_offset; 388 ol->op.crypto.data.to_cipher.length = data_len; 389 390 ol->op.crypto.data.to_hash.offset = ipdata_offset; 391 ol->op.crypto.data.to_hash.length = data_len; 392 393 rte_pktmbuf_offload_attach(m, ol); 394 395 return l2fwd_crypto_enqueue(m, cparams); 396 } 397 398 399 /* Send the burst of packets on an output interface */ 400 static int 401 l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port) 402 { 403 struct rte_mbuf **pkt_buffer; 404 unsigned ret; 405 unsigned queueid = 0; 406 407 pkt_buffer = (struct rte_mbuf **)qconf->tx_pkt_buf[port].buffer; 408 409 ret = rte_eth_tx_burst(port, (uint16_t) queueid, pkt_buffer, 410 (uint16_t)n); 411 port_statistics[port].tx += ret; 412 if (unlikely(ret < n)) { 413 port_statistics[port].dropped += (n - ret); 414 do { 415 rte_pktmbuf_free(pkt_buffer[ret]); 416 } while (++ret < n); 417 } 418 419 return 0; 420 } 421 422 /* Enqueue packets for TX and prepare them to be sent */ 423 static int 424 l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) 425 { 426 unsigned lcore_id, len; 427 struct lcore_queue_conf *qconf; 428 429 lcore_id = rte_lcore_id(); 430 431 qconf = &lcore_queue_conf[lcore_id]; 432 len = qconf->tx_pkt_buf[port].len; 433 qconf->tx_pkt_buf[port].buffer[len] = m; 434 len++; 435 436 /* enough pkts to be sent */ 437 if (unlikely(len == MAX_PKT_BURST)) { 438 l2fwd_send_burst(qconf, MAX_PKT_BURST, port); 439 len = 0; 440 } 441 442 qconf->tx_pkt_buf[port].len = len; 443 return 0; 444 } 445 446 static void 447 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) 448 { 449 struct ether_hdr *eth; 450 void *tmp; 451 unsigned dst_port; 452 453 dst_port = l2fwd_dst_ports[portid]; 454 eth = rte_pktmbuf_mtod(m, struct ether_hdr *); 455 456 /* 02:00:00:00:00:xx */ 457 tmp = ð->d_addr.addr_bytes[0]; 458 *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); 459 460 /* src addr */ 461 ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); 462 463 l2fwd_send_packet(m, (uint8_t) dst_port); 464 } 465 466 /** Generate random key */ 467 static void 468 generate_random_key(uint8_t *key, unsigned length) 469 { 470 unsigned i; 471 472 for (i = 0; i < length; i++) 473 key[i] = rand() % 0xff; 474 } 475 476 static struct rte_cryptodev_sym_session * 477 initialize_crypto_session(struct l2fwd_crypto_options *options, 478 uint8_t cdev_id) 479 { 480 struct rte_crypto_sym_xform *first_xform; 481 482 if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) { 483 first_xform = &options->cipher_xform; 484 first_xform->next = &options->auth_xform; 485 } else { 486 first_xform = &options->auth_xform; 487 first_xform->next = &options->cipher_xform; 488 } 489 490 /* Setup Cipher Parameters */ 491 return rte_cryptodev_sym_session_create(cdev_id, first_xform); 492 } 493 494 static void 495 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options); 496 497 /* main processing loop */ 498 static void 499 l2fwd_main_loop(struct l2fwd_crypto_options *options) 500 { 501 struct rte_mbuf *m, *pkts_burst[MAX_PKT_BURST]; 502 unsigned lcore_id = rte_lcore_id(); 503 uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0; 504 unsigned i, j, portid, nb_rx; 505 struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; 506 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / 507 US_PER_S * BURST_TX_DRAIN_US; 508 struct l2fwd_crypto_params *cparams; 509 struct l2fwd_crypto_params port_cparams[qconf->nb_crypto_devs]; 510 511 if (qconf->nb_rx_ports == 0) { 512 RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); 513 return; 514 } 515 516 RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); 517 518 l2fwd_crypto_options_print(options); 519 520 for (i = 0; i < qconf->nb_rx_ports; i++) { 521 522 portid = qconf->rx_port_list[i]; 523 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, 524 portid); 525 } 526 527 for (i = 0; i < qconf->nb_crypto_devs; i++) { 528 port_cparams[i].dev_id = qconf->cryptodev_list[i]; 529 port_cparams[i].qp_id = 0; 530 531 port_cparams[i].block_size = 64; 532 port_cparams[i].digest_length = 20; 533 534 port_cparams[i].iv_key.data = 535 (uint8_t *)rte_malloc(NULL, 16, 8); 536 port_cparams[i].iv_key.length = 16; 537 port_cparams[i].iv_key.phys_addr = rte_malloc_virt2phy( 538 (void *)port_cparams[i].iv_key.data); 539 generate_random_key(port_cparams[i].iv_key.data, 540 sizeof(cparams[i].iv_key.length)); 541 542 port_cparams[i].session = initialize_crypto_session(options, 543 port_cparams[i].dev_id); 544 545 if (port_cparams[i].session == NULL) 546 return; 547 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u cryptoid=%u\n", lcore_id, 548 port_cparams[i].dev_id); 549 } 550 551 while (1) { 552 553 cur_tsc = rte_rdtsc(); 554 555 /* 556 * TX burst queue drain 557 */ 558 diff_tsc = cur_tsc - prev_tsc; 559 if (unlikely(diff_tsc > drain_tsc)) { 560 561 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 562 if (qconf->tx_pkt_buf[portid].len == 0) 563 continue; 564 l2fwd_send_burst(&lcore_queue_conf[lcore_id], 565 qconf->tx_pkt_buf[portid].len, 566 (uint8_t) portid); 567 qconf->tx_pkt_buf[portid].len = 0; 568 } 569 570 /* if timer is enabled */ 571 if (timer_period > 0) { 572 573 /* advance the timer */ 574 timer_tsc += diff_tsc; 575 576 /* if timer has reached its timeout */ 577 if (unlikely(timer_tsc >= 578 (uint64_t)timer_period)) { 579 580 /* do this only on master core */ 581 if (lcore_id == rte_get_master_lcore() 582 && options->refresh_period) { 583 print_stats(); 584 timer_tsc = 0; 585 } 586 } 587 } 588 589 prev_tsc = cur_tsc; 590 } 591 592 /* 593 * Read packet from RX queues 594 */ 595 for (i = 0; i < qconf->nb_rx_ports; i++) { 596 struct rte_mbuf_offload *ol; 597 598 portid = qconf->rx_port_list[i]; 599 600 cparams = &port_cparams[i]; 601 602 nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, 603 pkts_burst, MAX_PKT_BURST); 604 605 port_statistics[portid].rx += nb_rx; 606 607 /* Enqueue packets from Crypto device*/ 608 for (j = 0; j < nb_rx; j++) { 609 m = pkts_burst[j]; 610 ol = rte_pktmbuf_offload_alloc( 611 l2fwd_mbuf_ol_pool, 612 RTE_PKTMBUF_OL_CRYPTO_SYM); 613 /* 614 * If we can't allocate a offload, then drop 615 * the rest of the burst and dequeue and 616 * process the packets to free offload structs 617 */ 618 if (unlikely(ol == NULL)) { 619 for (; j < nb_rx; j++) { 620 rte_pktmbuf_free(pkts_burst[j]); 621 port_statistics[portid].dropped++; 622 } 623 break; 624 } 625 626 rte_prefetch0(rte_pktmbuf_mtod(m, void *)); 627 rte_prefetch0((void *)ol); 628 629 l2fwd_simple_crypto_enqueue(m, ol, cparams); 630 } 631 632 /* Dequeue packets from Crypto device */ 633 nb_rx = rte_cryptodev_dequeue_burst( 634 cparams->dev_id, cparams->qp_id, 635 pkts_burst, MAX_PKT_BURST); 636 crypto_statistics[cparams->dev_id].dequeued += nb_rx; 637 638 /* Forward crypto'd packets */ 639 for (j = 0; j < nb_rx; j++) { 640 m = pkts_burst[j]; 641 rte_pktmbuf_offload_free(m->offload_ops); 642 rte_prefetch0(rte_pktmbuf_mtod(m, void *)); 643 l2fwd_simple_forward(m, portid); 644 } 645 } 646 } 647 } 648 649 static int 650 l2fwd_launch_one_lcore(void *arg) 651 { 652 l2fwd_main_loop((struct l2fwd_crypto_options *)arg); 653 return 0; 654 } 655 656 /* Display command line arguments usage */ 657 static void 658 l2fwd_crypto_usage(const char *prgname) 659 { 660 printf("%s [EAL options] -- --cdev TYPE [optional parameters]\n" 661 " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 662 " -q NQ: number of queue (=ports) per lcore (default is 1)\n" 663 " -s manage all ports from single lcore" 664 " -t PERIOD: statistics will be refreshed each PERIOD seconds" 665 " (0 to disable, 10 default, 86400 maximum)\n" 666 667 " --cdev AESNI_MB / QAT\n" 668 " --chain HASH_CIPHER / CIPHER_HASH\n" 669 670 " --cipher_algo ALGO\n" 671 " --cipher_op ENCRYPT / DECRYPT\n" 672 " --cipher_key KEY\n" 673 " --iv IV\n" 674 675 " --auth_algo ALGO\n" 676 " --auth_op GENERATE / VERIFY\n" 677 " --auth_key KEY\n" 678 679 " --sessionless\n", 680 prgname); 681 } 682 683 /** Parse crypto device type command line argument */ 684 static int 685 parse_cryptodev_type(enum rte_cryptodev_type *type, char *optarg) 686 { 687 if (strcmp("AESNI_MB", optarg) == 0) { 688 *type = RTE_CRYPTODEV_AESNI_MB_PMD; 689 return 0; 690 } else if (strcmp("QAT", optarg) == 0) { 691 *type = RTE_CRYPTODEV_QAT_SYM_PMD; 692 return 0; 693 } 694 695 return -1; 696 } 697 698 /** Parse crypto chain xform command line argument */ 699 static int 700 parse_crypto_opt_chain(struct l2fwd_crypto_options *options, char *optarg) 701 { 702 if (strcmp("CIPHER_HASH", optarg) == 0) { 703 options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH; 704 return 0; 705 } else if (strcmp("HASH_CIPHER", optarg) == 0) { 706 options->xform_chain = L2FWD_CRYPTO_HASH_CIPHER; 707 return 0; 708 } 709 710 return -1; 711 } 712 713 /** Parse crypto cipher algo option command line argument */ 714 static int 715 parse_cipher_algo(enum rte_crypto_cipher_algorithm *algo, char *optarg) 716 { 717 if (strcmp("AES_CBC", optarg) == 0) { 718 *algo = RTE_CRYPTO_CIPHER_AES_CBC; 719 return 0; 720 } else if (strcmp("AES_GCM", optarg) == 0) { 721 *algo = RTE_CRYPTO_CIPHER_AES_GCM; 722 return 0; 723 } 724 725 printf("Cipher algorithm not supported!\n"); 726 return -1; 727 } 728 729 /** Parse crypto cipher operation command line argument */ 730 static int 731 parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg) 732 { 733 if (strcmp("ENCRYPT", optarg) == 0) { 734 *op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 735 return 0; 736 } else if (strcmp("DECRYPT", optarg) == 0) { 737 *op = RTE_CRYPTO_CIPHER_OP_DECRYPT; 738 return 0; 739 } 740 741 printf("Cipher operation not supported!\n"); 742 return -1; 743 } 744 745 /** Parse crypto key command line argument */ 746 static int 747 parse_key(struct rte_crypto_key *key __rte_unused, 748 unsigned length __rte_unused, char *arg __rte_unused) 749 { 750 printf("Currently an unsupported argument!\n"); 751 return -1; 752 } 753 754 /** Parse crypto cipher operation command line argument */ 755 static int 756 parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg) 757 { 758 if (strcmp("SHA1", optarg) == 0) { 759 *algo = RTE_CRYPTO_AUTH_SHA1; 760 return 0; 761 } else if (strcmp("SHA1_HMAC", optarg) == 0) { 762 *algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 763 return 0; 764 } else if (strcmp("SHA224", optarg) == 0) { 765 *algo = RTE_CRYPTO_AUTH_SHA224; 766 return 0; 767 } else if (strcmp("SHA224_HMAC", optarg) == 0) { 768 *algo = RTE_CRYPTO_AUTH_SHA224_HMAC; 769 return 0; 770 } else if (strcmp("SHA256", optarg) == 0) { 771 *algo = RTE_CRYPTO_AUTH_SHA256; 772 return 0; 773 } else if (strcmp("SHA256_HMAC", optarg) == 0) { 774 *algo = RTE_CRYPTO_AUTH_SHA256_HMAC; 775 return 0; 776 } else if (strcmp("SHA512", optarg) == 0) { 777 *algo = RTE_CRYPTO_AUTH_SHA256; 778 return 0; 779 } else if (strcmp("SHA512_HMAC", optarg) == 0) { 780 *algo = RTE_CRYPTO_AUTH_SHA256_HMAC; 781 return 0; 782 } 783 784 printf("Authentication algorithm specified not supported!\n"); 785 return -1; 786 } 787 788 static int 789 parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg) 790 { 791 if (strcmp("VERIFY", optarg) == 0) { 792 *op = RTE_CRYPTO_AUTH_OP_VERIFY; 793 return 0; 794 } else if (strcmp("GENERATE", optarg) == 0) { 795 *op = RTE_CRYPTO_AUTH_OP_GENERATE; 796 return 0; 797 } 798 799 printf("Authentication operation specified not supported!\n"); 800 return -1; 801 } 802 803 /** Parse long options */ 804 static int 805 l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options, 806 struct option *lgopts, int option_index) 807 { 808 if (strcmp(lgopts[option_index].name, "cdev_type") == 0) 809 return parse_cryptodev_type(&options->cdev_type, optarg); 810 811 else if (strcmp(lgopts[option_index].name, "chain") == 0) 812 return parse_crypto_opt_chain(options, optarg); 813 814 /* Cipher options */ 815 else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0) 816 return parse_cipher_algo(&options->cipher_xform.cipher.algo, 817 optarg); 818 819 else if (strcmp(lgopts[option_index].name, "cipher_op") == 0) 820 return parse_cipher_op(&options->cipher_xform.cipher.op, 821 optarg); 822 823 else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) 824 return parse_key(&options->cipher_xform.cipher.key, 825 sizeof(options->ckey_data), optarg); 826 827 else if (strcmp(lgopts[option_index].name, "iv") == 0) 828 return parse_key(&options->iv_key, sizeof(options->ivkey_data), 829 optarg); 830 831 /* Authentication options */ 832 else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) 833 return parse_auth_algo(&options->auth_xform.auth.algo, 834 optarg); 835 836 else if (strcmp(lgopts[option_index].name, "auth_op") == 0) 837 return parse_auth_op(&options->auth_xform.auth.op, 838 optarg); 839 840 else if (strcmp(lgopts[option_index].name, "auth_key") == 0) 841 return parse_key(&options->auth_xform.auth.key, 842 sizeof(options->akey_data), optarg); 843 844 else if (strcmp(lgopts[option_index].name, "sessionless") == 0) { 845 options->sessionless = 1; 846 return 0; 847 } 848 849 return -1; 850 } 851 852 /** Parse port mask */ 853 static int 854 l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options, 855 const char *q_arg) 856 { 857 char *end = NULL; 858 unsigned long pm; 859 860 /* parse hexadecimal string */ 861 pm = strtoul(q_arg, &end, 16); 862 if ((pm == '\0') || (end == NULL) || (*end != '\0')) 863 pm = 0; 864 865 options->portmask = pm; 866 if (options->portmask == 0) { 867 printf("invalid portmask specified\n"); 868 return -1; 869 } 870 871 return pm; 872 } 873 874 /** Parse number of queues */ 875 static int 876 l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options, 877 const char *q_arg) 878 { 879 char *end = NULL; 880 unsigned long n; 881 882 /* parse hexadecimal string */ 883 n = strtoul(q_arg, &end, 10); 884 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 885 n = 0; 886 else if (n >= MAX_RX_QUEUE_PER_LCORE) 887 n = 0; 888 889 options->nb_ports_per_lcore = n; 890 if (options->nb_ports_per_lcore == 0) { 891 printf("invalid number of ports selected\n"); 892 return -1; 893 } 894 895 return 0; 896 } 897 898 /** Parse timer period */ 899 static int 900 l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options, 901 const char *q_arg) 902 { 903 char *end = NULL; 904 long int n; 905 906 /* parse number string */ 907 n = strtol(q_arg, &end, 10); 908 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 909 n = 0; 910 911 if (n >= MAX_TIMER_PERIOD) { 912 printf("Warning refresh period specified %ld is greater than " 913 "max value %d! using max value", 914 n, MAX_TIMER_PERIOD); 915 n = MAX_TIMER_PERIOD; 916 } 917 918 options->refresh_period = n * 1000 * TIMER_MILLISECOND; 919 920 return 0; 921 } 922 923 /** Generate default options for application */ 924 static void 925 l2fwd_crypto_default_options(struct l2fwd_crypto_options *options) 926 { 927 srand(time(NULL)); 928 929 options->portmask = 0xffffffff; 930 options->nb_ports_per_lcore = 1; 931 options->refresh_period = 10000; 932 options->single_lcore = 0; 933 934 options->cdev_type = RTE_CRYPTODEV_AESNI_MB_PMD; 935 options->sessionless = 0; 936 options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH; 937 938 /* Cipher Data */ 939 options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 940 options->cipher_xform.next = NULL; 941 942 options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC; 943 options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 944 945 generate_random_key(options->ckey_data, sizeof(options->ckey_data)); 946 947 options->cipher_xform.cipher.key.data = options->ckey_data; 948 options->cipher_xform.cipher.key.length = 16; 949 950 951 /* Authentication Data */ 952 options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH; 953 options->auth_xform.next = NULL; 954 955 options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 956 options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 957 958 options->auth_xform.auth.add_auth_data_length = 0; 959 options->auth_xform.auth.digest_length = 20; 960 961 generate_random_key(options->akey_data, sizeof(options->akey_data)); 962 963 options->auth_xform.auth.key.data = options->akey_data; 964 options->auth_xform.auth.key.length = 20; 965 } 966 967 static void 968 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options) 969 { 970 printf("Options:-\nn"); 971 printf("portmask: %x\n", options->portmask); 972 printf("ports per lcore: %u\n", options->nb_ports_per_lcore); 973 printf("refresh period : %u\n", options->refresh_period); 974 printf("single lcore mode: %s\n", 975 options->single_lcore ? "enabled" : "disabled"); 976 printf("stats_printing: %s\n", 977 options->refresh_period == 0 ? "disabled" : "enabled"); 978 979 switch (options->cdev_type) { 980 case RTE_CRYPTODEV_AESNI_MB_PMD: 981 printf("cryptodev type: AES-NI MB PMD\n"); break; 982 case RTE_CRYPTODEV_QAT_SYM_PMD: 983 printf("cryptodev type: QAT PMD\n"); break; 984 default: 985 break; 986 } 987 988 printf("sessionless crypto: %s\n", 989 options->sessionless ? "enabled" : "disabled"); 990 #if 0 991 options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH; 992 993 /* Cipher Data */ 994 options->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER; 995 options->cipher_xform.next = NULL; 996 997 options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC; 998 options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 999 1000 generate_random_key(options->ckey_data, sizeof(options->ckey_data)); 1001 1002 options->cipher_xform.cipher.key.data = options->ckey_data; 1003 options->cipher_xform.cipher.key.phys_addr = 0; 1004 options->cipher_xform.cipher.key.length = 16; 1005 1006 1007 /* Authentication Data */ 1008 options->auth_xform.type = RTE_CRYPTO_XFORM_AUTH; 1009 options->auth_xform.next = NULL; 1010 1011 options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC; 1012 options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 1013 1014 options->auth_xform.auth.add_auth_data_length = 0; 1015 options->auth_xform.auth.digest_length = 20; 1016 1017 generate_random_key(options->akey_data, sizeof(options->akey_data)); 1018 1019 options->auth_xform.auth.key.data = options->akey_data; 1020 options->auth_xform.auth.key.phys_addr = 0; 1021 options->auth_xform.auth.key.length = 20; 1022 #endif 1023 } 1024 1025 /* Parse the argument given in the command line of the application */ 1026 static int 1027 l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options, 1028 int argc, char **argv) 1029 { 1030 int opt, retval, option_index; 1031 char **argvopt = argv, *prgname = argv[0]; 1032 1033 static struct option lgopts[] = { 1034 { "sessionless", no_argument, 0, 0 }, 1035 1036 { "cdev_type", required_argument, 0, 0 }, 1037 { "chain", required_argument, 0, 0 }, 1038 1039 { "cipher_algo", required_argument, 0, 0 }, 1040 { "cipher_op", required_argument, 0, 0 }, 1041 { "cipher_key", required_argument, 0, 0 }, 1042 1043 { "auth_algo", required_argument, 0, 0 }, 1044 { "auth_op", required_argument, 0, 0 }, 1045 { "auth_key", required_argument, 0, 0 }, 1046 1047 { "iv", required_argument, 0, 0 }, 1048 1049 { "sessionless", no_argument, 0, 0 }, 1050 { NULL, 0, 0, 0 } 1051 }; 1052 1053 l2fwd_crypto_default_options(options); 1054 1055 while ((opt = getopt_long(argc, argvopt, "p:q:st:", lgopts, 1056 &option_index)) != EOF) { 1057 switch (opt) { 1058 /* long options */ 1059 case 0: 1060 retval = l2fwd_crypto_parse_args_long_options(options, 1061 lgopts, option_index); 1062 if (retval < 0) { 1063 l2fwd_crypto_usage(prgname); 1064 return -1; 1065 } 1066 break; 1067 1068 /* portmask */ 1069 case 'p': 1070 retval = l2fwd_crypto_parse_portmask(options, optarg); 1071 if (retval < 0) { 1072 l2fwd_crypto_usage(prgname); 1073 return -1; 1074 } 1075 break; 1076 1077 /* nqueue */ 1078 case 'q': 1079 retval = l2fwd_crypto_parse_nqueue(options, optarg); 1080 if (retval < 0) { 1081 l2fwd_crypto_usage(prgname); 1082 return -1; 1083 } 1084 break; 1085 1086 /* single */ 1087 case 's': 1088 options->single_lcore = 1; 1089 1090 break; 1091 1092 /* timer period */ 1093 case 't': 1094 retval = l2fwd_crypto_parse_timer_period(options, 1095 optarg); 1096 if (retval < 0) { 1097 l2fwd_crypto_usage(prgname); 1098 return -1; 1099 } 1100 break; 1101 1102 default: 1103 l2fwd_crypto_usage(prgname); 1104 return -1; 1105 } 1106 } 1107 1108 1109 if (optind >= 0) 1110 argv[optind-1] = prgname; 1111 1112 retval = optind-1; 1113 optind = 0; /* reset getopt lib */ 1114 1115 return retval; 1116 } 1117 1118 /* Check the link status of all ports in up to 9s, and print them finally */ 1119 static void 1120 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 1121 { 1122 #define CHECK_INTERVAL 100 /* 100ms */ 1123 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1124 uint8_t portid, count, all_ports_up, print_flag = 0; 1125 struct rte_eth_link link; 1126 1127 printf("\nChecking link status"); 1128 fflush(stdout); 1129 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1130 all_ports_up = 1; 1131 for (portid = 0; portid < port_num; portid++) { 1132 if ((port_mask & (1 << portid)) == 0) 1133 continue; 1134 memset(&link, 0, sizeof(link)); 1135 rte_eth_link_get_nowait(portid, &link); 1136 /* print link status if flag set */ 1137 if (print_flag == 1) { 1138 if (link.link_status) 1139 printf("Port %d Link Up - speed %u " 1140 "Mbps - %s\n", (uint8_t)portid, 1141 (unsigned)link.link_speed, 1142 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1143 ("full-duplex") : ("half-duplex\n")); 1144 else 1145 printf("Port %d Link Down\n", 1146 (uint8_t)portid); 1147 continue; 1148 } 1149 /* clear all_ports_up flag if any link down */ 1150 if (link.link_status == 0) { 1151 all_ports_up = 0; 1152 break; 1153 } 1154 } 1155 /* after finally printing all link status, get out */ 1156 if (print_flag == 1) 1157 break; 1158 1159 if (all_ports_up == 0) { 1160 printf("."); 1161 fflush(stdout); 1162 rte_delay_ms(CHECK_INTERVAL); 1163 } 1164 1165 /* set the print_flag if all ports up or timeout */ 1166 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1167 print_flag = 1; 1168 printf("done\n"); 1169 } 1170 } 1171 } 1172 1173 static int 1174 initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports) 1175 { 1176 unsigned i, cdev_id, cdev_count, enabled_cdev_count = 0; 1177 int retval; 1178 1179 if (options->cdev_type == RTE_CRYPTODEV_QAT_SYM_PMD) { 1180 if (rte_cryptodev_count() < nb_ports) 1181 return -1; 1182 } else if (options->cdev_type == RTE_CRYPTODEV_AESNI_MB_PMD) { 1183 for (i = 0; i < nb_ports; i++) { 1184 int retval = rte_eal_vdev_init(CRYPTODEV_NAME_AESNI_MB_PMD, 1185 NULL); 1186 if (retval < 0) 1187 return -1; 1188 } 1189 } 1190 1191 cdev_count = rte_cryptodev_count(); 1192 for (cdev_id = 0; 1193 cdev_id < cdev_count && enabled_cdev_count < nb_ports; 1194 cdev_id++) { 1195 struct rte_cryptodev_qp_conf qp_conf; 1196 struct rte_cryptodev_info dev_info; 1197 1198 struct rte_cryptodev_config conf = { 1199 .nb_queue_pairs = 1, 1200 .socket_id = SOCKET_ID_ANY, 1201 .session_mp = { 1202 .nb_objs = 2048, 1203 .cache_size = 64 1204 } 1205 }; 1206 1207 rte_cryptodev_info_get(cdev_id, &dev_info); 1208 1209 if (dev_info.dev_type != options->cdev_type) 1210 continue; 1211 1212 1213 retval = rte_cryptodev_configure(cdev_id, &conf); 1214 if (retval < 0) { 1215 printf("Failed to configure cryptodev %u", cdev_id); 1216 return -1; 1217 } 1218 1219 qp_conf.nb_descriptors = 2048; 1220 1221 retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf, 1222 SOCKET_ID_ANY); 1223 if (retval < 0) { 1224 printf("Failed to setup queue pair %u on cryptodev %u", 1225 0, cdev_id); 1226 return -1; 1227 } 1228 1229 l2fwd_enabled_crypto_mask |= (1 << cdev_id); 1230 1231 enabled_cdev_count++; 1232 } 1233 1234 return enabled_cdev_count; 1235 } 1236 1237 static int 1238 initialize_ports(struct l2fwd_crypto_options *options) 1239 { 1240 uint8_t last_portid, portid; 1241 unsigned enabled_portcount = 0; 1242 unsigned nb_ports = rte_eth_dev_count(); 1243 1244 if (nb_ports == 0) { 1245 printf("No Ethernet ports - bye\n"); 1246 return -1; 1247 } 1248 1249 if (nb_ports > RTE_MAX_ETHPORTS) 1250 nb_ports = RTE_MAX_ETHPORTS; 1251 1252 /* Reset l2fwd_dst_ports */ 1253 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) 1254 l2fwd_dst_ports[portid] = 0; 1255 1256 for (last_portid = 0, portid = 0; portid < nb_ports; portid++) { 1257 int retval; 1258 1259 /* Skip ports that are not enabled */ 1260 if ((options->portmask & (1 << portid)) == 0) 1261 continue; 1262 1263 /* init port */ 1264 printf("Initializing port %u... ", (unsigned) portid); 1265 fflush(stdout); 1266 retval = rte_eth_dev_configure(portid, 1, 1, &port_conf); 1267 if (retval < 0) { 1268 printf("Cannot configure device: err=%d, port=%u\n", 1269 retval, (unsigned) portid); 1270 return -1; 1271 } 1272 1273 /* init one RX queue */ 1274 fflush(stdout); 1275 retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd, 1276 rte_eth_dev_socket_id(portid), 1277 NULL, l2fwd_pktmbuf_pool); 1278 if (retval < 0) { 1279 printf("rte_eth_rx_queue_setup:err=%d, port=%u\n", 1280 retval, (unsigned) portid); 1281 return -1; 1282 } 1283 1284 /* init one TX queue on each port */ 1285 fflush(stdout); 1286 retval = rte_eth_tx_queue_setup(portid, 0, nb_txd, 1287 rte_eth_dev_socket_id(portid), 1288 NULL); 1289 if (retval < 0) { 1290 printf("rte_eth_tx_queue_setup:err=%d, port=%u\n", 1291 retval, (unsigned) portid); 1292 1293 return -1; 1294 } 1295 1296 /* Start device */ 1297 retval = rte_eth_dev_start(portid); 1298 if (retval < 0) { 1299 printf("rte_eth_dev_start:err=%d, port=%u\n", 1300 retval, (unsigned) portid); 1301 return -1; 1302 } 1303 1304 rte_eth_promiscuous_enable(portid); 1305 1306 rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]); 1307 1308 printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", 1309 (unsigned) portid, 1310 l2fwd_ports_eth_addr[portid].addr_bytes[0], 1311 l2fwd_ports_eth_addr[portid].addr_bytes[1], 1312 l2fwd_ports_eth_addr[portid].addr_bytes[2], 1313 l2fwd_ports_eth_addr[portid].addr_bytes[3], 1314 l2fwd_ports_eth_addr[portid].addr_bytes[4], 1315 l2fwd_ports_eth_addr[portid].addr_bytes[5]); 1316 1317 /* initialize port stats */ 1318 memset(&port_statistics, 0, sizeof(port_statistics)); 1319 1320 /* Setup port forwarding table */ 1321 if (enabled_portcount % 2) { 1322 l2fwd_dst_ports[portid] = last_portid; 1323 l2fwd_dst_ports[last_portid] = portid; 1324 } else { 1325 last_portid = portid; 1326 } 1327 1328 l2fwd_enabled_port_mask |= (1 << portid); 1329 enabled_portcount++; 1330 } 1331 1332 if (enabled_portcount == 1) { 1333 l2fwd_dst_ports[last_portid] = last_portid; 1334 } else if (enabled_portcount % 2) { 1335 printf("odd number of ports in portmask- bye\n"); 1336 return -1; 1337 } 1338 1339 check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); 1340 1341 return enabled_portcount; 1342 } 1343 1344 int 1345 main(int argc, char **argv) 1346 { 1347 struct lcore_queue_conf *qconf; 1348 struct l2fwd_crypto_options options; 1349 1350 uint8_t nb_ports, nb_cryptodevs, portid, cdev_id; 1351 unsigned lcore_id, rx_lcore_id; 1352 int ret, enabled_cdevcount, enabled_portcount; 1353 1354 /* init EAL */ 1355 ret = rte_eal_init(argc, argv); 1356 if (ret < 0) 1357 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); 1358 argc -= ret; 1359 argv += ret; 1360 1361 /* parse application arguments (after the EAL ones) */ 1362 ret = l2fwd_crypto_parse_args(&options, argc, argv); 1363 if (ret < 0) 1364 rte_exit(EXIT_FAILURE, "Invalid L2FWD-CRYPTO arguments\n"); 1365 1366 /* create the mbuf pool */ 1367 l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 128, 1368 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 1369 if (l2fwd_pktmbuf_pool == NULL) 1370 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 1371 1372 /* create crypto op pool */ 1373 l2fwd_mbuf_ol_pool = rte_pktmbuf_offload_pool_create( 1374 "mbuf_offload_pool", NB_MBUF, 128, 0, rte_socket_id()); 1375 if (l2fwd_mbuf_ol_pool == NULL) 1376 rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n"); 1377 1378 /* Enable Ethernet ports */ 1379 enabled_portcount = initialize_ports(&options); 1380 if (enabled_portcount < 1) 1381 rte_exit(EXIT_FAILURE, "Failed to initial Ethernet ports\n"); 1382 1383 nb_ports = rte_eth_dev_count(); 1384 /* Initialize the port/queue configuration of each logical core */ 1385 for (rx_lcore_id = 0, qconf = NULL, portid = 0; 1386 portid < nb_ports; portid++) { 1387 1388 /* skip ports that are not enabled */ 1389 if ((options.portmask & (1 << portid)) == 0) 1390 continue; 1391 1392 if (options.single_lcore && qconf == NULL) { 1393 while (rte_lcore_is_enabled(rx_lcore_id) == 0) { 1394 rx_lcore_id++; 1395 if (rx_lcore_id >= RTE_MAX_LCORE) 1396 rte_exit(EXIT_FAILURE, 1397 "Not enough cores\n"); 1398 } 1399 } else if (!options.single_lcore) { 1400 /* get the lcore_id for this port */ 1401 while (rte_lcore_is_enabled(rx_lcore_id) == 0 || 1402 lcore_queue_conf[rx_lcore_id].nb_rx_ports == 1403 options.nb_ports_per_lcore) { 1404 rx_lcore_id++; 1405 if (rx_lcore_id >= RTE_MAX_LCORE) 1406 rte_exit(EXIT_FAILURE, 1407 "Not enough cores\n"); 1408 } 1409 } 1410 1411 /* Assigned a new logical core in the loop above. */ 1412 if (qconf != &lcore_queue_conf[rx_lcore_id]) 1413 qconf = &lcore_queue_conf[rx_lcore_id]; 1414 1415 qconf->rx_port_list[qconf->nb_rx_ports] = portid; 1416 qconf->nb_rx_ports++; 1417 1418 printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned)portid); 1419 } 1420 1421 1422 /* Enable Crypto devices */ 1423 enabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount); 1424 if (enabled_cdevcount < 1) 1425 rte_exit(EXIT_FAILURE, "Failed to initial crypto devices\n"); 1426 1427 nb_cryptodevs = rte_cryptodev_count(); 1428 /* Initialize the port/queue configuration of each logical core */ 1429 for (rx_lcore_id = 0, qconf = NULL, cdev_id = 0; 1430 cdev_id < nb_cryptodevs && enabled_cdevcount; 1431 cdev_id++) { 1432 struct rte_cryptodev_info info; 1433 1434 rte_cryptodev_info_get(cdev_id, &info); 1435 1436 /* skip devices of the wrong type */ 1437 if (options.cdev_type != info.dev_type) 1438 continue; 1439 1440 if (options.single_lcore && qconf == NULL) { 1441 while (rte_lcore_is_enabled(rx_lcore_id) == 0) { 1442 rx_lcore_id++; 1443 if (rx_lcore_id >= RTE_MAX_LCORE) 1444 rte_exit(EXIT_FAILURE, 1445 "Not enough cores\n"); 1446 } 1447 } else if (!options.single_lcore) { 1448 /* get the lcore_id for this port */ 1449 while (rte_lcore_is_enabled(rx_lcore_id) == 0 || 1450 lcore_queue_conf[rx_lcore_id].nb_crypto_devs == 1451 options.nb_ports_per_lcore) { 1452 rx_lcore_id++; 1453 if (rx_lcore_id >= RTE_MAX_LCORE) 1454 rte_exit(EXIT_FAILURE, 1455 "Not enough cores\n"); 1456 } 1457 } 1458 1459 /* Assigned a new logical core in the loop above. */ 1460 if (qconf != &lcore_queue_conf[rx_lcore_id]) 1461 qconf = &lcore_queue_conf[rx_lcore_id]; 1462 1463 qconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id; 1464 qconf->nb_crypto_devs++; 1465 1466 enabled_cdevcount--; 1467 1468 printf("Lcore %u: cryptodev %u\n", rx_lcore_id, 1469 (unsigned)cdev_id); 1470 } 1471 1472 1473 1474 /* launch per-lcore init on every lcore */ 1475 rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options, 1476 CALL_MASTER); 1477 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 1478 if (rte_eal_wait_lcore(lcore_id) < 0) 1479 return -1; 1480 } 1481 1482 return 0; 1483 } 1484