1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Intel Corporation 3 */ 4 5 #include <stdbool.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdint.h> 9 #include <inttypes.h> 10 #include <sys/types.h> 11 #include <netinet/in.h> 12 #include <netinet/ip.h> 13 #include <netinet/ip6.h> 14 #include <string.h> 15 #include <sys/queue.h> 16 #include <stdarg.h> 17 #include <errno.h> 18 #include <signal.h> 19 #include <getopt.h> 20 21 #include <rte_common.h> 22 #include <rte_bitmap.h> 23 #include <rte_byteorder.h> 24 #include <rte_log.h> 25 #include <rte_eal.h> 26 #include <rte_launch.h> 27 #include <rte_cycles.h> 28 #include <rte_prefetch.h> 29 #include <rte_lcore.h> 30 #include <rte_per_lcore.h> 31 #include <rte_branch_prediction.h> 32 #include <rte_interrupts.h> 33 #include <rte_random.h> 34 #include <rte_debug.h> 35 #include <rte_ether.h> 36 #include <rte_ethdev.h> 37 #include <rte_mempool.h> 38 #include <rte_mbuf.h> 39 #include <rte_acl.h> 40 #include <rte_lpm.h> 41 #include <rte_lpm6.h> 42 #include <rte_hash.h> 43 #include <rte_jhash.h> 44 #include <rte_cryptodev.h> 45 #include <rte_security.h> 46 #include <rte_eventdev.h> 47 #include <rte_ip.h> 48 #include <rte_ip_frag.h> 49 #include <rte_alarm.h> 50 51 #include "event_helper.h" 52 #include "flow.h" 53 #include "ipsec.h" 54 #include "ipsec_worker.h" 55 #include "parser.h" 56 #include "sad.h" 57 58 volatile bool force_quit; 59 60 #define MAX_JUMBO_PKT_LEN 9600 61 62 #define MEMPOOL_CACHE_SIZE 256 63 64 #define CDEV_QUEUE_DESC 2048 65 #define CDEV_MAP_ENTRIES 16384 66 #define CDEV_MP_CACHE_SZ 64 67 #define CDEV_MP_CACHE_MULTIPLIER 1.5 /* from rte_mempool.c */ 68 #define MAX_QUEUE_PAIRS 1 69 70 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 71 72 /* Configure how many packets ahead to prefetch, when reading packets */ 73 #define PREFETCH_OFFSET 3 74 75 #define MAX_RX_QUEUE_PER_LCORE 16 76 77 #define MAX_LCORE_PARAMS 1024 78 79 /* 80 * Configurable number of RX/TX ring descriptors 81 */ 82 #define IPSEC_SECGW_RX_DESC_DEFAULT 1024 83 #define IPSEC_SECGW_TX_DESC_DEFAULT 1024 84 static uint16_t nb_rxd = IPSEC_SECGW_RX_DESC_DEFAULT; 85 static uint16_t nb_txd = IPSEC_SECGW_TX_DESC_DEFAULT; 86 87 #define ETHADDR_TO_UINT64(addr) __BYTES_TO_UINT64( \ 88 (addr)->addr_bytes[0], (addr)->addr_bytes[1], \ 89 (addr)->addr_bytes[2], (addr)->addr_bytes[3], \ 90 (addr)->addr_bytes[4], (addr)->addr_bytes[5], \ 91 0, 0) 92 93 #define FRAG_TBL_BUCKET_ENTRIES 4 94 #define MAX_FRAG_TTL_NS (10LL * NS_PER_S) 95 96 #define MTU_TO_FRAMELEN(x) ((x) + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN) 97 98 struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS] = { 99 { 0, ETHADDR(0x00, 0x16, 0x3e, 0x7e, 0x94, 0x9a) }, 100 { 0, ETHADDR(0x00, 0x16, 0x3e, 0x22, 0xa1, 0xd9) }, 101 { 0, ETHADDR(0x00, 0x16, 0x3e, 0x08, 0x69, 0x26) }, 102 { 0, ETHADDR(0x00, 0x16, 0x3e, 0x49, 0x9e, 0xdd) } 103 }; 104 105 struct flow_info flow_info_tbl[RTE_MAX_ETHPORTS]; 106 107 #define CMD_LINE_OPT_CONFIG "config" 108 #define CMD_LINE_OPT_SINGLE_SA "single-sa" 109 #define CMD_LINE_OPT_CRYPTODEV_MASK "cryptodev_mask" 110 #define CMD_LINE_OPT_TRANSFER_MODE "transfer-mode" 111 #define CMD_LINE_OPT_SCHEDULE_TYPE "event-schedule-type" 112 #define CMD_LINE_OPT_RX_OFFLOAD "rxoffload" 113 #define CMD_LINE_OPT_TX_OFFLOAD "txoffload" 114 #define CMD_LINE_OPT_REASSEMBLE "reassemble" 115 #define CMD_LINE_OPT_MTU "mtu" 116 #define CMD_LINE_OPT_FRAG_TTL "frag-ttl" 117 118 #define CMD_LINE_ARG_EVENT "event" 119 #define CMD_LINE_ARG_POLL "poll" 120 #define CMD_LINE_ARG_ORDERED "ordered" 121 #define CMD_LINE_ARG_ATOMIC "atomic" 122 #define CMD_LINE_ARG_PARALLEL "parallel" 123 124 enum { 125 /* long options mapped to a short option */ 126 127 /* first long only option value must be >= 256, so that we won't 128 * conflict with short options 129 */ 130 CMD_LINE_OPT_MIN_NUM = 256, 131 CMD_LINE_OPT_CONFIG_NUM, 132 CMD_LINE_OPT_SINGLE_SA_NUM, 133 CMD_LINE_OPT_CRYPTODEV_MASK_NUM, 134 CMD_LINE_OPT_TRANSFER_MODE_NUM, 135 CMD_LINE_OPT_SCHEDULE_TYPE_NUM, 136 CMD_LINE_OPT_RX_OFFLOAD_NUM, 137 CMD_LINE_OPT_TX_OFFLOAD_NUM, 138 CMD_LINE_OPT_REASSEMBLE_NUM, 139 CMD_LINE_OPT_MTU_NUM, 140 CMD_LINE_OPT_FRAG_TTL_NUM, 141 }; 142 143 static const struct option lgopts[] = { 144 {CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM}, 145 {CMD_LINE_OPT_SINGLE_SA, 1, 0, CMD_LINE_OPT_SINGLE_SA_NUM}, 146 {CMD_LINE_OPT_CRYPTODEV_MASK, 1, 0, CMD_LINE_OPT_CRYPTODEV_MASK_NUM}, 147 {CMD_LINE_OPT_TRANSFER_MODE, 1, 0, CMD_LINE_OPT_TRANSFER_MODE_NUM}, 148 {CMD_LINE_OPT_SCHEDULE_TYPE, 1, 0, CMD_LINE_OPT_SCHEDULE_TYPE_NUM}, 149 {CMD_LINE_OPT_RX_OFFLOAD, 1, 0, CMD_LINE_OPT_RX_OFFLOAD_NUM}, 150 {CMD_LINE_OPT_TX_OFFLOAD, 1, 0, CMD_LINE_OPT_TX_OFFLOAD_NUM}, 151 {CMD_LINE_OPT_REASSEMBLE, 1, 0, CMD_LINE_OPT_REASSEMBLE_NUM}, 152 {CMD_LINE_OPT_MTU, 1, 0, CMD_LINE_OPT_MTU_NUM}, 153 {CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM}, 154 {NULL, 0, 0, 0} 155 }; 156 157 uint32_t unprotected_port_mask; 158 uint32_t single_sa_idx; 159 /* mask of enabled ports */ 160 static uint32_t enabled_port_mask; 161 static uint64_t enabled_cryptodev_mask = UINT64_MAX; 162 static int32_t promiscuous_on = 1; 163 static int32_t numa_on = 1; /**< NUMA is enabled by default. */ 164 static uint32_t nb_lcores; 165 static uint32_t single_sa; 166 static uint32_t nb_bufs_in_pool; 167 168 /* 169 * RX/TX HW offload capabilities to enable/use on ethernet ports. 170 * By default all capabilities are enabled. 171 */ 172 static uint64_t dev_rx_offload = UINT64_MAX; 173 static uint64_t dev_tx_offload = UINT64_MAX; 174 175 /* 176 * global values that determine multi-seg policy 177 */ 178 static uint32_t frag_tbl_sz; 179 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE; 180 static uint32_t mtu_size = RTE_ETHER_MTU; 181 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS; 182 183 /* application wide librte_ipsec/SA parameters */ 184 struct app_sa_prm app_sa_prm = { 185 .enable = 0, 186 .cache_sz = SA_CACHE_SZ, 187 .udp_encap = 0 188 }; 189 static const char *cfgfile; 190 191 struct lcore_rx_queue { 192 uint16_t port_id; 193 uint8_t queue_id; 194 } __rte_cache_aligned; 195 196 struct lcore_params { 197 uint16_t port_id; 198 uint8_t queue_id; 199 uint8_t lcore_id; 200 } __rte_cache_aligned; 201 202 static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 203 204 static struct lcore_params *lcore_params; 205 static uint16_t nb_lcore_params; 206 207 static struct rte_hash *cdev_map_in; 208 static struct rte_hash *cdev_map_out; 209 210 struct buffer { 211 uint16_t len; 212 struct rte_mbuf *m_table[MAX_PKT_BURST] __rte_aligned(sizeof(void *)); 213 }; 214 215 struct lcore_conf { 216 uint16_t nb_rx_queue; 217 struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 218 uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 219 struct buffer tx_mbufs[RTE_MAX_ETHPORTS]; 220 struct ipsec_ctx inbound; 221 struct ipsec_ctx outbound; 222 struct rt_ctx *rt4_ctx; 223 struct rt_ctx *rt6_ctx; 224 struct { 225 struct rte_ip_frag_tbl *tbl; 226 struct rte_mempool *pool_dir; 227 struct rte_mempool *pool_indir; 228 struct rte_ip_frag_death_row dr; 229 } frag; 230 } __rte_cache_aligned; 231 232 static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 233 234 static struct rte_eth_conf port_conf = { 235 .rxmode = { 236 .mq_mode = ETH_MQ_RX_RSS, 237 .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 238 .split_hdr_size = 0, 239 .offloads = DEV_RX_OFFLOAD_CHECKSUM, 240 }, 241 .rx_adv_conf = { 242 .rss_conf = { 243 .rss_key = NULL, 244 .rss_hf = ETH_RSS_IP | ETH_RSS_UDP | 245 ETH_RSS_TCP | ETH_RSS_SCTP, 246 }, 247 }, 248 .txmode = { 249 .mq_mode = ETH_MQ_TX_NONE, 250 }, 251 }; 252 253 struct socket_ctx socket_ctx[NB_SOCKETS]; 254 255 /* 256 * Determine is multi-segment support required: 257 * - either frame buffer size is smaller then mtu 258 * - or reassmeble support is requested 259 */ 260 static int 261 multi_seg_required(void) 262 { 263 return (MTU_TO_FRAMELEN(mtu_size) + RTE_PKTMBUF_HEADROOM > 264 frame_buf_size || frag_tbl_sz != 0); 265 } 266 267 static inline void 268 adjust_ipv4_pktlen(struct rte_mbuf *m, const struct rte_ipv4_hdr *iph, 269 uint32_t l2_len) 270 { 271 uint32_t plen, trim; 272 273 plen = rte_be_to_cpu_16(iph->total_length) + l2_len; 274 if (plen < m->pkt_len) { 275 trim = m->pkt_len - plen; 276 rte_pktmbuf_trim(m, trim); 277 } 278 } 279 280 static inline void 281 adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph, 282 uint32_t l2_len) 283 { 284 uint32_t plen, trim; 285 286 plen = rte_be_to_cpu_16(iph->payload_len) + sizeof(*iph) + l2_len; 287 if (plen < m->pkt_len) { 288 trim = m->pkt_len - plen; 289 rte_pktmbuf_trim(m, trim); 290 } 291 } 292 293 #if (STATS_INTERVAL > 0) 294 295 /* Print out statistics on packet distribution */ 296 static void 297 print_stats_cb(__rte_unused void *param) 298 { 299 uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; 300 float burst_percent, rx_per_call, tx_per_call; 301 unsigned int coreid; 302 303 total_packets_dropped = 0; 304 total_packets_tx = 0; 305 total_packets_rx = 0; 306 307 const char clr[] = { 27, '[', '2', 'J', '\0' }; 308 const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 309 310 /* Clear screen and move to top left */ 311 printf("%s%s", clr, topLeft); 312 313 printf("\nCore statistics ===================================="); 314 315 for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) { 316 /* skip disabled cores */ 317 if (rte_lcore_is_enabled(coreid) == 0) 318 continue; 319 burst_percent = (float)(core_statistics[coreid].burst_rx * 100)/ 320 core_statistics[coreid].rx; 321 rx_per_call = (float)(core_statistics[coreid].rx)/ 322 core_statistics[coreid].rx_call; 323 tx_per_call = (float)(core_statistics[coreid].tx)/ 324 core_statistics[coreid].tx_call; 325 printf("\nStatistics for core %u ------------------------------" 326 "\nPackets received: %20"PRIu64 327 "\nPackets sent: %24"PRIu64 328 "\nPackets dropped: %21"PRIu64 329 "\nBurst percent: %23.2f" 330 "\nPackets per Rx call: %17.2f" 331 "\nPackets per Tx call: %17.2f", 332 coreid, 333 core_statistics[coreid].rx, 334 core_statistics[coreid].tx, 335 core_statistics[coreid].dropped, 336 burst_percent, 337 rx_per_call, 338 tx_per_call); 339 340 total_packets_dropped += core_statistics[coreid].dropped; 341 total_packets_tx += core_statistics[coreid].tx; 342 total_packets_rx += core_statistics[coreid].rx; 343 } 344 printf("\nAggregate statistics ===============================" 345 "\nTotal packets received: %14"PRIu64 346 "\nTotal packets sent: %18"PRIu64 347 "\nTotal packets dropped: %15"PRIu64, 348 total_packets_rx, 349 total_packets_tx, 350 total_packets_dropped); 351 printf("\n====================================================\n"); 352 353 rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL); 354 } 355 #endif /* STATS_INTERVAL */ 356 357 static inline void 358 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t) 359 { 360 const struct rte_ether_hdr *eth; 361 const struct rte_ipv4_hdr *iph4; 362 const struct rte_ipv6_hdr *iph6; 363 const struct rte_udp_hdr *udp; 364 uint16_t ip4_hdr_len; 365 uint16_t nat_port; 366 367 eth = rte_pktmbuf_mtod(pkt, const struct rte_ether_hdr *); 368 if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { 369 370 iph4 = (const struct rte_ipv4_hdr *)rte_pktmbuf_adj(pkt, 371 RTE_ETHER_HDR_LEN); 372 adjust_ipv4_pktlen(pkt, iph4, 0); 373 374 switch (iph4->next_proto_id) { 375 case IPPROTO_ESP: 376 t->ipsec.pkts[(t->ipsec.num)++] = pkt; 377 break; 378 case IPPROTO_UDP: 379 if (app_sa_prm.udp_encap == 1) { 380 ip4_hdr_len = ((iph4->version_ihl & 381 RTE_IPV4_HDR_IHL_MASK) * 382 RTE_IPV4_IHL_MULTIPLIER); 383 udp = rte_pktmbuf_mtod_offset(pkt, 384 struct rte_udp_hdr *, ip4_hdr_len); 385 nat_port = rte_cpu_to_be_16(IPSEC_NAT_T_PORT); 386 if (udp->src_port == nat_port || 387 udp->dst_port == nat_port){ 388 t->ipsec.pkts[(t->ipsec.num)++] = pkt; 389 pkt->packet_type |= 390 MBUF_PTYPE_TUNNEL_ESP_IN_UDP; 391 break; 392 } 393 } 394 /* Fall through */ 395 default: 396 t->ip4.data[t->ip4.num] = &iph4->next_proto_id; 397 t->ip4.pkts[(t->ip4.num)++] = pkt; 398 } 399 pkt->l2_len = 0; 400 pkt->l3_len = sizeof(*iph4); 401 pkt->packet_type |= RTE_PTYPE_L3_IPV4; 402 } else if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { 403 int next_proto; 404 size_t l3len, ext_len; 405 uint8_t *p; 406 407 /* get protocol type */ 408 iph6 = (const struct rte_ipv6_hdr *)rte_pktmbuf_adj(pkt, 409 RTE_ETHER_HDR_LEN); 410 adjust_ipv6_pktlen(pkt, iph6, 0); 411 412 next_proto = iph6->proto; 413 414 /* determine l3 header size up to ESP extension */ 415 l3len = sizeof(struct ip6_hdr); 416 p = rte_pktmbuf_mtod(pkt, uint8_t *); 417 while (next_proto != IPPROTO_ESP && l3len < pkt->data_len && 418 (next_proto = rte_ipv6_get_next_ext(p + l3len, 419 next_proto, &ext_len)) >= 0) 420 l3len += ext_len; 421 422 /* drop packet when IPv6 header exceeds first segment length */ 423 if (unlikely(l3len > pkt->data_len)) { 424 free_pkts(&pkt, 1); 425 return; 426 } 427 428 switch (next_proto) { 429 case IPPROTO_ESP: 430 t->ipsec.pkts[(t->ipsec.num)++] = pkt; 431 break; 432 case IPPROTO_UDP: 433 if (app_sa_prm.udp_encap == 1) { 434 udp = rte_pktmbuf_mtod_offset(pkt, 435 struct rte_udp_hdr *, l3len); 436 nat_port = rte_cpu_to_be_16(IPSEC_NAT_T_PORT); 437 if (udp->src_port == nat_port || 438 udp->dst_port == nat_port){ 439 t->ipsec.pkts[(t->ipsec.num)++] = pkt; 440 pkt->packet_type |= 441 MBUF_PTYPE_TUNNEL_ESP_IN_UDP; 442 break; 443 } 444 } 445 /* Fall through */ 446 default: 447 t->ip6.data[t->ip6.num] = &iph6->proto; 448 t->ip6.pkts[(t->ip6.num)++] = pkt; 449 } 450 pkt->l2_len = 0; 451 pkt->l3_len = l3len; 452 pkt->packet_type |= RTE_PTYPE_L3_IPV6; 453 } else { 454 /* Unknown/Unsupported type, drop the packet */ 455 RTE_LOG(ERR, IPSEC, "Unsupported packet type 0x%x\n", 456 rte_be_to_cpu_16(eth->ether_type)); 457 free_pkts(&pkt, 1); 458 return; 459 } 460 461 /* Check if the packet has been processed inline. For inline protocol 462 * processed packets, the metadata in the mbuf can be used to identify 463 * the security processing done on the packet. The metadata will be 464 * used to retrieve the application registered userdata associated 465 * with the security session. 466 */ 467 468 if (pkt->ol_flags & PKT_RX_SEC_OFFLOAD && 469 rte_security_dynfield_is_registered()) { 470 struct ipsec_sa *sa; 471 struct ipsec_mbuf_metadata *priv; 472 struct rte_security_ctx *ctx = (struct rte_security_ctx *) 473 rte_eth_dev_get_sec_ctx( 474 pkt->port); 475 476 /* Retrieve the userdata registered. Here, the userdata 477 * registered is the SA pointer. 478 */ 479 sa = (struct ipsec_sa *)rte_security_get_userdata(ctx, 480 *rte_security_dynfield(pkt)); 481 if (sa == NULL) { 482 /* userdata could not be retrieved */ 483 return; 484 } 485 486 /* Save SA as priv member in mbuf. This will be used in the 487 * IPsec selector(SP-SA) check. 488 */ 489 490 priv = get_priv(pkt); 491 priv->sa = sa; 492 } 493 } 494 495 static inline void 496 prepare_traffic(struct rte_mbuf **pkts, struct ipsec_traffic *t, 497 uint16_t nb_pkts) 498 { 499 int32_t i; 500 501 t->ipsec.num = 0; 502 t->ip4.num = 0; 503 t->ip6.num = 0; 504 505 for (i = 0; i < (nb_pkts - PREFETCH_OFFSET); i++) { 506 rte_prefetch0(rte_pktmbuf_mtod(pkts[i + PREFETCH_OFFSET], 507 void *)); 508 prepare_one_packet(pkts[i], t); 509 } 510 /* Process left packets */ 511 for (; i < nb_pkts; i++) 512 prepare_one_packet(pkts[i], t); 513 } 514 515 static inline void 516 prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port, 517 const struct lcore_conf *qconf) 518 { 519 struct ip *ip; 520 struct rte_ether_hdr *ethhdr; 521 522 ip = rte_pktmbuf_mtod(pkt, struct ip *); 523 524 ethhdr = (struct rte_ether_hdr *) 525 rte_pktmbuf_prepend(pkt, RTE_ETHER_HDR_LEN); 526 527 if (ip->ip_v == IPVERSION) { 528 pkt->ol_flags |= qconf->outbound.ipv4_offloads; 529 pkt->l3_len = sizeof(struct ip); 530 pkt->l2_len = RTE_ETHER_HDR_LEN; 531 532 ip->ip_sum = 0; 533 534 /* calculate IPv4 cksum in SW */ 535 if ((pkt->ol_flags & PKT_TX_IP_CKSUM) == 0) 536 ip->ip_sum = rte_ipv4_cksum((struct rte_ipv4_hdr *)ip); 537 538 ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 539 } else { 540 pkt->ol_flags |= qconf->outbound.ipv6_offloads; 541 pkt->l3_len = sizeof(struct ip6_hdr); 542 pkt->l2_len = RTE_ETHER_HDR_LEN; 543 544 ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 545 } 546 547 memcpy(ðhdr->src_addr, ðaddr_tbl[port].src, 548 sizeof(struct rte_ether_addr)); 549 memcpy(ðhdr->dst_addr, ðaddr_tbl[port].dst, 550 sizeof(struct rte_ether_addr)); 551 } 552 553 static inline void 554 prepare_tx_burst(struct rte_mbuf *pkts[], uint16_t nb_pkts, uint16_t port, 555 const struct lcore_conf *qconf) 556 { 557 int32_t i; 558 const int32_t prefetch_offset = 2; 559 560 for (i = 0; i < (nb_pkts - prefetch_offset); i++) { 561 rte_mbuf_prefetch_part2(pkts[i + prefetch_offset]); 562 prepare_tx_pkt(pkts[i], port, qconf); 563 } 564 /* Process left packets */ 565 for (; i < nb_pkts; i++) 566 prepare_tx_pkt(pkts[i], port, qconf); 567 } 568 569 /* Send burst of packets on an output interface */ 570 static inline int32_t 571 send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port) 572 { 573 struct rte_mbuf **m_table; 574 int32_t ret; 575 uint16_t queueid; 576 577 queueid = qconf->tx_queue_id[port]; 578 m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; 579 580 prepare_tx_burst(m_table, n, port, qconf); 581 582 ret = rte_eth_tx_burst(port, queueid, m_table, n); 583 584 core_stats_update_tx(ret); 585 586 if (unlikely(ret < n)) { 587 do { 588 free_pkts(&m_table[ret], 1); 589 } while (++ret < n); 590 } 591 592 return 0; 593 } 594 595 /* 596 * Helper function to fragment and queue for TX one packet. 597 */ 598 static inline uint32_t 599 send_fragment_packet(struct lcore_conf *qconf, struct rte_mbuf *m, 600 uint16_t port, uint8_t proto) 601 { 602 struct buffer *tbl; 603 uint32_t len, n; 604 int32_t rc; 605 606 tbl = qconf->tx_mbufs + port; 607 len = tbl->len; 608 609 /* free space for new fragments */ 610 if (len + RTE_LIBRTE_IP_FRAG_MAX_FRAG >= RTE_DIM(tbl->m_table)) { 611 send_burst(qconf, len, port); 612 len = 0; 613 } 614 615 n = RTE_DIM(tbl->m_table) - len; 616 617 if (proto == IPPROTO_IP) 618 rc = rte_ipv4_fragment_packet(m, tbl->m_table + len, 619 n, mtu_size, qconf->frag.pool_dir, 620 qconf->frag.pool_indir); 621 else 622 rc = rte_ipv6_fragment_packet(m, tbl->m_table + len, 623 n, mtu_size, qconf->frag.pool_dir, 624 qconf->frag.pool_indir); 625 626 if (rc >= 0) 627 len += rc; 628 else 629 RTE_LOG(ERR, IPSEC, 630 "%s: failed to fragment packet with size %u, " 631 "error code: %d\n", 632 __func__, m->pkt_len, rte_errno); 633 634 free_pkts(&m, 1); 635 return len; 636 } 637 638 /* Enqueue a single packet, and send burst if queue is filled */ 639 static inline int32_t 640 send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto) 641 { 642 uint32_t lcore_id; 643 uint16_t len; 644 struct lcore_conf *qconf; 645 646 lcore_id = rte_lcore_id(); 647 648 qconf = &lcore_conf[lcore_id]; 649 len = qconf->tx_mbufs[port].len; 650 651 if (m->pkt_len <= mtu_size) { 652 qconf->tx_mbufs[port].m_table[len] = m; 653 len++; 654 655 /* need to fragment the packet */ 656 } else if (frag_tbl_sz > 0) 657 len = send_fragment_packet(qconf, m, port, proto); 658 else 659 free_pkts(&m, 1); 660 661 /* enough pkts to be sent */ 662 if (unlikely(len == MAX_PKT_BURST)) { 663 send_burst(qconf, MAX_PKT_BURST, port); 664 len = 0; 665 } 666 667 qconf->tx_mbufs[port].len = len; 668 return 0; 669 } 670 671 static inline void 672 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip, 673 uint16_t lim) 674 { 675 struct rte_mbuf *m; 676 uint32_t i, j, res, sa_idx; 677 678 if (ip->num == 0 || sp == NULL) 679 return; 680 681 rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, 682 ip->num, DEFAULT_MAX_CATEGORIES); 683 684 j = 0; 685 for (i = 0; i < ip->num; i++) { 686 m = ip->pkts[i]; 687 res = ip->res[i]; 688 if (res == BYPASS) { 689 ip->pkts[j++] = m; 690 continue; 691 } 692 if (res == DISCARD) { 693 free_pkts(&m, 1); 694 continue; 695 } 696 697 /* Only check SPI match for processed IPSec packets */ 698 if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) { 699 free_pkts(&m, 1); 700 continue; 701 } 702 703 sa_idx = res - 1; 704 if (!inbound_sa_check(sa, m, sa_idx)) { 705 free_pkts(&m, 1); 706 continue; 707 } 708 ip->pkts[j++] = m; 709 } 710 ip->num = j; 711 } 712 713 static void 714 split46_traffic(struct ipsec_traffic *trf, struct rte_mbuf *mb[], uint32_t num) 715 { 716 uint32_t i, n4, n6; 717 struct ip *ip; 718 struct rte_mbuf *m; 719 720 n4 = trf->ip4.num; 721 n6 = trf->ip6.num; 722 723 for (i = 0; i < num; i++) { 724 725 m = mb[i]; 726 ip = rte_pktmbuf_mtod(m, struct ip *); 727 728 if (ip->ip_v == IPVERSION) { 729 trf->ip4.pkts[n4] = m; 730 trf->ip4.data[n4] = rte_pktmbuf_mtod_offset(m, 731 uint8_t *, offsetof(struct ip, ip_p)); 732 n4++; 733 } else if (ip->ip_v == IP6_VERSION) { 734 trf->ip6.pkts[n6] = m; 735 trf->ip6.data[n6] = rte_pktmbuf_mtod_offset(m, 736 uint8_t *, 737 offsetof(struct ip6_hdr, ip6_nxt)); 738 n6++; 739 } else 740 free_pkts(&m, 1); 741 } 742 743 trf->ip4.num = n4; 744 trf->ip6.num = n6; 745 } 746 747 748 static inline void 749 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx, 750 struct ipsec_traffic *traffic) 751 { 752 uint16_t nb_pkts_in, n_ip4, n_ip6; 753 754 n_ip4 = traffic->ip4.num; 755 n_ip6 = traffic->ip6.num; 756 757 if (app_sa_prm.enable == 0) { 758 nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec.pkts, 759 traffic->ipsec.num, MAX_PKT_BURST); 760 split46_traffic(traffic, traffic->ipsec.pkts, nb_pkts_in); 761 } else { 762 inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts, 763 traffic->ipsec.saptr, traffic->ipsec.num); 764 ipsec_process(ipsec_ctx, traffic); 765 } 766 767 inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4, 768 n_ip4); 769 770 inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6, 771 n_ip6); 772 } 773 774 static inline void 775 outbound_sp(struct sp_ctx *sp, struct traffic_type *ip, 776 struct traffic_type *ipsec) 777 { 778 struct rte_mbuf *m; 779 uint32_t i, j, sa_idx; 780 781 if (ip->num == 0 || sp == NULL) 782 return; 783 784 rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, 785 ip->num, DEFAULT_MAX_CATEGORIES); 786 787 j = 0; 788 for (i = 0; i < ip->num; i++) { 789 m = ip->pkts[i]; 790 sa_idx = ip->res[i] - 1; 791 if (ip->res[i] == DISCARD) 792 free_pkts(&m, 1); 793 else if (ip->res[i] == BYPASS) 794 ip->pkts[j++] = m; 795 else { 796 ipsec->res[ipsec->num] = sa_idx; 797 ipsec->pkts[ipsec->num++] = m; 798 } 799 } 800 ip->num = j; 801 } 802 803 static inline void 804 process_pkts_outbound(struct ipsec_ctx *ipsec_ctx, 805 struct ipsec_traffic *traffic) 806 { 807 struct rte_mbuf *m; 808 uint16_t idx, nb_pkts_out, i; 809 810 /* Drop any IPsec traffic from protected ports */ 811 free_pkts(traffic->ipsec.pkts, traffic->ipsec.num); 812 813 traffic->ipsec.num = 0; 814 815 outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec); 816 817 outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec); 818 819 if (app_sa_prm.enable == 0) { 820 821 nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ipsec.pkts, 822 traffic->ipsec.res, traffic->ipsec.num, 823 MAX_PKT_BURST); 824 825 for (i = 0; i < nb_pkts_out; i++) { 826 m = traffic->ipsec.pkts[i]; 827 struct ip *ip = rte_pktmbuf_mtod(m, struct ip *); 828 if (ip->ip_v == IPVERSION) { 829 idx = traffic->ip4.num++; 830 traffic->ip4.pkts[idx] = m; 831 } else { 832 idx = traffic->ip6.num++; 833 traffic->ip6.pkts[idx] = m; 834 } 835 } 836 } else { 837 outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res, 838 traffic->ipsec.saptr, traffic->ipsec.num); 839 ipsec_process(ipsec_ctx, traffic); 840 } 841 } 842 843 static inline void 844 process_pkts_inbound_nosp(struct ipsec_ctx *ipsec_ctx, 845 struct ipsec_traffic *traffic) 846 { 847 struct rte_mbuf *m; 848 uint32_t nb_pkts_in, i, idx; 849 850 if (app_sa_prm.enable == 0) { 851 852 nb_pkts_in = ipsec_inbound(ipsec_ctx, traffic->ipsec.pkts, 853 traffic->ipsec.num, MAX_PKT_BURST); 854 855 for (i = 0; i < nb_pkts_in; i++) { 856 m = traffic->ipsec.pkts[i]; 857 struct ip *ip = rte_pktmbuf_mtod(m, struct ip *); 858 if (ip->ip_v == IPVERSION) { 859 idx = traffic->ip4.num++; 860 traffic->ip4.pkts[idx] = m; 861 } else { 862 idx = traffic->ip6.num++; 863 traffic->ip6.pkts[idx] = m; 864 } 865 } 866 } else { 867 inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts, 868 traffic->ipsec.saptr, traffic->ipsec.num); 869 ipsec_process(ipsec_ctx, traffic); 870 } 871 } 872 873 static inline void 874 process_pkts_outbound_nosp(struct ipsec_ctx *ipsec_ctx, 875 struct ipsec_traffic *traffic) 876 { 877 struct rte_mbuf *m; 878 uint32_t nb_pkts_out, i, n; 879 struct ip *ip; 880 881 /* Drop any IPsec traffic from protected ports */ 882 free_pkts(traffic->ipsec.pkts, traffic->ipsec.num); 883 884 n = 0; 885 886 for (i = 0; i < traffic->ip4.num; i++) { 887 traffic->ipsec.pkts[n] = traffic->ip4.pkts[i]; 888 traffic->ipsec.res[n++] = single_sa_idx; 889 } 890 891 for (i = 0; i < traffic->ip6.num; i++) { 892 traffic->ipsec.pkts[n] = traffic->ip6.pkts[i]; 893 traffic->ipsec.res[n++] = single_sa_idx; 894 } 895 896 traffic->ip4.num = 0; 897 traffic->ip6.num = 0; 898 traffic->ipsec.num = n; 899 900 if (app_sa_prm.enable == 0) { 901 902 nb_pkts_out = ipsec_outbound(ipsec_ctx, traffic->ipsec.pkts, 903 traffic->ipsec.res, traffic->ipsec.num, 904 MAX_PKT_BURST); 905 906 /* They all sue the same SA (ip4 or ip6 tunnel) */ 907 m = traffic->ipsec.pkts[0]; 908 ip = rte_pktmbuf_mtod(m, struct ip *); 909 if (ip->ip_v == IPVERSION) { 910 traffic->ip4.num = nb_pkts_out; 911 for (i = 0; i < nb_pkts_out; i++) 912 traffic->ip4.pkts[i] = traffic->ipsec.pkts[i]; 913 } else { 914 traffic->ip6.num = nb_pkts_out; 915 for (i = 0; i < nb_pkts_out; i++) 916 traffic->ip6.pkts[i] = traffic->ipsec.pkts[i]; 917 } 918 } else { 919 outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res, 920 traffic->ipsec.saptr, traffic->ipsec.num); 921 ipsec_process(ipsec_ctx, traffic); 922 } 923 } 924 925 static inline int32_t 926 get_hop_for_offload_pkt(struct rte_mbuf *pkt, int is_ipv6) 927 { 928 struct ipsec_mbuf_metadata *priv; 929 struct ipsec_sa *sa; 930 931 priv = get_priv(pkt); 932 933 sa = priv->sa; 934 if (unlikely(sa == NULL)) { 935 RTE_LOG(ERR, IPSEC, "SA not saved in private data\n"); 936 goto fail; 937 } 938 939 if (is_ipv6) 940 return sa->portid; 941 942 /* else */ 943 return (sa->portid | RTE_LPM_LOOKUP_SUCCESS); 944 945 fail: 946 if (is_ipv6) 947 return -1; 948 949 /* else */ 950 return 0; 951 } 952 953 static inline void 954 route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts) 955 { 956 uint32_t hop[MAX_PKT_BURST * 2]; 957 uint32_t dst_ip[MAX_PKT_BURST * 2]; 958 int32_t pkt_hop = 0; 959 uint16_t i, offset; 960 uint16_t lpm_pkts = 0; 961 962 if (nb_pkts == 0) 963 return; 964 965 /* Need to do an LPM lookup for non-inline packets. Inline packets will 966 * have port ID in the SA 967 */ 968 969 for (i = 0; i < nb_pkts; i++) { 970 if (!(pkts[i]->ol_flags & PKT_TX_SEC_OFFLOAD)) { 971 /* Security offload not enabled. So an LPM lookup is 972 * required to get the hop 973 */ 974 offset = offsetof(struct ip, ip_dst); 975 dst_ip[lpm_pkts] = *rte_pktmbuf_mtod_offset(pkts[i], 976 uint32_t *, offset); 977 dst_ip[lpm_pkts] = rte_be_to_cpu_32(dst_ip[lpm_pkts]); 978 lpm_pkts++; 979 } 980 } 981 982 rte_lpm_lookup_bulk((struct rte_lpm *)rt_ctx, dst_ip, hop, lpm_pkts); 983 984 lpm_pkts = 0; 985 986 for (i = 0; i < nb_pkts; i++) { 987 if (pkts[i]->ol_flags & PKT_TX_SEC_OFFLOAD) { 988 /* Read hop from the SA */ 989 pkt_hop = get_hop_for_offload_pkt(pkts[i], 0); 990 } else { 991 /* Need to use hop returned by lookup */ 992 pkt_hop = hop[lpm_pkts++]; 993 } 994 995 if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) { 996 free_pkts(&pkts[i], 1); 997 continue; 998 } 999 send_single_packet(pkts[i], pkt_hop & 0xff, IPPROTO_IP); 1000 } 1001 } 1002 1003 static inline void 1004 route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts) 1005 { 1006 int32_t hop[MAX_PKT_BURST * 2]; 1007 uint8_t dst_ip[MAX_PKT_BURST * 2][16]; 1008 uint8_t *ip6_dst; 1009 int32_t pkt_hop = 0; 1010 uint16_t i, offset; 1011 uint16_t lpm_pkts = 0; 1012 1013 if (nb_pkts == 0) 1014 return; 1015 1016 /* Need to do an LPM lookup for non-inline packets. Inline packets will 1017 * have port ID in the SA 1018 */ 1019 1020 for (i = 0; i < nb_pkts; i++) { 1021 if (!(pkts[i]->ol_flags & PKT_TX_SEC_OFFLOAD)) { 1022 /* Security offload not enabled. So an LPM lookup is 1023 * required to get the hop 1024 */ 1025 offset = offsetof(struct ip6_hdr, ip6_dst); 1026 ip6_dst = rte_pktmbuf_mtod_offset(pkts[i], uint8_t *, 1027 offset); 1028 memcpy(&dst_ip[lpm_pkts][0], ip6_dst, 16); 1029 lpm_pkts++; 1030 } 1031 } 1032 1033 rte_lpm6_lookup_bulk_func((struct rte_lpm6 *)rt_ctx, dst_ip, hop, 1034 lpm_pkts); 1035 1036 lpm_pkts = 0; 1037 1038 for (i = 0; i < nb_pkts; i++) { 1039 if (pkts[i]->ol_flags & PKT_TX_SEC_OFFLOAD) { 1040 /* Read hop from the SA */ 1041 pkt_hop = get_hop_for_offload_pkt(pkts[i], 1); 1042 } else { 1043 /* Need to use hop returned by lookup */ 1044 pkt_hop = hop[lpm_pkts++]; 1045 } 1046 1047 if (pkt_hop == -1) { 1048 free_pkts(&pkts[i], 1); 1049 continue; 1050 } 1051 send_single_packet(pkts[i], pkt_hop & 0xff, IPPROTO_IPV6); 1052 } 1053 } 1054 1055 static inline void 1056 process_pkts(struct lcore_conf *qconf, struct rte_mbuf **pkts, 1057 uint8_t nb_pkts, uint16_t portid) 1058 { 1059 struct ipsec_traffic traffic; 1060 1061 prepare_traffic(pkts, &traffic, nb_pkts); 1062 1063 if (unlikely(single_sa)) { 1064 if (is_unprotected_port(portid)) 1065 process_pkts_inbound_nosp(&qconf->inbound, &traffic); 1066 else 1067 process_pkts_outbound_nosp(&qconf->outbound, &traffic); 1068 } else { 1069 if (is_unprotected_port(portid)) 1070 process_pkts_inbound(&qconf->inbound, &traffic); 1071 else 1072 process_pkts_outbound(&qconf->outbound, &traffic); 1073 } 1074 1075 route4_pkts(qconf->rt4_ctx, traffic.ip4.pkts, traffic.ip4.num); 1076 route6_pkts(qconf->rt6_ctx, traffic.ip6.pkts, traffic.ip6.num); 1077 } 1078 1079 static inline void 1080 drain_tx_buffers(struct lcore_conf *qconf) 1081 { 1082 struct buffer *buf; 1083 uint32_t portid; 1084 1085 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 1086 buf = &qconf->tx_mbufs[portid]; 1087 if (buf->len == 0) 1088 continue; 1089 send_burst(qconf, buf->len, portid); 1090 buf->len = 0; 1091 } 1092 } 1093 1094 static inline void 1095 drain_crypto_buffers(struct lcore_conf *qconf) 1096 { 1097 uint32_t i; 1098 struct ipsec_ctx *ctx; 1099 1100 /* drain inbound buffers*/ 1101 ctx = &qconf->inbound; 1102 for (i = 0; i != ctx->nb_qps; i++) { 1103 if (ctx->tbl[i].len != 0) 1104 enqueue_cop_burst(ctx->tbl + i); 1105 } 1106 1107 /* drain outbound buffers*/ 1108 ctx = &qconf->outbound; 1109 for (i = 0; i != ctx->nb_qps; i++) { 1110 if (ctx->tbl[i].len != 0) 1111 enqueue_cop_burst(ctx->tbl + i); 1112 } 1113 } 1114 1115 static void 1116 drain_inbound_crypto_queues(const struct lcore_conf *qconf, 1117 struct ipsec_ctx *ctx) 1118 { 1119 uint32_t n; 1120 struct ipsec_traffic trf; 1121 1122 if (app_sa_prm.enable == 0) { 1123 1124 /* dequeue packets from crypto-queue */ 1125 n = ipsec_inbound_cqp_dequeue(ctx, trf.ipsec.pkts, 1126 RTE_DIM(trf.ipsec.pkts)); 1127 1128 trf.ip4.num = 0; 1129 trf.ip6.num = 0; 1130 1131 /* split traffic by ipv4-ipv6 */ 1132 split46_traffic(&trf, trf.ipsec.pkts, n); 1133 } else 1134 ipsec_cqp_process(ctx, &trf); 1135 1136 /* process ipv4 packets */ 1137 if (trf.ip4.num != 0) { 1138 inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0); 1139 route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num); 1140 } 1141 1142 /* process ipv6 packets */ 1143 if (trf.ip6.num != 0) { 1144 inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0); 1145 route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num); 1146 } 1147 } 1148 1149 static void 1150 drain_outbound_crypto_queues(const struct lcore_conf *qconf, 1151 struct ipsec_ctx *ctx) 1152 { 1153 uint32_t n; 1154 struct ipsec_traffic trf; 1155 1156 if (app_sa_prm.enable == 0) { 1157 1158 /* dequeue packets from crypto-queue */ 1159 n = ipsec_outbound_cqp_dequeue(ctx, trf.ipsec.pkts, 1160 RTE_DIM(trf.ipsec.pkts)); 1161 1162 trf.ip4.num = 0; 1163 trf.ip6.num = 0; 1164 1165 /* split traffic by ipv4-ipv6 */ 1166 split46_traffic(&trf, trf.ipsec.pkts, n); 1167 } else 1168 ipsec_cqp_process(ctx, &trf); 1169 1170 /* process ipv4 packets */ 1171 if (trf.ip4.num != 0) 1172 route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num); 1173 1174 /* process ipv6 packets */ 1175 if (trf.ip6.num != 0) 1176 route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num); 1177 } 1178 1179 /* main processing loop */ 1180 void 1181 ipsec_poll_mode_worker(void) 1182 { 1183 struct rte_mbuf *pkts[MAX_PKT_BURST]; 1184 uint32_t lcore_id; 1185 uint64_t prev_tsc, diff_tsc, cur_tsc; 1186 int32_t i, nb_rx; 1187 uint16_t portid; 1188 uint8_t queueid; 1189 struct lcore_conf *qconf; 1190 int32_t rc, socket_id; 1191 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) 1192 / US_PER_S * BURST_TX_DRAIN_US; 1193 struct lcore_rx_queue *rxql; 1194 1195 prev_tsc = 0; 1196 lcore_id = rte_lcore_id(); 1197 qconf = &lcore_conf[lcore_id]; 1198 rxql = qconf->rx_queue_list; 1199 socket_id = rte_lcore_to_socket_id(lcore_id); 1200 1201 qconf->rt4_ctx = socket_ctx[socket_id].rt_ip4; 1202 qconf->rt6_ctx = socket_ctx[socket_id].rt_ip6; 1203 qconf->inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in; 1204 qconf->inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in; 1205 qconf->inbound.sa_ctx = socket_ctx[socket_id].sa_in; 1206 qconf->inbound.cdev_map = cdev_map_in; 1207 qconf->inbound.session_pool = socket_ctx[socket_id].session_pool; 1208 qconf->inbound.session_priv_pool = 1209 socket_ctx[socket_id].session_priv_pool; 1210 qconf->outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out; 1211 qconf->outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out; 1212 qconf->outbound.sa_ctx = socket_ctx[socket_id].sa_out; 1213 qconf->outbound.cdev_map = cdev_map_out; 1214 qconf->outbound.session_pool = socket_ctx[socket_id].session_pool; 1215 qconf->outbound.session_priv_pool = 1216 socket_ctx[socket_id].session_priv_pool; 1217 qconf->frag.pool_dir = socket_ctx[socket_id].mbuf_pool; 1218 qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir; 1219 1220 rc = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz); 1221 if (rc != 0) { 1222 RTE_LOG(ERR, IPSEC, 1223 "SAD cache init on lcore %u, failed with code: %d\n", 1224 lcore_id, rc); 1225 return; 1226 } 1227 1228 if (qconf->nb_rx_queue == 0) { 1229 RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n", 1230 lcore_id); 1231 return; 1232 } 1233 1234 RTE_LOG(INFO, IPSEC, "entering main loop on lcore %u\n", lcore_id); 1235 1236 for (i = 0; i < qconf->nb_rx_queue; i++) { 1237 portid = rxql[i].port_id; 1238 queueid = rxql[i].queue_id; 1239 RTE_LOG(INFO, IPSEC, 1240 " -- lcoreid=%u portid=%u rxqueueid=%hhu\n", 1241 lcore_id, portid, queueid); 1242 } 1243 1244 while (!force_quit) { 1245 cur_tsc = rte_rdtsc(); 1246 1247 /* TX queue buffer drain */ 1248 diff_tsc = cur_tsc - prev_tsc; 1249 1250 if (unlikely(diff_tsc > drain_tsc)) { 1251 drain_tx_buffers(qconf); 1252 drain_crypto_buffers(qconf); 1253 prev_tsc = cur_tsc; 1254 } 1255 1256 for (i = 0; i < qconf->nb_rx_queue; ++i) { 1257 1258 /* Read packets from RX queues */ 1259 portid = rxql[i].port_id; 1260 queueid = rxql[i].queue_id; 1261 nb_rx = rte_eth_rx_burst(portid, queueid, 1262 pkts, MAX_PKT_BURST); 1263 1264 if (nb_rx > 0) { 1265 core_stats_update_rx(nb_rx); 1266 process_pkts(qconf, pkts, nb_rx, portid); 1267 } 1268 1269 /* dequeue and process completed crypto-ops */ 1270 if (is_unprotected_port(portid)) 1271 drain_inbound_crypto_queues(qconf, 1272 &qconf->inbound); 1273 else 1274 drain_outbound_crypto_queues(qconf, 1275 &qconf->outbound); 1276 } 1277 } 1278 } 1279 1280 int 1281 check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) 1282 { 1283 uint16_t i; 1284 uint16_t portid; 1285 uint8_t queueid; 1286 1287 for (i = 0; i < nb_lcore_params; ++i) { 1288 portid = lcore_params_array[i].port_id; 1289 if (portid == fdir_portid) { 1290 queueid = lcore_params_array[i].queue_id; 1291 if (queueid == fdir_qid) 1292 break; 1293 } 1294 1295 if (i == nb_lcore_params - 1) 1296 return -1; 1297 } 1298 1299 return 1; 1300 } 1301 1302 static int32_t 1303 check_poll_mode_params(struct eh_conf *eh_conf) 1304 { 1305 uint8_t lcore; 1306 uint16_t portid; 1307 uint16_t i; 1308 int32_t socket_id; 1309 1310 if (!eh_conf) 1311 return -EINVAL; 1312 1313 if (eh_conf->mode != EH_PKT_TRANSFER_MODE_POLL) 1314 return 0; 1315 1316 if (lcore_params == NULL) { 1317 printf("Error: No port/queue/core mappings\n"); 1318 return -1; 1319 } 1320 1321 for (i = 0; i < nb_lcore_params; ++i) { 1322 lcore = lcore_params[i].lcore_id; 1323 if (!rte_lcore_is_enabled(lcore)) { 1324 printf("error: lcore %hhu is not enabled in " 1325 "lcore mask\n", lcore); 1326 return -1; 1327 } 1328 socket_id = rte_lcore_to_socket_id(lcore); 1329 if (socket_id != 0 && numa_on == 0) { 1330 printf("warning: lcore %hhu is on socket %d " 1331 "with numa off\n", 1332 lcore, socket_id); 1333 } 1334 portid = lcore_params[i].port_id; 1335 if ((enabled_port_mask & (1 << portid)) == 0) { 1336 printf("port %u is not enabled in port mask\n", portid); 1337 return -1; 1338 } 1339 if (!rte_eth_dev_is_valid_port(portid)) { 1340 printf("port %u is not present on the board\n", portid); 1341 return -1; 1342 } 1343 } 1344 return 0; 1345 } 1346 1347 static uint8_t 1348 get_port_nb_rx_queues(const uint16_t port) 1349 { 1350 int32_t queue = -1; 1351 uint16_t i; 1352 1353 for (i = 0; i < nb_lcore_params; ++i) { 1354 if (lcore_params[i].port_id == port && 1355 lcore_params[i].queue_id > queue) 1356 queue = lcore_params[i].queue_id; 1357 } 1358 return (uint8_t)(++queue); 1359 } 1360 1361 static int32_t 1362 init_lcore_rx_queues(void) 1363 { 1364 uint16_t i, nb_rx_queue; 1365 uint8_t lcore; 1366 1367 for (i = 0; i < nb_lcore_params; ++i) { 1368 lcore = lcore_params[i].lcore_id; 1369 nb_rx_queue = lcore_conf[lcore].nb_rx_queue; 1370 if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 1371 printf("error: too many queues (%u) for lcore: %u\n", 1372 nb_rx_queue + 1, lcore); 1373 return -1; 1374 } 1375 lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 1376 lcore_params[i].port_id; 1377 lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 1378 lcore_params[i].queue_id; 1379 lcore_conf[lcore].nb_rx_queue++; 1380 } 1381 return 0; 1382 } 1383 1384 /* display usage */ 1385 static void 1386 print_usage(const char *prgname) 1387 { 1388 fprintf(stderr, "%s [EAL options] --" 1389 " -p PORTMASK" 1390 " [-P]" 1391 " [-u PORTMASK]" 1392 " [-j FRAMESIZE]" 1393 " [-l]" 1394 " [-w REPLAY_WINDOW_SIZE]" 1395 " [-e]" 1396 " [-a]" 1397 " [-c]" 1398 " [-s NUMBER_OF_MBUFS_IN_PKT_POOL]" 1399 " -f CONFIG_FILE" 1400 " --config (port,queue,lcore)[,(port,queue,lcore)]" 1401 " [--single-sa SAIDX]" 1402 " [--cryptodev_mask MASK]" 1403 " [--transfer-mode MODE]" 1404 " [--event-schedule-type TYPE]" 1405 " [--" CMD_LINE_OPT_RX_OFFLOAD " RX_OFFLOAD_MASK]" 1406 " [--" CMD_LINE_OPT_TX_OFFLOAD " TX_OFFLOAD_MASK]" 1407 " [--" CMD_LINE_OPT_REASSEMBLE " REASSEMBLE_TABLE_SIZE]" 1408 " [--" CMD_LINE_OPT_MTU " MTU]" 1409 "\n\n" 1410 " -p PORTMASK: Hexadecimal bitmask of ports to configure\n" 1411 " -P : Enable promiscuous mode\n" 1412 " -u PORTMASK: Hexadecimal bitmask of unprotected ports\n" 1413 " -j FRAMESIZE: Data buffer size, minimum (and default)\n" 1414 " value: RTE_MBUF_DEFAULT_BUF_SIZE\n" 1415 " -l enables code-path that uses librte_ipsec\n" 1416 " -w REPLAY_WINDOW_SIZE specifies IPsec SQN replay window\n" 1417 " size for each SA\n" 1418 " -e enables ESN\n" 1419 " -a enables SA SQN atomic behaviour\n" 1420 " -c specifies inbound SAD cache size,\n" 1421 " zero value disables the cache (default value: 128)\n" 1422 " -s number of mbufs in packet pool, if not specified number\n" 1423 " of mbufs will be calculated based on number of cores,\n" 1424 " ports and crypto queues\n" 1425 " -f CONFIG_FILE: Configuration file\n" 1426 " --config (port,queue,lcore): Rx queue configuration. In poll\n" 1427 " mode determines which queues from\n" 1428 " which ports are mapped to which cores.\n" 1429 " In event mode this option is not used\n" 1430 " as packets are dynamically scheduled\n" 1431 " to cores by HW.\n" 1432 " --single-sa SAIDX: In poll mode use single SA index for\n" 1433 " outbound traffic, bypassing the SP\n" 1434 " In event mode selects driver submode,\n" 1435 " SA index value is ignored\n" 1436 " --cryptodev_mask MASK: Hexadecimal bitmask of the crypto\n" 1437 " devices to configure\n" 1438 " --transfer-mode MODE\n" 1439 " \"poll\" : Packet transfer via polling (default)\n" 1440 " \"event\" : Packet transfer via event device\n" 1441 " --event-schedule-type TYPE queue schedule type, used only when\n" 1442 " transfer mode is set to event\n" 1443 " \"ordered\" : Ordered (default)\n" 1444 " \"atomic\" : Atomic\n" 1445 " \"parallel\" : Parallel\n" 1446 " --" CMD_LINE_OPT_RX_OFFLOAD 1447 ": bitmask of the RX HW offload capabilities to enable/use\n" 1448 " (DEV_RX_OFFLOAD_*)\n" 1449 " --" CMD_LINE_OPT_TX_OFFLOAD 1450 ": bitmask of the TX HW offload capabilities to enable/use\n" 1451 " (DEV_TX_OFFLOAD_*)\n" 1452 " --" CMD_LINE_OPT_REASSEMBLE " NUM" 1453 ": max number of entries in reassemble(fragment) table\n" 1454 " (zero (default value) disables reassembly)\n" 1455 " --" CMD_LINE_OPT_MTU " MTU" 1456 ": MTU value on all ports (default value: 1500)\n" 1457 " outgoing packets with bigger size will be fragmented\n" 1458 " incoming packets with bigger size will be discarded\n" 1459 " --" CMD_LINE_OPT_FRAG_TTL " FRAG_TTL_NS" 1460 ": fragments lifetime in nanoseconds, default\n" 1461 " and maximum value is 10.000.000.000 ns (10 s)\n" 1462 "\n", 1463 prgname); 1464 } 1465 1466 static int 1467 parse_mask(const char *str, uint64_t *val) 1468 { 1469 char *end; 1470 unsigned long t; 1471 1472 errno = 0; 1473 t = strtoul(str, &end, 0); 1474 if (errno != 0 || end[0] != 0) 1475 return -EINVAL; 1476 1477 *val = t; 1478 return 0; 1479 } 1480 1481 static int32_t 1482 parse_portmask(const char *portmask) 1483 { 1484 char *end = NULL; 1485 unsigned long pm; 1486 1487 errno = 0; 1488 1489 /* parse hexadecimal string */ 1490 pm = strtoul(portmask, &end, 16); 1491 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 1492 return -1; 1493 1494 if ((pm == 0) && errno) 1495 return -1; 1496 1497 return pm; 1498 } 1499 1500 static int64_t 1501 parse_decimal(const char *str) 1502 { 1503 char *end = NULL; 1504 uint64_t num; 1505 1506 num = strtoull(str, &end, 10); 1507 if ((str[0] == '\0') || (end == NULL) || (*end != '\0') 1508 || num > INT64_MAX) 1509 return -1; 1510 1511 return num; 1512 } 1513 1514 static int32_t 1515 parse_config(const char *q_arg) 1516 { 1517 char s[256]; 1518 const char *p, *p0 = q_arg; 1519 char *end; 1520 enum fieldnames { 1521 FLD_PORT = 0, 1522 FLD_QUEUE, 1523 FLD_LCORE, 1524 _NUM_FLD 1525 }; 1526 unsigned long int_fld[_NUM_FLD]; 1527 char *str_fld[_NUM_FLD]; 1528 int32_t i; 1529 uint32_t size; 1530 1531 nb_lcore_params = 0; 1532 1533 while ((p = strchr(p0, '(')) != NULL) { 1534 ++p; 1535 p0 = strchr(p, ')'); 1536 if (p0 == NULL) 1537 return -1; 1538 1539 size = p0 - p; 1540 if (size >= sizeof(s)) 1541 return -1; 1542 1543 snprintf(s, sizeof(s), "%.*s", size, p); 1544 if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 1545 _NUM_FLD) 1546 return -1; 1547 for (i = 0; i < _NUM_FLD; i++) { 1548 errno = 0; 1549 int_fld[i] = strtoul(str_fld[i], &end, 0); 1550 if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) 1551 return -1; 1552 } 1553 if (nb_lcore_params >= MAX_LCORE_PARAMS) { 1554 printf("exceeded max number of lcore params: %hu\n", 1555 nb_lcore_params); 1556 return -1; 1557 } 1558 lcore_params_array[nb_lcore_params].port_id = 1559 (uint8_t)int_fld[FLD_PORT]; 1560 lcore_params_array[nb_lcore_params].queue_id = 1561 (uint8_t)int_fld[FLD_QUEUE]; 1562 lcore_params_array[nb_lcore_params].lcore_id = 1563 (uint8_t)int_fld[FLD_LCORE]; 1564 ++nb_lcore_params; 1565 } 1566 lcore_params = lcore_params_array; 1567 return 0; 1568 } 1569 1570 static void 1571 print_app_sa_prm(const struct app_sa_prm *prm) 1572 { 1573 printf("librte_ipsec usage: %s\n", 1574 (prm->enable == 0) ? "disabled" : "enabled"); 1575 1576 printf("replay window size: %u\n", prm->window_size); 1577 printf("ESN: %s\n", (prm->enable_esn == 0) ? "disabled" : "enabled"); 1578 printf("SA flags: %#" PRIx64 "\n", prm->flags); 1579 printf("Frag TTL: %" PRIu64 " ns\n", frag_ttl_ns); 1580 } 1581 1582 static int 1583 parse_transfer_mode(struct eh_conf *conf, const char *optarg) 1584 { 1585 if (!strcmp(CMD_LINE_ARG_POLL, optarg)) 1586 conf->mode = EH_PKT_TRANSFER_MODE_POLL; 1587 else if (!strcmp(CMD_LINE_ARG_EVENT, optarg)) 1588 conf->mode = EH_PKT_TRANSFER_MODE_EVENT; 1589 else { 1590 printf("Unsupported packet transfer mode\n"); 1591 return -EINVAL; 1592 } 1593 1594 return 0; 1595 } 1596 1597 static int 1598 parse_schedule_type(struct eh_conf *conf, const char *optarg) 1599 { 1600 struct eventmode_conf *em_conf = NULL; 1601 1602 /* Get eventmode conf */ 1603 em_conf = conf->mode_params; 1604 1605 if (!strcmp(CMD_LINE_ARG_ORDERED, optarg)) 1606 em_conf->ext_params.sched_type = RTE_SCHED_TYPE_ORDERED; 1607 else if (!strcmp(CMD_LINE_ARG_ATOMIC, optarg)) 1608 em_conf->ext_params.sched_type = RTE_SCHED_TYPE_ATOMIC; 1609 else if (!strcmp(CMD_LINE_ARG_PARALLEL, optarg)) 1610 em_conf->ext_params.sched_type = RTE_SCHED_TYPE_PARALLEL; 1611 else { 1612 printf("Unsupported queue schedule type\n"); 1613 return -EINVAL; 1614 } 1615 1616 return 0; 1617 } 1618 1619 static int32_t 1620 parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf) 1621 { 1622 int opt; 1623 int64_t ret; 1624 char **argvopt; 1625 int32_t option_index; 1626 char *prgname = argv[0]; 1627 int32_t f_present = 0; 1628 1629 argvopt = argv; 1630 1631 while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:", 1632 lgopts, &option_index)) != EOF) { 1633 1634 switch (opt) { 1635 case 'p': 1636 enabled_port_mask = parse_portmask(optarg); 1637 if (enabled_port_mask == 0) { 1638 printf("invalid portmask\n"); 1639 print_usage(prgname); 1640 return -1; 1641 } 1642 break; 1643 case 'P': 1644 printf("Promiscuous mode selected\n"); 1645 promiscuous_on = 1; 1646 break; 1647 case 'u': 1648 unprotected_port_mask = parse_portmask(optarg); 1649 if (unprotected_port_mask == 0) { 1650 printf("invalid unprotected portmask\n"); 1651 print_usage(prgname); 1652 return -1; 1653 } 1654 break; 1655 case 'f': 1656 if (f_present == 1) { 1657 printf("\"-f\" option present more than " 1658 "once!\n"); 1659 print_usage(prgname); 1660 return -1; 1661 } 1662 cfgfile = optarg; 1663 f_present = 1; 1664 break; 1665 1666 case 's': 1667 ret = parse_decimal(optarg); 1668 if (ret < 0) { 1669 printf("Invalid number of buffers in a pool: " 1670 "%s\n", optarg); 1671 print_usage(prgname); 1672 return -1; 1673 } 1674 1675 nb_bufs_in_pool = ret; 1676 break; 1677 1678 case 'j': 1679 ret = parse_decimal(optarg); 1680 if (ret < RTE_MBUF_DEFAULT_BUF_SIZE || 1681 ret > UINT16_MAX) { 1682 printf("Invalid frame buffer size value: %s\n", 1683 optarg); 1684 print_usage(prgname); 1685 return -1; 1686 } 1687 frame_buf_size = ret; 1688 printf("Custom frame buffer size %u\n", frame_buf_size); 1689 break; 1690 case 'l': 1691 app_sa_prm.enable = 1; 1692 break; 1693 case 'w': 1694 app_sa_prm.window_size = parse_decimal(optarg); 1695 break; 1696 case 'e': 1697 app_sa_prm.enable_esn = 1; 1698 break; 1699 case 'a': 1700 app_sa_prm.enable = 1; 1701 app_sa_prm.flags |= RTE_IPSEC_SAFLAG_SQN_ATOM; 1702 break; 1703 case 'c': 1704 ret = parse_decimal(optarg); 1705 if (ret < 0) { 1706 printf("Invalid SA cache size: %s\n", optarg); 1707 print_usage(prgname); 1708 return -1; 1709 } 1710 app_sa_prm.cache_sz = ret; 1711 break; 1712 case CMD_LINE_OPT_CONFIG_NUM: 1713 ret = parse_config(optarg); 1714 if (ret) { 1715 printf("Invalid config\n"); 1716 print_usage(prgname); 1717 return -1; 1718 } 1719 break; 1720 case CMD_LINE_OPT_SINGLE_SA_NUM: 1721 ret = parse_decimal(optarg); 1722 if (ret == -1 || ret > UINT32_MAX) { 1723 printf("Invalid argument[sa_idx]\n"); 1724 print_usage(prgname); 1725 return -1; 1726 } 1727 1728 /* else */ 1729 single_sa = 1; 1730 single_sa_idx = ret; 1731 eh_conf->ipsec_mode = EH_IPSEC_MODE_TYPE_DRIVER; 1732 printf("Configured with single SA index %u\n", 1733 single_sa_idx); 1734 break; 1735 case CMD_LINE_OPT_CRYPTODEV_MASK_NUM: 1736 ret = parse_portmask(optarg); 1737 if (ret == -1) { 1738 printf("Invalid argument[portmask]\n"); 1739 print_usage(prgname); 1740 return -1; 1741 } 1742 1743 /* else */ 1744 enabled_cryptodev_mask = ret; 1745 break; 1746 1747 case CMD_LINE_OPT_TRANSFER_MODE_NUM: 1748 ret = parse_transfer_mode(eh_conf, optarg); 1749 if (ret < 0) { 1750 printf("Invalid packet transfer mode\n"); 1751 print_usage(prgname); 1752 return -1; 1753 } 1754 break; 1755 1756 case CMD_LINE_OPT_SCHEDULE_TYPE_NUM: 1757 ret = parse_schedule_type(eh_conf, optarg); 1758 if (ret < 0) { 1759 printf("Invalid queue schedule type\n"); 1760 print_usage(prgname); 1761 return -1; 1762 } 1763 break; 1764 1765 case CMD_LINE_OPT_RX_OFFLOAD_NUM: 1766 ret = parse_mask(optarg, &dev_rx_offload); 1767 if (ret != 0) { 1768 printf("Invalid argument for \'%s\': %s\n", 1769 CMD_LINE_OPT_RX_OFFLOAD, optarg); 1770 print_usage(prgname); 1771 return -1; 1772 } 1773 break; 1774 case CMD_LINE_OPT_TX_OFFLOAD_NUM: 1775 ret = parse_mask(optarg, &dev_tx_offload); 1776 if (ret != 0) { 1777 printf("Invalid argument for \'%s\': %s\n", 1778 CMD_LINE_OPT_TX_OFFLOAD, optarg); 1779 print_usage(prgname); 1780 return -1; 1781 } 1782 break; 1783 case CMD_LINE_OPT_REASSEMBLE_NUM: 1784 ret = parse_decimal(optarg); 1785 if (ret < 0 || ret > UINT32_MAX) { 1786 printf("Invalid argument for \'%s\': %s\n", 1787 CMD_LINE_OPT_REASSEMBLE, optarg); 1788 print_usage(prgname); 1789 return -1; 1790 } 1791 frag_tbl_sz = ret; 1792 break; 1793 case CMD_LINE_OPT_MTU_NUM: 1794 ret = parse_decimal(optarg); 1795 if (ret < 0 || ret > RTE_IPV4_MAX_PKT_LEN) { 1796 printf("Invalid argument for \'%s\': %s\n", 1797 CMD_LINE_OPT_MTU, optarg); 1798 print_usage(prgname); 1799 return -1; 1800 } 1801 mtu_size = ret; 1802 break; 1803 case CMD_LINE_OPT_FRAG_TTL_NUM: 1804 ret = parse_decimal(optarg); 1805 if (ret < 0 || ret > MAX_FRAG_TTL_NS) { 1806 printf("Invalid argument for \'%s\': %s\n", 1807 CMD_LINE_OPT_MTU, optarg); 1808 print_usage(prgname); 1809 return -1; 1810 } 1811 frag_ttl_ns = ret; 1812 break; 1813 default: 1814 print_usage(prgname); 1815 return -1; 1816 } 1817 } 1818 1819 if (f_present == 0) { 1820 printf("Mandatory option \"-f\" not present\n"); 1821 return -1; 1822 } 1823 1824 /* check do we need to enable multi-seg support */ 1825 if (multi_seg_required()) { 1826 /* legacy mode doesn't support multi-seg */ 1827 app_sa_prm.enable = 1; 1828 printf("frame buf size: %u, mtu: %u, " 1829 "number of reassemble entries: %u\n" 1830 "multi-segment support is required\n", 1831 frame_buf_size, mtu_size, frag_tbl_sz); 1832 } 1833 1834 print_app_sa_prm(&app_sa_prm); 1835 1836 if (optind >= 0) 1837 argv[optind-1] = prgname; 1838 1839 ret = optind-1; 1840 optind = 1; /* reset getopt lib */ 1841 return ret; 1842 } 1843 1844 static void 1845 print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 1846 { 1847 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 1848 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 1849 printf("%s%s", name, buf); 1850 } 1851 1852 /* 1853 * Update destination ethaddr for the port. 1854 */ 1855 int 1856 add_dst_ethaddr(uint16_t port, const struct rte_ether_addr *addr) 1857 { 1858 if (port >= RTE_DIM(ethaddr_tbl)) 1859 return -EINVAL; 1860 1861 ethaddr_tbl[port].dst = ETHADDR_TO_UINT64(addr); 1862 return 0; 1863 } 1864 1865 /* Check the link status of all ports in up to 9s, and print them finally */ 1866 static void 1867 check_all_ports_link_status(uint32_t port_mask) 1868 { 1869 #define CHECK_INTERVAL 100 /* 100ms */ 1870 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1871 uint16_t portid; 1872 uint8_t count, all_ports_up, print_flag = 0; 1873 struct rte_eth_link link; 1874 int ret; 1875 char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 1876 1877 printf("\nChecking link status"); 1878 fflush(stdout); 1879 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1880 all_ports_up = 1; 1881 RTE_ETH_FOREACH_DEV(portid) { 1882 if ((port_mask & (1 << portid)) == 0) 1883 continue; 1884 memset(&link, 0, sizeof(link)); 1885 ret = rte_eth_link_get_nowait(portid, &link); 1886 if (ret < 0) { 1887 all_ports_up = 0; 1888 if (print_flag == 1) 1889 printf("Port %u link get failed: %s\n", 1890 portid, rte_strerror(-ret)); 1891 continue; 1892 } 1893 /* print link status if flag set */ 1894 if (print_flag == 1) { 1895 rte_eth_link_to_str(link_status_text, 1896 sizeof(link_status_text), &link); 1897 printf("Port %d %s\n", portid, 1898 link_status_text); 1899 continue; 1900 } 1901 /* clear all_ports_up flag if any link down */ 1902 if (link.link_status == ETH_LINK_DOWN) { 1903 all_ports_up = 0; 1904 break; 1905 } 1906 } 1907 /* after finally printing all link status, get out */ 1908 if (print_flag == 1) 1909 break; 1910 1911 if (all_ports_up == 0) { 1912 printf("."); 1913 fflush(stdout); 1914 rte_delay_ms(CHECK_INTERVAL); 1915 } 1916 1917 /* set the print_flag if all ports up or timeout */ 1918 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1919 print_flag = 1; 1920 printf("done\n"); 1921 } 1922 } 1923 } 1924 1925 static int32_t 1926 add_mapping(struct rte_hash *map, const char *str, uint16_t cdev_id, 1927 uint16_t qp, struct lcore_params *params, 1928 struct ipsec_ctx *ipsec_ctx, 1929 const struct rte_cryptodev_capabilities *cipher, 1930 const struct rte_cryptodev_capabilities *auth, 1931 const struct rte_cryptodev_capabilities *aead) 1932 { 1933 int32_t ret = 0; 1934 unsigned long i; 1935 struct cdev_key key = { 0 }; 1936 1937 key.lcore_id = params->lcore_id; 1938 if (cipher) 1939 key.cipher_algo = cipher->sym.cipher.algo; 1940 if (auth) 1941 key.auth_algo = auth->sym.auth.algo; 1942 if (aead) 1943 key.aead_algo = aead->sym.aead.algo; 1944 1945 ret = rte_hash_lookup(map, &key); 1946 if (ret != -ENOENT) 1947 return 0; 1948 1949 for (i = 0; i < ipsec_ctx->nb_qps; i++) 1950 if (ipsec_ctx->tbl[i].id == cdev_id) 1951 break; 1952 1953 if (i == ipsec_ctx->nb_qps) { 1954 if (ipsec_ctx->nb_qps == MAX_QP_PER_LCORE) { 1955 printf("Maximum number of crypto devices assigned to " 1956 "a core, increase MAX_QP_PER_LCORE value\n"); 1957 return 0; 1958 } 1959 ipsec_ctx->tbl[i].id = cdev_id; 1960 ipsec_ctx->tbl[i].qp = qp; 1961 ipsec_ctx->nb_qps++; 1962 printf("%s cdev mapping: lcore %u using cdev %u qp %u " 1963 "(cdev_id_qp %lu)\n", str, key.lcore_id, 1964 cdev_id, qp, i); 1965 } 1966 1967 ret = rte_hash_add_key_data(map, &key, (void *)i); 1968 if (ret < 0) { 1969 printf("Faled to insert cdev mapping for (lcore %u, " 1970 "cdev %u, qp %u), errno %d\n", 1971 key.lcore_id, ipsec_ctx->tbl[i].id, 1972 ipsec_ctx->tbl[i].qp, ret); 1973 return 0; 1974 } 1975 1976 return 1; 1977 } 1978 1979 static int32_t 1980 add_cdev_mapping(struct rte_cryptodev_info *dev_info, uint16_t cdev_id, 1981 uint16_t qp, struct lcore_params *params) 1982 { 1983 int32_t ret = 0; 1984 const struct rte_cryptodev_capabilities *i, *j; 1985 struct rte_hash *map; 1986 struct lcore_conf *qconf; 1987 struct ipsec_ctx *ipsec_ctx; 1988 const char *str; 1989 1990 qconf = &lcore_conf[params->lcore_id]; 1991 1992 if ((unprotected_port_mask & (1 << params->port_id)) == 0) { 1993 map = cdev_map_out; 1994 ipsec_ctx = &qconf->outbound; 1995 str = "Outbound"; 1996 } else { 1997 map = cdev_map_in; 1998 ipsec_ctx = &qconf->inbound; 1999 str = "Inbound"; 2000 } 2001 2002 /* Required cryptodevs with operation chainning */ 2003 if (!(dev_info->feature_flags & 2004 RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING)) 2005 return ret; 2006 2007 for (i = dev_info->capabilities; 2008 i->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; i++) { 2009 if (i->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC) 2010 continue; 2011 2012 if (i->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD) { 2013 ret |= add_mapping(map, str, cdev_id, qp, params, 2014 ipsec_ctx, NULL, NULL, i); 2015 continue; 2016 } 2017 2018 if (i->sym.xform_type != RTE_CRYPTO_SYM_XFORM_CIPHER) 2019 continue; 2020 2021 for (j = dev_info->capabilities; 2022 j->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; j++) { 2023 if (j->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC) 2024 continue; 2025 2026 if (j->sym.xform_type != RTE_CRYPTO_SYM_XFORM_AUTH) 2027 continue; 2028 2029 ret |= add_mapping(map, str, cdev_id, qp, params, 2030 ipsec_ctx, i, j, NULL); 2031 } 2032 } 2033 2034 return ret; 2035 } 2036 2037 /* Check if the device is enabled by cryptodev_mask */ 2038 static int 2039 check_cryptodev_mask(uint8_t cdev_id) 2040 { 2041 if (enabled_cryptodev_mask & (1 << cdev_id)) 2042 return 0; 2043 2044 return -1; 2045 } 2046 2047 static uint16_t 2048 cryptodevs_init(uint16_t req_queue_num) 2049 { 2050 struct rte_cryptodev_config dev_conf; 2051 struct rte_cryptodev_qp_conf qp_conf; 2052 uint16_t idx, max_nb_qps, qp, total_nb_qps, i; 2053 int16_t cdev_id; 2054 struct rte_hash_parameters params = { 0 }; 2055 2056 const uint64_t mseg_flag = multi_seg_required() ? 2057 RTE_CRYPTODEV_FF_IN_PLACE_SGL : 0; 2058 2059 params.entries = CDEV_MAP_ENTRIES; 2060 params.key_len = sizeof(struct cdev_key); 2061 params.hash_func = rte_jhash; 2062 params.hash_func_init_val = 0; 2063 params.socket_id = rte_socket_id(); 2064 2065 params.name = "cdev_map_in"; 2066 cdev_map_in = rte_hash_create(¶ms); 2067 if (cdev_map_in == NULL) 2068 rte_panic("Failed to create cdev_map hash table, errno = %d\n", 2069 rte_errno); 2070 2071 params.name = "cdev_map_out"; 2072 cdev_map_out = rte_hash_create(¶ms); 2073 if (cdev_map_out == NULL) 2074 rte_panic("Failed to create cdev_map hash table, errno = %d\n", 2075 rte_errno); 2076 2077 printf("lcore/cryptodev/qp mappings:\n"); 2078 2079 idx = 0; 2080 total_nb_qps = 0; 2081 for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) { 2082 struct rte_cryptodev_info cdev_info; 2083 2084 if (check_cryptodev_mask((uint8_t)cdev_id)) 2085 continue; 2086 2087 rte_cryptodev_info_get(cdev_id, &cdev_info); 2088 2089 if ((mseg_flag & cdev_info.feature_flags) != mseg_flag) 2090 rte_exit(EXIT_FAILURE, 2091 "Device %hd does not support \'%s\' feature\n", 2092 cdev_id, 2093 rte_cryptodev_get_feature_name(mseg_flag)); 2094 2095 if (nb_lcore_params > cdev_info.max_nb_queue_pairs) 2096 max_nb_qps = cdev_info.max_nb_queue_pairs; 2097 else 2098 max_nb_qps = nb_lcore_params; 2099 2100 qp = 0; 2101 i = 0; 2102 while (qp < max_nb_qps && i < nb_lcore_params) { 2103 if (add_cdev_mapping(&cdev_info, cdev_id, qp, 2104 &lcore_params[idx])) 2105 qp++; 2106 idx++; 2107 idx = idx % nb_lcore_params; 2108 i++; 2109 } 2110 2111 qp = RTE_MIN(max_nb_qps, RTE_MAX(req_queue_num, qp)); 2112 if (qp == 0) 2113 continue; 2114 2115 total_nb_qps += qp; 2116 dev_conf.socket_id = rte_cryptodev_socket_id(cdev_id); 2117 dev_conf.nb_queue_pairs = qp; 2118 dev_conf.ff_disable = RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO; 2119 2120 uint32_t dev_max_sess = cdev_info.sym.max_nb_sessions; 2121 if (dev_max_sess != 0 && 2122 dev_max_sess < get_nb_crypto_sessions()) 2123 rte_exit(EXIT_FAILURE, 2124 "Device does not support at least %u " 2125 "sessions", get_nb_crypto_sessions()); 2126 2127 if (rte_cryptodev_configure(cdev_id, &dev_conf)) 2128 rte_panic("Failed to initialize cryptodev %u\n", 2129 cdev_id); 2130 2131 qp_conf.nb_descriptors = CDEV_QUEUE_DESC; 2132 qp_conf.mp_session = 2133 socket_ctx[dev_conf.socket_id].session_pool; 2134 qp_conf.mp_session_private = 2135 socket_ctx[dev_conf.socket_id].session_priv_pool; 2136 for (qp = 0; qp < dev_conf.nb_queue_pairs; qp++) 2137 if (rte_cryptodev_queue_pair_setup(cdev_id, qp, 2138 &qp_conf, dev_conf.socket_id)) 2139 rte_panic("Failed to setup queue %u for " 2140 "cdev_id %u\n", 0, cdev_id); 2141 2142 if (rte_cryptodev_start(cdev_id)) 2143 rte_panic("Failed to start cryptodev %u\n", 2144 cdev_id); 2145 } 2146 2147 printf("\n"); 2148 2149 return total_nb_qps; 2150 } 2151 2152 static void 2153 port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads) 2154 { 2155 uint32_t frame_size; 2156 struct rte_eth_dev_info dev_info; 2157 struct rte_eth_txconf *txconf; 2158 uint16_t nb_tx_queue, nb_rx_queue; 2159 uint16_t tx_queueid, rx_queueid, queue, lcore_id; 2160 int32_t ret, socket_id; 2161 struct lcore_conf *qconf; 2162 struct rte_ether_addr ethaddr; 2163 struct rte_eth_conf local_port_conf = port_conf; 2164 2165 ret = rte_eth_dev_info_get(portid, &dev_info); 2166 if (ret != 0) 2167 rte_exit(EXIT_FAILURE, 2168 "Error during getting device (port %u) info: %s\n", 2169 portid, strerror(-ret)); 2170 2171 /* limit allowed HW offloafs, as user requested */ 2172 dev_info.rx_offload_capa &= dev_rx_offload; 2173 dev_info.tx_offload_capa &= dev_tx_offload; 2174 2175 printf("Configuring device port %u:\n", portid); 2176 2177 ret = rte_eth_macaddr_get(portid, ðaddr); 2178 if (ret != 0) 2179 rte_exit(EXIT_FAILURE, 2180 "Error getting MAC address (port %u): %s\n", 2181 portid, rte_strerror(-ret)); 2182 2183 ethaddr_tbl[portid].src = ETHADDR_TO_UINT64(ðaddr); 2184 print_ethaddr("Address: ", ðaddr); 2185 printf("\n"); 2186 2187 nb_rx_queue = get_port_nb_rx_queues(portid); 2188 nb_tx_queue = nb_lcores; 2189 2190 if (nb_rx_queue > dev_info.max_rx_queues) 2191 rte_exit(EXIT_FAILURE, "Error: queue %u not available " 2192 "(max rx queue is %u)\n", 2193 nb_rx_queue, dev_info.max_rx_queues); 2194 2195 if (nb_tx_queue > dev_info.max_tx_queues) 2196 rte_exit(EXIT_FAILURE, "Error: queue %u not available " 2197 "(max tx queue is %u)\n", 2198 nb_tx_queue, dev_info.max_tx_queues); 2199 2200 printf("Creating queues: nb_rx_queue=%d nb_tx_queue=%u...\n", 2201 nb_rx_queue, nb_tx_queue); 2202 2203 frame_size = MTU_TO_FRAMELEN(mtu_size); 2204 if (frame_size > local_port_conf.rxmode.max_rx_pkt_len) 2205 local_port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; 2206 local_port_conf.rxmode.max_rx_pkt_len = frame_size; 2207 2208 if (multi_seg_required()) { 2209 local_port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER; 2210 local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS; 2211 } 2212 2213 local_port_conf.rxmode.offloads |= req_rx_offloads; 2214 local_port_conf.txmode.offloads |= req_tx_offloads; 2215 2216 /* Check that all required capabilities are supported */ 2217 if ((local_port_conf.rxmode.offloads & dev_info.rx_offload_capa) != 2218 local_port_conf.rxmode.offloads) 2219 rte_exit(EXIT_FAILURE, 2220 "Error: port %u required RX offloads: 0x%" PRIx64 2221 ", avaialbe RX offloads: 0x%" PRIx64 "\n", 2222 portid, local_port_conf.rxmode.offloads, 2223 dev_info.rx_offload_capa); 2224 2225 if ((local_port_conf.txmode.offloads & dev_info.tx_offload_capa) != 2226 local_port_conf.txmode.offloads) 2227 rte_exit(EXIT_FAILURE, 2228 "Error: port %u required TX offloads: 0x%" PRIx64 2229 ", avaialbe TX offloads: 0x%" PRIx64 "\n", 2230 portid, local_port_conf.txmode.offloads, 2231 dev_info.tx_offload_capa); 2232 2233 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 2234 local_port_conf.txmode.offloads |= 2235 DEV_TX_OFFLOAD_MBUF_FAST_FREE; 2236 2237 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) 2238 local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM; 2239 2240 printf("port %u configurng rx_offloads=0x%" PRIx64 2241 ", tx_offloads=0x%" PRIx64 "\n", 2242 portid, local_port_conf.rxmode.offloads, 2243 local_port_conf.txmode.offloads); 2244 2245 local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 2246 dev_info.flow_type_rss_offloads; 2247 if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 2248 port_conf.rx_adv_conf.rss_conf.rss_hf) { 2249 printf("Port %u modified RSS hash function based on hardware support," 2250 "requested:%#"PRIx64" configured:%#"PRIx64"\n", 2251 portid, 2252 port_conf.rx_adv_conf.rss_conf.rss_hf, 2253 local_port_conf.rx_adv_conf.rss_conf.rss_hf); 2254 } 2255 2256 ret = rte_eth_dev_configure(portid, nb_rx_queue, nb_tx_queue, 2257 &local_port_conf); 2258 if (ret < 0) 2259 rte_exit(EXIT_FAILURE, "Cannot configure device: " 2260 "err=%d, port=%d\n", ret, portid); 2261 2262 ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd); 2263 if (ret < 0) 2264 rte_exit(EXIT_FAILURE, "Cannot adjust number of descriptors: " 2265 "err=%d, port=%d\n", ret, portid); 2266 2267 /* init one TX queue per lcore */ 2268 tx_queueid = 0; 2269 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2270 if (rte_lcore_is_enabled(lcore_id) == 0) 2271 continue; 2272 2273 if (numa_on) 2274 socket_id = (uint8_t)rte_lcore_to_socket_id(lcore_id); 2275 else 2276 socket_id = 0; 2277 2278 /* init TX queue */ 2279 printf("Setup txq=%u,%d,%d\n", lcore_id, tx_queueid, socket_id); 2280 2281 txconf = &dev_info.default_txconf; 2282 txconf->offloads = local_port_conf.txmode.offloads; 2283 2284 ret = rte_eth_tx_queue_setup(portid, tx_queueid, nb_txd, 2285 socket_id, txconf); 2286 if (ret < 0) 2287 rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: " 2288 "err=%d, port=%d\n", ret, portid); 2289 2290 qconf = &lcore_conf[lcore_id]; 2291 qconf->tx_queue_id[portid] = tx_queueid; 2292 2293 /* Pre-populate pkt offloads based on capabilities */ 2294 qconf->outbound.ipv4_offloads = PKT_TX_IPV4; 2295 qconf->outbound.ipv6_offloads = PKT_TX_IPV6; 2296 if (local_port_conf.txmode.offloads & DEV_TX_OFFLOAD_IPV4_CKSUM) 2297 qconf->outbound.ipv4_offloads |= PKT_TX_IP_CKSUM; 2298 2299 tx_queueid++; 2300 2301 /* init RX queues */ 2302 for (queue = 0; queue < qconf->nb_rx_queue; ++queue) { 2303 struct rte_eth_rxconf rxq_conf; 2304 2305 if (portid != qconf->rx_queue_list[queue].port_id) 2306 continue; 2307 2308 rx_queueid = qconf->rx_queue_list[queue].queue_id; 2309 2310 printf("Setup rxq=%d,%d,%d\n", portid, rx_queueid, 2311 socket_id); 2312 2313 rxq_conf = dev_info.default_rxconf; 2314 rxq_conf.offloads = local_port_conf.rxmode.offloads; 2315 ret = rte_eth_rx_queue_setup(portid, rx_queueid, 2316 nb_rxd, socket_id, &rxq_conf, 2317 socket_ctx[socket_id].mbuf_pool); 2318 if (ret < 0) 2319 rte_exit(EXIT_FAILURE, 2320 "rte_eth_rx_queue_setup: err=%d, " 2321 "port=%d\n", ret, portid); 2322 } 2323 } 2324 printf("\n"); 2325 } 2326 2327 static size_t 2328 max_session_size(void) 2329 { 2330 size_t max_sz, sz; 2331 void *sec_ctx; 2332 int16_t cdev_id, port_id, n; 2333 2334 max_sz = 0; 2335 n = rte_cryptodev_count(); 2336 for (cdev_id = 0; cdev_id != n; cdev_id++) { 2337 sz = rte_cryptodev_sym_get_private_session_size(cdev_id); 2338 if (sz > max_sz) 2339 max_sz = sz; 2340 /* 2341 * If crypto device is security capable, need to check the 2342 * size of security session as well. 2343 */ 2344 2345 /* Get security context of the crypto device */ 2346 sec_ctx = rte_cryptodev_get_sec_ctx(cdev_id); 2347 if (sec_ctx == NULL) 2348 continue; 2349 2350 /* Get size of security session */ 2351 sz = rte_security_session_get_size(sec_ctx); 2352 if (sz > max_sz) 2353 max_sz = sz; 2354 } 2355 2356 RTE_ETH_FOREACH_DEV(port_id) { 2357 if ((enabled_port_mask & (1 << port_id)) == 0) 2358 continue; 2359 2360 sec_ctx = rte_eth_dev_get_sec_ctx(port_id); 2361 if (sec_ctx == NULL) 2362 continue; 2363 2364 sz = rte_security_session_get_size(sec_ctx); 2365 if (sz > max_sz) 2366 max_sz = sz; 2367 } 2368 2369 return max_sz; 2370 } 2371 2372 static void 2373 session_pool_init(struct socket_ctx *ctx, int32_t socket_id, size_t sess_sz) 2374 { 2375 char mp_name[RTE_MEMPOOL_NAMESIZE]; 2376 struct rte_mempool *sess_mp; 2377 uint32_t nb_sess; 2378 2379 snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, 2380 "sess_mp_%u", socket_id); 2381 nb_sess = (get_nb_crypto_sessions() + CDEV_MP_CACHE_SZ * 2382 rte_lcore_count()); 2383 nb_sess = RTE_MAX(nb_sess, CDEV_MP_CACHE_SZ * 2384 CDEV_MP_CACHE_MULTIPLIER); 2385 sess_mp = rte_cryptodev_sym_session_pool_create( 2386 mp_name, nb_sess, sess_sz, CDEV_MP_CACHE_SZ, 0, 2387 socket_id); 2388 ctx->session_pool = sess_mp; 2389 2390 if (ctx->session_pool == NULL) 2391 rte_exit(EXIT_FAILURE, 2392 "Cannot init session pool on socket %d\n", socket_id); 2393 else 2394 printf("Allocated session pool on socket %d\n", socket_id); 2395 } 2396 2397 static void 2398 session_priv_pool_init(struct socket_ctx *ctx, int32_t socket_id, 2399 size_t sess_sz) 2400 { 2401 char mp_name[RTE_MEMPOOL_NAMESIZE]; 2402 struct rte_mempool *sess_mp; 2403 uint32_t nb_sess; 2404 2405 snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, 2406 "sess_mp_priv_%u", socket_id); 2407 nb_sess = (get_nb_crypto_sessions() + CDEV_MP_CACHE_SZ * 2408 rte_lcore_count()); 2409 nb_sess = RTE_MAX(nb_sess, CDEV_MP_CACHE_SZ * 2410 CDEV_MP_CACHE_MULTIPLIER); 2411 sess_mp = rte_mempool_create(mp_name, 2412 nb_sess, 2413 sess_sz, 2414 CDEV_MP_CACHE_SZ, 2415 0, NULL, NULL, NULL, 2416 NULL, socket_id, 2417 0); 2418 ctx->session_priv_pool = sess_mp; 2419 2420 if (ctx->session_priv_pool == NULL) 2421 rte_exit(EXIT_FAILURE, 2422 "Cannot init session priv pool on socket %d\n", 2423 socket_id); 2424 else 2425 printf("Allocated session priv pool on socket %d\n", 2426 socket_id); 2427 } 2428 2429 static void 2430 pool_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t nb_mbuf) 2431 { 2432 char s[64]; 2433 int32_t ms; 2434 2435 snprintf(s, sizeof(s), "mbuf_pool_%d", socket_id); 2436 ctx->mbuf_pool = rte_pktmbuf_pool_create(s, nb_mbuf, 2437 MEMPOOL_CACHE_SIZE, ipsec_metadata_size(), 2438 frame_buf_size, socket_id); 2439 2440 /* 2441 * if multi-segment support is enabled, then create a pool 2442 * for indirect mbufs. 2443 */ 2444 ms = multi_seg_required(); 2445 if (ms != 0) { 2446 snprintf(s, sizeof(s), "mbuf_pool_indir_%d", socket_id); 2447 ctx->mbuf_pool_indir = rte_pktmbuf_pool_create(s, nb_mbuf, 2448 MEMPOOL_CACHE_SIZE, 0, 0, socket_id); 2449 } 2450 2451 if (ctx->mbuf_pool == NULL || (ms != 0 && ctx->mbuf_pool_indir == NULL)) 2452 rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", 2453 socket_id); 2454 else 2455 printf("Allocated mbuf pool on socket %d\n", socket_id); 2456 } 2457 2458 static inline int 2459 inline_ipsec_event_esn_overflow(struct rte_security_ctx *ctx, uint64_t md) 2460 { 2461 struct ipsec_sa *sa; 2462 2463 /* For inline protocol processing, the metadata in the event will 2464 * uniquely identify the security session which raised the event. 2465 * Application would then need the userdata it had registered with the 2466 * security session to process the event. 2467 */ 2468 2469 sa = (struct ipsec_sa *)rte_security_get_userdata(ctx, md); 2470 2471 if (sa == NULL) { 2472 /* userdata could not be retrieved */ 2473 return -1; 2474 } 2475 2476 /* Sequence number over flow. SA need to be re-established */ 2477 RTE_SET_USED(sa); 2478 return 0; 2479 } 2480 2481 static int 2482 inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type, 2483 void *param, void *ret_param) 2484 { 2485 uint64_t md; 2486 struct rte_eth_event_ipsec_desc *event_desc = NULL; 2487 struct rte_security_ctx *ctx = (struct rte_security_ctx *) 2488 rte_eth_dev_get_sec_ctx(port_id); 2489 2490 RTE_SET_USED(param); 2491 2492 if (type != RTE_ETH_EVENT_IPSEC) 2493 return -1; 2494 2495 event_desc = ret_param; 2496 if (event_desc == NULL) { 2497 printf("Event descriptor not set\n"); 2498 return -1; 2499 } 2500 2501 md = event_desc->metadata; 2502 2503 if (event_desc->subtype == RTE_ETH_EVENT_IPSEC_ESN_OVERFLOW) 2504 return inline_ipsec_event_esn_overflow(ctx, md); 2505 else if (event_desc->subtype >= RTE_ETH_EVENT_IPSEC_MAX) { 2506 printf("Invalid IPsec event reported\n"); 2507 return -1; 2508 } 2509 2510 return -1; 2511 } 2512 2513 static uint16_t 2514 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue, 2515 struct rte_mbuf *pkt[], uint16_t nb_pkts, 2516 __rte_unused uint16_t max_pkts, void *user_param) 2517 { 2518 uint64_t tm; 2519 uint32_t i, k; 2520 struct lcore_conf *lc; 2521 struct rte_mbuf *mb; 2522 struct rte_ether_hdr *eth; 2523 2524 lc = user_param; 2525 k = 0; 2526 tm = 0; 2527 2528 for (i = 0; i != nb_pkts; i++) { 2529 2530 mb = pkt[i]; 2531 eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *); 2532 if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { 2533 2534 struct rte_ipv4_hdr *iph; 2535 2536 iph = (struct rte_ipv4_hdr *)(eth + 1); 2537 if (rte_ipv4_frag_pkt_is_fragmented(iph)) { 2538 2539 mb->l2_len = sizeof(*eth); 2540 mb->l3_len = sizeof(*iph); 2541 tm = (tm != 0) ? tm : rte_rdtsc(); 2542 mb = rte_ipv4_frag_reassemble_packet( 2543 lc->frag.tbl, &lc->frag.dr, 2544 mb, tm, iph); 2545 2546 if (mb != NULL) { 2547 /* fix ip cksum after reassemble. */ 2548 iph = rte_pktmbuf_mtod_offset(mb, 2549 struct rte_ipv4_hdr *, 2550 mb->l2_len); 2551 iph->hdr_checksum = 0; 2552 iph->hdr_checksum = rte_ipv4_cksum(iph); 2553 } 2554 } 2555 } else if (eth->ether_type == 2556 rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { 2557 2558 struct rte_ipv6_hdr *iph; 2559 struct ipv6_extension_fragment *fh; 2560 2561 iph = (struct rte_ipv6_hdr *)(eth + 1); 2562 fh = rte_ipv6_frag_get_ipv6_fragment_header(iph); 2563 if (fh != NULL) { 2564 mb->l2_len = sizeof(*eth); 2565 mb->l3_len = (uintptr_t)fh - (uintptr_t)iph + 2566 sizeof(*fh); 2567 tm = (tm != 0) ? tm : rte_rdtsc(); 2568 mb = rte_ipv6_frag_reassemble_packet( 2569 lc->frag.tbl, &lc->frag.dr, 2570 mb, tm, iph, fh); 2571 if (mb != NULL) 2572 /* fix l3_len after reassemble. */ 2573 mb->l3_len = mb->l3_len - sizeof(*fh); 2574 } 2575 } 2576 2577 pkt[k] = mb; 2578 k += (mb != NULL); 2579 } 2580 2581 /* some fragments were encountered, drain death row */ 2582 if (tm != 0) 2583 rte_ip_frag_free_death_row(&lc->frag.dr, 0); 2584 2585 return k; 2586 } 2587 2588 2589 static int 2590 reassemble_lcore_init(struct lcore_conf *lc, uint32_t cid) 2591 { 2592 int32_t sid; 2593 uint32_t i; 2594 uint64_t frag_cycles; 2595 const struct lcore_rx_queue *rxq; 2596 const struct rte_eth_rxtx_callback *cb; 2597 2598 /* create fragment table */ 2599 sid = rte_lcore_to_socket_id(cid); 2600 frag_cycles = (rte_get_tsc_hz() + NS_PER_S - 1) / 2601 NS_PER_S * frag_ttl_ns; 2602 2603 lc->frag.tbl = rte_ip_frag_table_create(frag_tbl_sz, 2604 FRAG_TBL_BUCKET_ENTRIES, frag_tbl_sz, frag_cycles, sid); 2605 if (lc->frag.tbl == NULL) { 2606 printf("%s(%u): failed to create fragment table of size: %u, " 2607 "error code: %d\n", 2608 __func__, cid, frag_tbl_sz, rte_errno); 2609 return -ENOMEM; 2610 } 2611 2612 /* setup reassemble RX callbacks for all queues */ 2613 for (i = 0; i != lc->nb_rx_queue; i++) { 2614 2615 rxq = lc->rx_queue_list + i; 2616 cb = rte_eth_add_rx_callback(rxq->port_id, rxq->queue_id, 2617 rx_callback, lc); 2618 if (cb == NULL) { 2619 printf("%s(%u): failed to install RX callback for " 2620 "portid=%u, queueid=%u, error code: %d\n", 2621 __func__, cid, 2622 rxq->port_id, rxq->queue_id, rte_errno); 2623 return -ENOMEM; 2624 } 2625 } 2626 2627 return 0; 2628 } 2629 2630 static int 2631 reassemble_init(void) 2632 { 2633 int32_t rc; 2634 uint32_t i, lc; 2635 2636 rc = 0; 2637 for (i = 0; i != nb_lcore_params; i++) { 2638 lc = lcore_params[i].lcore_id; 2639 rc = reassemble_lcore_init(lcore_conf + lc, lc); 2640 if (rc != 0) 2641 break; 2642 } 2643 2644 return rc; 2645 } 2646 2647 static void 2648 create_default_ipsec_flow(uint16_t port_id, uint64_t rx_offloads) 2649 { 2650 struct rte_flow_action action[2]; 2651 struct rte_flow_item pattern[2]; 2652 struct rte_flow_attr attr = {0}; 2653 struct rte_flow_error err; 2654 struct rte_flow *flow; 2655 int ret; 2656 2657 if (!(rx_offloads & DEV_RX_OFFLOAD_SECURITY)) 2658 return; 2659 2660 /* Add the default rte_flow to enable SECURITY for all ESP packets */ 2661 2662 pattern[0].type = RTE_FLOW_ITEM_TYPE_ESP; 2663 pattern[0].spec = NULL; 2664 pattern[0].mask = NULL; 2665 pattern[0].last = NULL; 2666 pattern[1].type = RTE_FLOW_ITEM_TYPE_END; 2667 2668 action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY; 2669 action[0].conf = NULL; 2670 action[1].type = RTE_FLOW_ACTION_TYPE_END; 2671 action[1].conf = NULL; 2672 2673 attr.ingress = 1; 2674 2675 ret = rte_flow_validate(port_id, &attr, pattern, action, &err); 2676 if (ret) 2677 return; 2678 2679 flow = rte_flow_create(port_id, &attr, pattern, action, &err); 2680 if (flow == NULL) 2681 return; 2682 2683 flow_info_tbl[port_id].rx_def_flow = flow; 2684 RTE_LOG(INFO, IPSEC, 2685 "Created default flow enabling SECURITY for all ESP traffic on port %d\n", 2686 port_id); 2687 } 2688 2689 static void 2690 signal_handler(int signum) 2691 { 2692 if (signum == SIGINT || signum == SIGTERM) { 2693 printf("\n\nSignal %d received, preparing to exit...\n", 2694 signum); 2695 force_quit = true; 2696 } 2697 } 2698 2699 static void 2700 ev_mode_sess_verify(struct ipsec_sa *sa, int nb_sa) 2701 { 2702 struct rte_ipsec_session *ips; 2703 int32_t i; 2704 2705 if (!sa || !nb_sa) 2706 return; 2707 2708 for (i = 0; i < nb_sa; i++) { 2709 ips = ipsec_get_primary_session(&sa[i]); 2710 if (ips->type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) 2711 rte_exit(EXIT_FAILURE, "Event mode supports only " 2712 "inline protocol sessions\n"); 2713 } 2714 2715 } 2716 2717 static int32_t 2718 check_event_mode_params(struct eh_conf *eh_conf) 2719 { 2720 struct eventmode_conf *em_conf = NULL; 2721 struct lcore_params *params; 2722 uint16_t portid; 2723 2724 if (!eh_conf || !eh_conf->mode_params) 2725 return -EINVAL; 2726 2727 /* Get eventmode conf */ 2728 em_conf = eh_conf->mode_params; 2729 2730 if (eh_conf->mode == EH_PKT_TRANSFER_MODE_POLL && 2731 em_conf->ext_params.sched_type != SCHED_TYPE_NOT_SET) { 2732 printf("error: option --event-schedule-type applies only to " 2733 "event mode\n"); 2734 return -EINVAL; 2735 } 2736 2737 if (eh_conf->mode != EH_PKT_TRANSFER_MODE_EVENT) 2738 return 0; 2739 2740 /* Set schedule type to ORDERED if it wasn't explicitly set by user */ 2741 if (em_conf->ext_params.sched_type == SCHED_TYPE_NOT_SET) 2742 em_conf->ext_params.sched_type = RTE_SCHED_TYPE_ORDERED; 2743 2744 /* 2745 * Event mode currently supports only inline protocol sessions. 2746 * If there are other types of sessions configured then exit with 2747 * error. 2748 */ 2749 ev_mode_sess_verify(sa_in, nb_sa_in); 2750 ev_mode_sess_verify(sa_out, nb_sa_out); 2751 2752 2753 /* Option --config does not apply to event mode */ 2754 if (nb_lcore_params > 0) { 2755 printf("error: option --config applies only to poll mode\n"); 2756 return -EINVAL; 2757 } 2758 2759 /* 2760 * In order to use the same port_init routine for both poll and event 2761 * modes initialize lcore_params with one queue for each eth port 2762 */ 2763 lcore_params = lcore_params_array; 2764 RTE_ETH_FOREACH_DEV(portid) { 2765 if ((enabled_port_mask & (1 << portid)) == 0) 2766 continue; 2767 2768 params = &lcore_params[nb_lcore_params++]; 2769 params->port_id = portid; 2770 params->queue_id = 0; 2771 params->lcore_id = rte_get_next_lcore(0, 0, 1); 2772 } 2773 2774 return 0; 2775 } 2776 2777 static void 2778 inline_sessions_free(struct sa_ctx *sa_ctx) 2779 { 2780 struct rte_ipsec_session *ips; 2781 struct ipsec_sa *sa; 2782 int32_t ret; 2783 uint32_t i; 2784 2785 if (!sa_ctx) 2786 return; 2787 2788 for (i = 0; i < sa_ctx->nb_sa; i++) { 2789 2790 sa = &sa_ctx->sa[i]; 2791 if (!sa->spi) 2792 continue; 2793 2794 ips = ipsec_get_primary_session(sa); 2795 if (ips->type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL && 2796 ips->type != RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) 2797 continue; 2798 2799 if (!rte_eth_dev_is_valid_port(sa->portid)) 2800 continue; 2801 2802 ret = rte_security_session_destroy( 2803 rte_eth_dev_get_sec_ctx(sa->portid), 2804 ips->security.ses); 2805 if (ret) 2806 RTE_LOG(ERR, IPSEC, "Failed to destroy security " 2807 "session type %d, spi %d\n", 2808 ips->type, sa->spi); 2809 } 2810 } 2811 2812 static uint32_t 2813 calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq, 2814 uint32_t nb_txq) 2815 { 2816 return RTE_MAX((nb_rxq * nb_rxd + 2817 nb_ports * nb_lcores * MAX_PKT_BURST + 2818 nb_ports * nb_txq * nb_txd + 2819 nb_lcores * MEMPOOL_CACHE_SIZE + 2820 nb_crypto_qp * CDEV_QUEUE_DESC + 2821 nb_lcores * frag_tbl_sz * 2822 FRAG_TBL_BUCKET_ENTRIES), 2823 8192U); 2824 } 2825 2826 int32_t 2827 main(int32_t argc, char **argv) 2828 { 2829 int32_t ret; 2830 uint32_t lcore_id, nb_txq, nb_rxq = 0; 2831 uint32_t cdev_id; 2832 uint32_t i; 2833 uint8_t socket_id; 2834 uint16_t portid, nb_crypto_qp, nb_ports = 0; 2835 uint64_t req_rx_offloads[RTE_MAX_ETHPORTS]; 2836 uint64_t req_tx_offloads[RTE_MAX_ETHPORTS]; 2837 struct eh_conf *eh_conf = NULL; 2838 size_t sess_sz; 2839 2840 nb_bufs_in_pool = 0; 2841 2842 /* init EAL */ 2843 ret = rte_eal_init(argc, argv); 2844 if (ret < 0) 2845 rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 2846 argc -= ret; 2847 argv += ret; 2848 2849 force_quit = false; 2850 signal(SIGINT, signal_handler); 2851 signal(SIGTERM, signal_handler); 2852 2853 /* initialize event helper configuration */ 2854 eh_conf = eh_conf_init(); 2855 if (eh_conf == NULL) 2856 rte_exit(EXIT_FAILURE, "Failed to init event helper config"); 2857 2858 /* parse application arguments (after the EAL ones) */ 2859 ret = parse_args(argc, argv, eh_conf); 2860 if (ret < 0) 2861 rte_exit(EXIT_FAILURE, "Invalid parameters\n"); 2862 2863 /* parse configuration file */ 2864 if (parse_cfg_file(cfgfile) < 0) { 2865 printf("parsing file \"%s\" failed\n", 2866 optarg); 2867 print_usage(argv[0]); 2868 return -1; 2869 } 2870 2871 if ((unprotected_port_mask & enabled_port_mask) != 2872 unprotected_port_mask) 2873 rte_exit(EXIT_FAILURE, "Invalid unprotected portmask 0x%x\n", 2874 unprotected_port_mask); 2875 2876 if (check_poll_mode_params(eh_conf) < 0) 2877 rte_exit(EXIT_FAILURE, "check_poll_mode_params failed\n"); 2878 2879 if (check_event_mode_params(eh_conf) < 0) 2880 rte_exit(EXIT_FAILURE, "check_event_mode_params failed\n"); 2881 2882 ret = init_lcore_rx_queues(); 2883 if (ret < 0) 2884 rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); 2885 2886 nb_lcores = rte_lcore_count(); 2887 2888 sess_sz = max_session_size(); 2889 2890 /* 2891 * In event mode request minimum number of crypto queues 2892 * to be reserved equal to number of ports. 2893 */ 2894 if (eh_conf->mode == EH_PKT_TRANSFER_MODE_EVENT) 2895 nb_crypto_qp = rte_eth_dev_count_avail(); 2896 else 2897 nb_crypto_qp = 0; 2898 2899 nb_crypto_qp = cryptodevs_init(nb_crypto_qp); 2900 2901 if (nb_bufs_in_pool == 0) { 2902 RTE_ETH_FOREACH_DEV(portid) { 2903 if ((enabled_port_mask & (1 << portid)) == 0) 2904 continue; 2905 nb_ports++; 2906 nb_rxq += get_port_nb_rx_queues(portid); 2907 } 2908 2909 nb_txq = nb_lcores; 2910 2911 nb_bufs_in_pool = calculate_nb_mbufs(nb_ports, nb_crypto_qp, 2912 nb_rxq, nb_txq); 2913 } 2914 2915 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2916 if (rte_lcore_is_enabled(lcore_id) == 0) 2917 continue; 2918 2919 if (numa_on) 2920 socket_id = (uint8_t)rte_lcore_to_socket_id(lcore_id); 2921 else 2922 socket_id = 0; 2923 2924 /* mbuf_pool is initialised by the pool_init() function*/ 2925 if (socket_ctx[socket_id].mbuf_pool) 2926 continue; 2927 2928 pool_init(&socket_ctx[socket_id], socket_id, nb_bufs_in_pool); 2929 session_pool_init(&socket_ctx[socket_id], socket_id, sess_sz); 2930 session_priv_pool_init(&socket_ctx[socket_id], socket_id, 2931 sess_sz); 2932 } 2933 printf("Number of mbufs in packet pool %d\n", nb_bufs_in_pool); 2934 2935 RTE_ETH_FOREACH_DEV(portid) { 2936 if ((enabled_port_mask & (1 << portid)) == 0) 2937 continue; 2938 2939 sa_check_offloads(portid, &req_rx_offloads[portid], 2940 &req_tx_offloads[portid]); 2941 port_init(portid, req_rx_offloads[portid], 2942 req_tx_offloads[portid]); 2943 } 2944 2945 /* 2946 * Set the enabled port mask in helper config for use by helper 2947 * sub-system. This will be used while initializing devices using 2948 * helper sub-system. 2949 */ 2950 eh_conf->eth_portmask = enabled_port_mask; 2951 2952 /* Initialize eventmode components */ 2953 ret = eh_devs_init(eh_conf); 2954 if (ret < 0) 2955 rte_exit(EXIT_FAILURE, "eh_devs_init failed, err=%d\n", ret); 2956 2957 /* start ports */ 2958 RTE_ETH_FOREACH_DEV(portid) { 2959 if ((enabled_port_mask & (1 << portid)) == 0) 2960 continue; 2961 2962 /* Create flow before starting the device */ 2963 create_default_ipsec_flow(portid, req_rx_offloads[portid]); 2964 2965 ret = rte_eth_dev_start(portid); 2966 if (ret < 0) 2967 rte_exit(EXIT_FAILURE, "rte_eth_dev_start: " 2968 "err=%d, port=%d\n", ret, portid); 2969 /* 2970 * If enabled, put device in promiscuous mode. 2971 * This allows IO forwarding mode to forward packets 2972 * to itself through 2 cross-connected ports of the 2973 * target machine. 2974 */ 2975 if (promiscuous_on) { 2976 ret = rte_eth_promiscuous_enable(portid); 2977 if (ret != 0) 2978 rte_exit(EXIT_FAILURE, 2979 "rte_eth_promiscuous_enable: err=%s, port=%d\n", 2980 rte_strerror(-ret), portid); 2981 } 2982 2983 rte_eth_dev_callback_register(portid, 2984 RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL); 2985 } 2986 2987 /* fragment reassemble is enabled */ 2988 if (frag_tbl_sz != 0) { 2989 ret = reassemble_init(); 2990 if (ret != 0) 2991 rte_exit(EXIT_FAILURE, "failed at reassemble init"); 2992 } 2993 2994 /* Replicate each context per socket */ 2995 for (i = 0; i < NB_SOCKETS && i < rte_socket_count(); i++) { 2996 socket_id = rte_socket_id_by_idx(i); 2997 if ((socket_ctx[socket_id].mbuf_pool != NULL) && 2998 (socket_ctx[socket_id].sa_in == NULL) && 2999 (socket_ctx[socket_id].sa_out == NULL)) { 3000 sa_init(&socket_ctx[socket_id], socket_id); 3001 sp4_init(&socket_ctx[socket_id], socket_id); 3002 sp6_init(&socket_ctx[socket_id], socket_id); 3003 rt_init(&socket_ctx[socket_id], socket_id); 3004 } 3005 } 3006 3007 flow_init(); 3008 3009 check_all_ports_link_status(enabled_port_mask); 3010 3011 #if (STATS_INTERVAL > 0) 3012 rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL); 3013 #else 3014 RTE_LOG(INFO, IPSEC, "Stats display disabled\n"); 3015 #endif /* STATS_INTERVAL */ 3016 3017 /* launch per-lcore init on every lcore */ 3018 rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN); 3019 RTE_LCORE_FOREACH_WORKER(lcore_id) { 3020 if (rte_eal_wait_lcore(lcore_id) < 0) 3021 return -1; 3022 } 3023 3024 /* Uninitialize eventmode components */ 3025 ret = eh_devs_uninit(eh_conf); 3026 if (ret < 0) 3027 rte_exit(EXIT_FAILURE, "eh_devs_uninit failed, err=%d\n", ret); 3028 3029 /* Free eventmode configuration memory */ 3030 eh_conf_uninit(eh_conf); 3031 3032 /* Destroy inline inbound and outbound sessions */ 3033 for (i = 0; i < NB_SOCKETS && i < rte_socket_count(); i++) { 3034 socket_id = rte_socket_id_by_idx(i); 3035 inline_sessions_free(socket_ctx[socket_id].sa_in); 3036 inline_sessions_free(socket_ctx[socket_id].sa_out); 3037 } 3038 3039 for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) { 3040 printf("Closing cryptodev %d...", cdev_id); 3041 rte_cryptodev_stop(cdev_id); 3042 rte_cryptodev_close(cdev_id); 3043 printf(" Done\n"); 3044 } 3045 3046 RTE_ETH_FOREACH_DEV(portid) { 3047 if ((enabled_port_mask & (1 << portid)) == 0) 3048 continue; 3049 3050 printf("Closing port %d...", portid); 3051 if (flow_info_tbl[portid].rx_def_flow) { 3052 struct rte_flow_error err; 3053 3054 ret = rte_flow_destroy(portid, 3055 flow_info_tbl[portid].rx_def_flow, &err); 3056 if (ret) 3057 RTE_LOG(ERR, IPSEC, "Failed to destroy flow " 3058 " for port %u, err msg: %s\n", portid, 3059 err.message); 3060 } 3061 ret = rte_eth_dev_stop(portid); 3062 if (ret != 0) 3063 RTE_LOG(ERR, IPSEC, 3064 "rte_eth_dev_stop: err=%s, port=%u\n", 3065 rte_strerror(-ret), portid); 3066 3067 rte_eth_dev_close(portid); 3068 printf(" Done\n"); 3069 } 3070 3071 /* clean up the EAL */ 3072 rte_eal_cleanup(); 3073 printf("Bye...\n"); 3074 3075 return 0; 3076 } 3077