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