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