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