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