1322ebca6SAkhil Goyal /* SPDX-License-Identifier: BSD-3-Clause 2322ebca6SAkhil Goyal * Copyright(C) 2023 Marvell. 3322ebca6SAkhil Goyal */ 4322ebca6SAkhil Goyal 5322ebca6SAkhil Goyal #include <stdio.h> 6322ebca6SAkhil Goyal #include <stdlib.h> 7322ebca6SAkhil Goyal #include <string.h> 8322ebca6SAkhil Goyal #include <stdint.h> 9322ebca6SAkhil Goyal #include <inttypes.h> 10322ebca6SAkhil Goyal #include <sys/types.h> 11322ebca6SAkhil Goyal #include <sys/queue.h> 12322ebca6SAkhil Goyal #include <setjmp.h> 13322ebca6SAkhil Goyal #include <stdarg.h> 14322ebca6SAkhil Goyal #include <ctype.h> 15322ebca6SAkhil Goyal #include <errno.h> 16322ebca6SAkhil Goyal #include <getopt.h> 17322ebca6SAkhil Goyal #include <signal.h> 18322ebca6SAkhil Goyal #include <stdbool.h> 19322ebca6SAkhil Goyal 20322ebca6SAkhil Goyal #include <rte_common.h> 21322ebca6SAkhil Goyal #include <rte_log.h> 22322ebca6SAkhil Goyal #include <rte_malloc.h> 23322ebca6SAkhil Goyal #include <rte_memory.h> 24322ebca6SAkhil Goyal #include <rte_memcpy.h> 25322ebca6SAkhil Goyal #include <rte_eal.h> 26322ebca6SAkhil Goyal #include <rte_launch.h> 27322ebca6SAkhil Goyal #include <rte_cycles.h> 28322ebca6SAkhil Goyal #include <rte_prefetch.h> 29322ebca6SAkhil Goyal #include <rte_lcore.h> 30322ebca6SAkhil Goyal #include <rte_per_lcore.h> 31322ebca6SAkhil Goyal #include <rte_branch_prediction.h> 32322ebca6SAkhil Goyal #include <rte_interrupts.h> 33322ebca6SAkhil Goyal #include <rte_random.h> 34322ebca6SAkhil Goyal #include <rte_debug.h> 35322ebca6SAkhil Goyal #include <rte_ether.h> 36322ebca6SAkhil Goyal #include <rte_ethdev.h> 37322ebca6SAkhil Goyal #include <rte_mempool.h> 38322ebca6SAkhil Goyal #include <rte_mbuf.h> 39322ebca6SAkhil Goyal #include <rte_security.h> 40322ebca6SAkhil Goyal #include <rte_string_fns.h> 41322ebca6SAkhil Goyal 42322ebca6SAkhil Goyal static volatile bool force_quit; 43322ebca6SAkhil Goyal 44322ebca6SAkhil Goyal /* MAC updating enabled by default */ 45322ebca6SAkhil Goyal static int mac_updating; 46322ebca6SAkhil Goyal 47322ebca6SAkhil Goyal /* Ports set in promiscuous mode on by default. */ 48322ebca6SAkhil Goyal static int promiscuous_on = 1; 49322ebca6SAkhil Goyal 50322ebca6SAkhil Goyal #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 51322ebca6SAkhil Goyal 52322ebca6SAkhil Goyal #define MAX_PKT_BURST 32 53322ebca6SAkhil Goyal #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 54322ebca6SAkhil Goyal #define MEMPOOL_CACHE_SIZE 256 55322ebca6SAkhil Goyal #define SESSION_POOL_CACHE_SIZE 0 56322ebca6SAkhil Goyal 57322ebca6SAkhil Goyal /* Configurable number of RX/TX ring descriptors */ 58322ebca6SAkhil Goyal #define RX_DESC_DEFAULT 1024 59322ebca6SAkhil Goyal #define TX_DESC_DEFAULT 1024 60322ebca6SAkhil Goyal static uint16_t nb_rxd = RX_DESC_DEFAULT; 61322ebca6SAkhil Goyal static uint16_t nb_txd = TX_DESC_DEFAULT; 62322ebca6SAkhil Goyal 63322ebca6SAkhil Goyal /* ethernet addresses of ports */ 64322ebca6SAkhil Goyal static struct rte_ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; 65322ebca6SAkhil Goyal 66322ebca6SAkhil Goyal /* Ethernet header configuration for MACsec flow on each port. */ 67322ebca6SAkhil Goyal static struct rte_ether_hdr port_ether_hdr_config[RTE_MAX_ETHPORTS]; 68322ebca6SAkhil Goyal 69322ebca6SAkhil Goyal /* mask of enabled ports */ 70322ebca6SAkhil Goyal static uint32_t l2fwd_enabled_port_mask; 71322ebca6SAkhil Goyal 72322ebca6SAkhil Goyal /* list of enabled ports */ 73322ebca6SAkhil Goyal static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; 74322ebca6SAkhil Goyal 757e06c0deSTyler Retzlaff struct __rte_cache_aligned port_pair_params { 76322ebca6SAkhil Goyal #define NUM_PORTS 2 77322ebca6SAkhil Goyal uint16_t port[NUM_PORTS]; 787e06c0deSTyler Retzlaff }; 79322ebca6SAkhil Goyal 80322ebca6SAkhil Goyal static struct port_pair_params port_pair_params_array[RTE_MAX_ETHPORTS / 2]; 81322ebca6SAkhil Goyal static struct port_pair_params *port_pair_params; 82322ebca6SAkhil Goyal static uint16_t nb_port_pair_params; 83322ebca6SAkhil Goyal 84322ebca6SAkhil Goyal static unsigned int l2fwd_rx_queue_per_lcore = 1; 85322ebca6SAkhil Goyal 86322ebca6SAkhil Goyal #define MAX_RX_QUEUE_PER_LCORE 16 87322ebca6SAkhil Goyal #define MAX_TX_QUEUE_PER_PORT 16 88322ebca6SAkhil Goyal /* List of queues to be polled for a given lcore. 8< */ 897e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_queue_conf { 90322ebca6SAkhil Goyal unsigned int n_rx_port; 91322ebca6SAkhil Goyal unsigned int rx_port_list[MAX_RX_QUEUE_PER_LCORE]; 927e06c0deSTyler Retzlaff }; 93322ebca6SAkhil Goyal struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; 94322ebca6SAkhil Goyal /* >8 End of list of queues to be polled for a given lcore. */ 95322ebca6SAkhil Goyal 96322ebca6SAkhil Goyal static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 97322ebca6SAkhil Goyal 98322ebca6SAkhil Goyal static struct rte_eth_conf port_conf = { 99322ebca6SAkhil Goyal .txmode = { 100322ebca6SAkhil Goyal .mq_mode = RTE_ETH_MQ_TX_NONE, 101322ebca6SAkhil Goyal }, 102322ebca6SAkhil Goyal }; 103322ebca6SAkhil Goyal 104322ebca6SAkhil Goyal /* Mempools for mbuf and security session */ 105322ebca6SAkhil Goyal struct rte_mempool *l2fwd_pktmbuf_pool; 106322ebca6SAkhil Goyal 107322ebca6SAkhil Goyal /* Per-port statistics struct */ 1087e06c0deSTyler Retzlaff struct __rte_cache_aligned l2fwd_port_statistics { 109322ebca6SAkhil Goyal uint64_t tx; 110322ebca6SAkhil Goyal uint64_t rx; 111322ebca6SAkhil Goyal uint64_t dropped; 1127e06c0deSTyler Retzlaff }; 113322ebca6SAkhil Goyal struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; 114322ebca6SAkhil Goyal 115322ebca6SAkhil Goyal #define MAX_TIMER_PERIOD 86400 /* 1 day max */ 116322ebca6SAkhil Goyal /* A tsc-based timer responsible for triggering statistics printout */ 117322ebca6SAkhil Goyal static uint64_t timer_period = 10; /* default period is 10 seconds */ 118322ebca6SAkhil Goyal 119322ebca6SAkhil Goyal #define MCS_MAX_KEY_LEN 32 120322ebca6SAkhil Goyal #define MCS_SALT_LEN 12 121322ebca6SAkhil Goyal 122322ebca6SAkhil Goyal struct l2fwd_key { 123322ebca6SAkhil Goyal uint8_t data[MCS_MAX_KEY_LEN]; 124322ebca6SAkhil Goyal uint32_t len; 125322ebca6SAkhil Goyal rte_iova_t phys_addr; 126322ebca6SAkhil Goyal }; 127322ebca6SAkhil Goyal 128322ebca6SAkhil Goyal /** l2fwd macsec application command line options */ 129322ebca6SAkhil Goyal struct l2fwd_macsec_options { 130322ebca6SAkhil Goyal unsigned int portmask; 131322ebca6SAkhil Goyal unsigned int tx_portmask; 132322ebca6SAkhil Goyal unsigned int rx_portmask; 133322ebca6SAkhil Goyal unsigned int nb_ports_per_lcore; 134322ebca6SAkhil Goyal unsigned int refresh_period; 135322ebca6SAkhil Goyal unsigned int single_lcore:1; 136322ebca6SAkhil Goyal }; 137322ebca6SAkhil Goyal 138322ebca6SAkhil Goyal /** l2fwd macsec lcore params */ 139322ebca6SAkhil Goyal struct l2fwd_macsec_port_params { 140322ebca6SAkhil Goyal uint8_t dev_id; 141322ebca6SAkhil Goyal uint8_t qp_id; 142322ebca6SAkhil Goyal void *sec_ctx; 143322ebca6SAkhil Goyal struct rte_mempool *sess_pool; 144322ebca6SAkhil Goyal 145322ebca6SAkhil Goyal void *sess; 146322ebca6SAkhil Goyal uint16_t sa_id[4]; 147322ebca6SAkhil Goyal uint16_t sc_id; 148322ebca6SAkhil Goyal struct rte_flow *tx_flow; 149322ebca6SAkhil Goyal struct rte_flow *rx_flow; 150322ebca6SAkhil Goyal 151322ebca6SAkhil Goyal enum rte_security_macsec_direction dir; 152322ebca6SAkhil Goyal enum rte_security_macsec_alg alg; 153322ebca6SAkhil Goyal struct l2fwd_key sa_key; 154322ebca6SAkhil Goyal uint8_t salt[MCS_SALT_LEN]; 155322ebca6SAkhil Goyal 156322ebca6SAkhil Goyal uint8_t eth_hdr[RTE_ETHER_HDR_LEN]; 157322ebca6SAkhil Goyal uint32_t ssci; 158322ebca6SAkhil Goyal uint64_t sci; 159322ebca6SAkhil Goyal uint64_t pn_threshold; 160322ebca6SAkhil Goyal uint32_t xpn; 161322ebca6SAkhil Goyal uint32_t next_pn; 162322ebca6SAkhil Goyal uint32_t mtu; 163322ebca6SAkhil Goyal uint8_t sectag_insert_mode; 164322ebca6SAkhil Goyal bool encrypt; 165322ebca6SAkhil Goyal bool protect_frames; 166322ebca6SAkhil Goyal bool replay_protect; 167322ebca6SAkhil Goyal int val_frames; 168322ebca6SAkhil Goyal uint32_t replay_win_sz; 169322ebca6SAkhil Goyal bool send_sci; 170322ebca6SAkhil Goyal bool end_station; 171322ebca6SAkhil Goyal bool scb; 172322ebca6SAkhil Goyal uint8_t an; 173322ebca6SAkhil Goyal }; 174322ebca6SAkhil Goyal struct l2fwd_macsec_port_params mcs_port_params[RTE_MAX_ETHPORTS]; 175322ebca6SAkhil Goyal 176322ebca6SAkhil Goyal static void 177322ebca6SAkhil Goyal mcs_stats_dump(uint16_t portid) 178322ebca6SAkhil Goyal { 179322ebca6SAkhil Goyal struct rte_security_stats sess_stats = {0}; 180322ebca6SAkhil Goyal struct rte_security_macsec_secy_stats *secy_stat; 181322ebca6SAkhil Goyal struct rte_security_macsec_sc_stats sc_stat = {0}; 182322ebca6SAkhil Goyal 183322ebca6SAkhil Goyal if (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_RX) { 184322ebca6SAkhil Goyal printf("\n********* RX SECY STATS ************\n"); 185322ebca6SAkhil Goyal rte_security_session_stats_get(mcs_port_params[portid].sec_ctx, 186322ebca6SAkhil Goyal mcs_port_params[portid].sess, &sess_stats); 187322ebca6SAkhil Goyal secy_stat = &sess_stats.macsec; 188322ebca6SAkhil Goyal 189322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_bcast_cnt) 190322ebca6SAkhil Goyal printf("RX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n", 191322ebca6SAkhil Goyal secy_stat->ctl_pkt_bcast_cnt); 192322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_mcast_cnt) 193322ebca6SAkhil Goyal printf("RX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n", 194322ebca6SAkhil Goyal secy_stat->ctl_pkt_mcast_cnt); 195322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_ucast_cnt) 196322ebca6SAkhil Goyal printf("RX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n", 197322ebca6SAkhil Goyal secy_stat->ctl_pkt_ucast_cnt); 198322ebca6SAkhil Goyal if (secy_stat->ctl_octet_cnt) 199322ebca6SAkhil Goyal printf("RX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt); 200322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_bcast_cnt) 201322ebca6SAkhil Goyal printf("RX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n", 202322ebca6SAkhil Goyal secy_stat->unctl_pkt_bcast_cnt); 203322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_mcast_cnt) 204322ebca6SAkhil Goyal printf("RX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n", 205322ebca6SAkhil Goyal secy_stat->unctl_pkt_mcast_cnt); 206322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_ucast_cnt) 207322ebca6SAkhil Goyal printf("RX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n", 208322ebca6SAkhil Goyal secy_stat->unctl_pkt_ucast_cnt); 209322ebca6SAkhil Goyal if (secy_stat->unctl_octet_cnt) 210322ebca6SAkhil Goyal printf("RX: unctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->unctl_octet_cnt); 211322ebca6SAkhil Goyal /* Valid only for RX */ 212322ebca6SAkhil Goyal if (secy_stat->octet_decrypted_cnt) 213322ebca6SAkhil Goyal printf("RX: octet_decrypted_cnt: 0x%" PRIx64 "\n", 214322ebca6SAkhil Goyal secy_stat->octet_decrypted_cnt); 215322ebca6SAkhil Goyal if (secy_stat->octet_validated_cnt) 216322ebca6SAkhil Goyal printf("RX: octet_validated_cnt: 0x%" PRIx64 "\n", 217322ebca6SAkhil Goyal secy_stat->octet_validated_cnt); 218322ebca6SAkhil Goyal if (secy_stat->pkt_port_disabled_cnt) 219322ebca6SAkhil Goyal printf("RX: pkt_port_disabled_cnt: 0x%" PRIx64 "\n", 220322ebca6SAkhil Goyal secy_stat->pkt_port_disabled_cnt); 221322ebca6SAkhil Goyal if (secy_stat->pkt_badtag_cnt) 222322ebca6SAkhil Goyal printf("RX: pkt_badtag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_badtag_cnt); 223322ebca6SAkhil Goyal if (secy_stat->pkt_nosa_cnt) 224322ebca6SAkhil Goyal printf("RX: pkt_nosa_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_nosa_cnt); 225322ebca6SAkhil Goyal if (secy_stat->pkt_nosaerror_cnt) 226322ebca6SAkhil Goyal printf("RX: pkt_nosaerror_cnt: 0x%" PRIx64 "\n", 227322ebca6SAkhil Goyal secy_stat->pkt_nosaerror_cnt); 228322ebca6SAkhil Goyal if (secy_stat->pkt_tagged_ctl_cnt) 229322ebca6SAkhil Goyal printf("RX: pkt_tagged_ctl_cnt: 0x%" PRIx64 "\n", 230322ebca6SAkhil Goyal secy_stat->pkt_tagged_ctl_cnt); 231322ebca6SAkhil Goyal if (secy_stat->pkt_untaged_cnt) 232322ebca6SAkhil Goyal printf("RX: pkt_untaged_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_untaged_cnt); 233322ebca6SAkhil Goyal if (secy_stat->pkt_ctl_cnt) 234322ebca6SAkhil Goyal printf("RX: pkt_ctl_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_ctl_cnt); 235322ebca6SAkhil Goyal if (secy_stat->pkt_notag_cnt) 236322ebca6SAkhil Goyal printf("RX: pkt_notag_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_notag_cnt); 237322ebca6SAkhil Goyal printf("\n"); 238322ebca6SAkhil Goyal printf("\n********** RX SC[%u] STATS **************\n", 239322ebca6SAkhil Goyal mcs_port_params[portid].sc_id); 240322ebca6SAkhil Goyal 241322ebca6SAkhil Goyal rte_security_macsec_sc_stats_get(mcs_port_params[portid].sec_ctx, 242322ebca6SAkhil Goyal mcs_port_params[portid].sc_id, RTE_SECURITY_MACSEC_DIR_RX, 243322ebca6SAkhil Goyal &sc_stat); 244322ebca6SAkhil Goyal /* RX */ 245322ebca6SAkhil Goyal if (sc_stat.hit_cnt) 246322ebca6SAkhil Goyal printf("RX hit_cnt: 0x%" PRIx64 "\n", sc_stat.hit_cnt); 247322ebca6SAkhil Goyal if (sc_stat.pkt_invalid_cnt) 248322ebca6SAkhil Goyal printf("RX pkt_invalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_invalid_cnt); 249322ebca6SAkhil Goyal if (sc_stat.pkt_late_cnt) 250322ebca6SAkhil Goyal printf("RX pkt_late_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_late_cnt); 251322ebca6SAkhil Goyal if (sc_stat.pkt_notvalid_cnt) 252322ebca6SAkhil Goyal printf("RX pkt_notvalid_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_notvalid_cnt); 253322ebca6SAkhil Goyal if (sc_stat.pkt_unchecked_cnt) 254322ebca6SAkhil Goyal printf("RX pkt_unchecked_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_unchecked_cnt); 255322ebca6SAkhil Goyal if (sc_stat.pkt_delay_cnt) 256322ebca6SAkhil Goyal printf("RX pkt_delay_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_delay_cnt); 257322ebca6SAkhil Goyal if (sc_stat.pkt_ok_cnt) 258322ebca6SAkhil Goyal printf("RX pkt_ok_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_ok_cnt); 259322ebca6SAkhil Goyal if (sc_stat.octet_decrypt_cnt) 260322ebca6SAkhil Goyal printf("RX octet_decrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_decrypt_cnt); 261322ebca6SAkhil Goyal if (sc_stat.octet_validate_cnt) 262322ebca6SAkhil Goyal printf("RX octet_validate_cnt: 0x%" PRIx64 "\n", 263322ebca6SAkhil Goyal sc_stat.octet_validate_cnt); 264322ebca6SAkhil Goyal } 265322ebca6SAkhil Goyal 266322ebca6SAkhil Goyal if (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_TX) { 267322ebca6SAkhil Goyal memset(&sess_stats, 0, sizeof(struct rte_security_stats)); 268322ebca6SAkhil Goyal rte_security_session_stats_get(mcs_port_params[portid].sec_ctx, 269322ebca6SAkhil Goyal mcs_port_params[portid].sess, &sess_stats); 270322ebca6SAkhil Goyal secy_stat = &sess_stats.macsec; 271322ebca6SAkhil Goyal 272322ebca6SAkhil Goyal printf("\n********* TX SECY STATS ************\n"); 273322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_bcast_cnt) 274322ebca6SAkhil Goyal printf("TX: ctl_pkt_bcast_cnt: 0x%" PRIx64 "\n", 275322ebca6SAkhil Goyal secy_stat->ctl_pkt_bcast_cnt); 276322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_mcast_cnt) 277322ebca6SAkhil Goyal printf("TX: ctl_pkt_mcast_cnt: 0x%" PRIx64 "\n", 278322ebca6SAkhil Goyal secy_stat->ctl_pkt_mcast_cnt); 279322ebca6SAkhil Goyal if (secy_stat->ctl_pkt_ucast_cnt) 280322ebca6SAkhil Goyal printf("TX: ctl_pkt_ucast_cnt: 0x%" PRIx64 "\n", 281322ebca6SAkhil Goyal secy_stat->ctl_pkt_ucast_cnt); 282322ebca6SAkhil Goyal if (secy_stat->ctl_octet_cnt) 283322ebca6SAkhil Goyal printf("TX: ctl_octet_cnt: 0x%" PRIx64 "\n", secy_stat->ctl_octet_cnt); 284322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_bcast_cnt) 285322ebca6SAkhil Goyal printf("TX: unctl_pkt_bcast_cnt: 0x%" PRIx64 "\n", 286322ebca6SAkhil Goyal secy_stat->unctl_pkt_bcast_cnt); 287322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_mcast_cnt) 288322ebca6SAkhil Goyal printf("TX: unctl_pkt_mcast_cnt: 0x%" PRIx64 "\n", 289322ebca6SAkhil Goyal secy_stat->unctl_pkt_mcast_cnt); 290322ebca6SAkhil Goyal if (secy_stat->unctl_pkt_ucast_cnt) 291322ebca6SAkhil Goyal printf("TX: unctl_pkt_ucast_cnt: 0x%" PRIx64 "\n", 292322ebca6SAkhil Goyal secy_stat->unctl_pkt_ucast_cnt); 293322ebca6SAkhil Goyal if (secy_stat->unctl_octet_cnt) 294322ebca6SAkhil Goyal printf("TX: unctl_octet_cnt: 0x%" PRIx64 "\n", 295322ebca6SAkhil Goyal secy_stat->unctl_octet_cnt); 296322ebca6SAkhil Goyal /* Valid only for TX */ 297322ebca6SAkhil Goyal if (secy_stat->octet_encrypted_cnt) 298322ebca6SAkhil Goyal printf("TX: octet_encrypted_cnt: 0x%" PRIx64 "\n", 299322ebca6SAkhil Goyal secy_stat->octet_encrypted_cnt); 300322ebca6SAkhil Goyal if (secy_stat->octet_protected_cnt) 301322ebca6SAkhil Goyal printf("TX: octet_protected_cnt: 0x%" PRIx64 "\n", 302322ebca6SAkhil Goyal secy_stat->octet_protected_cnt); 303322ebca6SAkhil Goyal if (secy_stat->pkt_noactivesa_cnt) 304322ebca6SAkhil Goyal printf("TX: pkt_noactivesa_cnt: 0x%" PRIx64 "\n", 305322ebca6SAkhil Goyal secy_stat->pkt_noactivesa_cnt); 306322ebca6SAkhil Goyal if (secy_stat->pkt_toolong_cnt) 307322ebca6SAkhil Goyal printf("TX: pkt_toolong_cnt: 0x%" PRIx64 "\n", secy_stat->pkt_toolong_cnt); 308322ebca6SAkhil Goyal if (secy_stat->pkt_untagged_cnt) 309322ebca6SAkhil Goyal printf("TX: pkt_untagged_cnt: 0x%" PRIx64 "\n", 310322ebca6SAkhil Goyal secy_stat->pkt_untagged_cnt); 311322ebca6SAkhil Goyal 312322ebca6SAkhil Goyal 313322ebca6SAkhil Goyal memset(&sc_stat, 0, sizeof(struct rte_security_macsec_sc_stats)); 314322ebca6SAkhil Goyal rte_security_macsec_sc_stats_get(mcs_port_params[portid].sec_ctx, 315322ebca6SAkhil Goyal mcs_port_params[portid].sc_id, RTE_SECURITY_MACSEC_DIR_TX, 316322ebca6SAkhil Goyal &sc_stat); 317322ebca6SAkhil Goyal printf("\n********** TX SC[%u] STATS **************\n", 318322ebca6SAkhil Goyal mcs_port_params[portid].sc_id); 319322ebca6SAkhil Goyal if (sc_stat.pkt_encrypt_cnt) 320322ebca6SAkhil Goyal printf("TX pkt_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_encrypt_cnt); 321322ebca6SAkhil Goyal if (sc_stat.pkt_protected_cnt) 322322ebca6SAkhil Goyal printf("TX pkt_protected_cnt: 0x%" PRIx64 "\n", sc_stat.pkt_protected_cnt); 323322ebca6SAkhil Goyal if (sc_stat.octet_encrypt_cnt) 324322ebca6SAkhil Goyal printf("TX octet_encrypt_cnt: 0x%" PRIx64 "\n", sc_stat.octet_encrypt_cnt); 325322ebca6SAkhil Goyal } 326322ebca6SAkhil Goyal } 327322ebca6SAkhil Goyal 328322ebca6SAkhil Goyal /* Print out statistics on packets dropped */ 329322ebca6SAkhil Goyal static void 330322ebca6SAkhil Goyal print_stats(void) 331322ebca6SAkhil Goyal { 332322ebca6SAkhil Goyal uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; 333322ebca6SAkhil Goyal unsigned int portid; 334322ebca6SAkhil Goyal 335322ebca6SAkhil Goyal total_packets_dropped = 0; 336322ebca6SAkhil Goyal total_packets_tx = 0; 337322ebca6SAkhil Goyal total_packets_rx = 0; 338322ebca6SAkhil Goyal 339322ebca6SAkhil Goyal const char clr[] = { 27, '[', '2', 'J', '\0' }; 340322ebca6SAkhil Goyal const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 341322ebca6SAkhil Goyal 342322ebca6SAkhil Goyal /* Clear screen and move to top left */ 343322ebca6SAkhil Goyal printf("%s%s", clr, topLeft); 344322ebca6SAkhil Goyal 345322ebca6SAkhil Goyal printf("\nPort statistics ===================================="); 346322ebca6SAkhil Goyal 347322ebca6SAkhil Goyal for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 348322ebca6SAkhil Goyal /* skip disabled ports */ 349322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 350322ebca6SAkhil Goyal continue; 351322ebca6SAkhil Goyal printf("\nStatistics for port %u ------------------------------" 352322ebca6SAkhil Goyal "\nPackets sent: %24"PRIu64 353322ebca6SAkhil Goyal "\nPackets received: %20"PRIu64 354322ebca6SAkhil Goyal "\nPackets dropped: %21"PRIu64, 355322ebca6SAkhil Goyal portid, 356322ebca6SAkhil Goyal port_statistics[portid].tx, 357322ebca6SAkhil Goyal port_statistics[portid].rx, 358322ebca6SAkhil Goyal port_statistics[portid].dropped); 359322ebca6SAkhil Goyal 360322ebca6SAkhil Goyal total_packets_dropped += port_statistics[portid].dropped; 361322ebca6SAkhil Goyal total_packets_tx += port_statistics[portid].tx; 362322ebca6SAkhil Goyal total_packets_rx += port_statistics[portid].rx; 363322ebca6SAkhil Goyal 364322ebca6SAkhil Goyal mcs_stats_dump(portid); 365322ebca6SAkhil Goyal } 366322ebca6SAkhil Goyal printf("\nAggregate statistics ===============================" 367322ebca6SAkhil Goyal "\nTotal packets sent: %18"PRIu64 368322ebca6SAkhil Goyal "\nTotal packets received: %14"PRIu64 369322ebca6SAkhil Goyal "\nTotal packets dropped: %15"PRIu64, 370322ebca6SAkhil Goyal total_packets_tx, 371322ebca6SAkhil Goyal total_packets_rx, 372322ebca6SAkhil Goyal total_packets_dropped); 373322ebca6SAkhil Goyal printf("\n====================================================\n"); 374322ebca6SAkhil Goyal 375322ebca6SAkhil Goyal fflush(stdout); 376322ebca6SAkhil Goyal } 377322ebca6SAkhil Goyal 378322ebca6SAkhil Goyal static void 379322ebca6SAkhil Goyal l2fwd_mac_updating(struct rte_mbuf *m, unsigned int dest_portid) 380322ebca6SAkhil Goyal { 381322ebca6SAkhil Goyal struct rte_ether_hdr *eth; 382322ebca6SAkhil Goyal void *tmp; 383322ebca6SAkhil Goyal 384322ebca6SAkhil Goyal eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 385322ebca6SAkhil Goyal 386322ebca6SAkhil Goyal /* 02:00:00:00:00:xx */ 387322ebca6SAkhil Goyal tmp = ð->dst_addr.addr_bytes[0]; 388322ebca6SAkhil Goyal *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dest_portid << 40); 389322ebca6SAkhil Goyal 390322ebca6SAkhil Goyal /* src addr */ 391322ebca6SAkhil Goyal rte_ether_addr_copy(&l2fwd_ports_eth_addr[dest_portid], ð->src_addr); 392322ebca6SAkhil Goyal } 393322ebca6SAkhil Goyal 394322ebca6SAkhil Goyal static void 395322ebca6SAkhil Goyal l2fwd_simple_forward(struct rte_mbuf *m, unsigned int portid) 396322ebca6SAkhil Goyal { 397322ebca6SAkhil Goyal unsigned int dst_port; 398322ebca6SAkhil Goyal int sent; 399322ebca6SAkhil Goyal struct rte_eth_dev_tx_buffer *buffer; 400322ebca6SAkhil Goyal 401322ebca6SAkhil Goyal dst_port = l2fwd_dst_ports[portid]; 402322ebca6SAkhil Goyal 403322ebca6SAkhil Goyal if (mac_updating) 404322ebca6SAkhil Goyal l2fwd_mac_updating(m, dst_port); 405322ebca6SAkhil Goyal 406322ebca6SAkhil Goyal buffer = tx_buffer[dst_port]; 407322ebca6SAkhil Goyal sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); 408322ebca6SAkhil Goyal if (sent) 409322ebca6SAkhil Goyal port_statistics[dst_port].tx += sent; 410322ebca6SAkhil Goyal } 411322ebca6SAkhil Goyal 412322ebca6SAkhil Goyal static void 413322ebca6SAkhil Goyal fill_macsec_sa_conf(uint16_t portid, struct rte_security_macsec_sa *sa) 414322ebca6SAkhil Goyal { 415322ebca6SAkhil Goyal sa->dir = mcs_port_params[portid].dir; 416322ebca6SAkhil Goyal 417322ebca6SAkhil Goyal sa->key.data = mcs_port_params[portid].sa_key.data; 418322ebca6SAkhil Goyal sa->key.length = mcs_port_params[portid].sa_key.len; 419322ebca6SAkhil Goyal 420322ebca6SAkhil Goyal memcpy((uint8_t *)sa->salt, (const uint8_t *)mcs_port_params[portid].salt, 421322ebca6SAkhil Goyal RTE_SECURITY_MACSEC_SALT_LEN); 422322ebca6SAkhil Goyal 423322ebca6SAkhil Goyal /* AN is set as per the value in secure packet in test vector */ 424322ebca6SAkhil Goyal sa->an = mcs_port_params[portid].an & RTE_MACSEC_AN_MASK; 425322ebca6SAkhil Goyal 426322ebca6SAkhil Goyal sa->ssci = mcs_port_params[portid].ssci; 427322ebca6SAkhil Goyal sa->xpn = mcs_port_params[portid].xpn; 428322ebca6SAkhil Goyal /* Starting packet number which is expected to come next. 429322ebca6SAkhil Goyal * It is take from the test vector so that we can match the out packet. 430322ebca6SAkhil Goyal */ 431322ebca6SAkhil Goyal sa->next_pn = mcs_port_params[portid].next_pn; 432322ebca6SAkhil Goyal } 433322ebca6SAkhil Goyal 434322ebca6SAkhil Goyal static void 435322ebca6SAkhil Goyal fill_macsec_sc_conf(uint16_t portid, struct rte_security_macsec_sc *sc_conf) 436322ebca6SAkhil Goyal { 437322ebca6SAkhil Goyal uint8_t i; 438322ebca6SAkhil Goyal 439322ebca6SAkhil Goyal sc_conf->dir = mcs_port_params[portid].dir; 440322ebca6SAkhil Goyal sc_conf->pn_threshold = mcs_port_params[portid].pn_threshold; 441322ebca6SAkhil Goyal if (sc_conf->dir == RTE_SECURITY_MACSEC_DIR_TX) { 442322ebca6SAkhil Goyal sc_conf->sc_tx.sa_id = mcs_port_params[portid].sa_id[0]; 443322ebca6SAkhil Goyal if (mcs_port_params[portid].sa_id[1] != 0xFFFF) { 444322ebca6SAkhil Goyal sc_conf->sc_tx.sa_id_rekey = mcs_port_params[portid].sa_id[1]; 445322ebca6SAkhil Goyal sc_conf->sc_tx.re_key_en = 1; 446322ebca6SAkhil Goyal } 447322ebca6SAkhil Goyal sc_conf->sc_tx.active = 1; 448322ebca6SAkhil Goyal sc_conf->sc_tx.sci = mcs_port_params[portid].sci; 4490d187ba8SAkhil Goyal if (mcs_port_params[portid].alg == RTE_SECURITY_MACSEC_ALG_GCM_XPN_128 || 4500d187ba8SAkhil Goyal mcs_port_params[portid].alg == RTE_SECURITY_MACSEC_ALG_GCM_XPN_256) 451322ebca6SAkhil Goyal sc_conf->sc_tx.is_xpn = 1; 452322ebca6SAkhil Goyal } else { 453322ebca6SAkhil Goyal for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) { 454322ebca6SAkhil Goyal if (mcs_port_params[portid].sa_id[i] != 0xFFFF) { 455322ebca6SAkhil Goyal sc_conf->sc_rx.sa_id[i] = mcs_port_params[portid].sa_id[i]; 456322ebca6SAkhil Goyal sc_conf->sc_rx.sa_in_use[i] = 1; 457322ebca6SAkhil Goyal } 458322ebca6SAkhil Goyal } 459322ebca6SAkhil Goyal sc_conf->sc_rx.active = 1; 4600d187ba8SAkhil Goyal if (mcs_port_params[portid].alg == RTE_SECURITY_MACSEC_ALG_GCM_XPN_128 || 4610d187ba8SAkhil Goyal mcs_port_params[portid].alg == RTE_SECURITY_MACSEC_ALG_GCM_XPN_256) 462322ebca6SAkhil Goyal sc_conf->sc_rx.is_xpn = 1; 463322ebca6SAkhil Goyal } 464322ebca6SAkhil Goyal } 465322ebca6SAkhil Goyal 466322ebca6SAkhil Goyal /* Create Inline MACsec session */ 467322ebca6SAkhil Goyal static int 468322ebca6SAkhil Goyal fill_session_conf(uint16_t portid, struct rte_security_session_conf *sess_conf) 469322ebca6SAkhil Goyal { 470322ebca6SAkhil Goyal sess_conf->action_type = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL; 471322ebca6SAkhil Goyal sess_conf->protocol = RTE_SECURITY_PROTOCOL_MACSEC; 472322ebca6SAkhil Goyal sess_conf->macsec.dir = mcs_port_params[portid].dir; 473322ebca6SAkhil Goyal sess_conf->macsec.alg = mcs_port_params[portid].alg; 474322ebca6SAkhil Goyal sess_conf->macsec.cipher_off = 0; 475322ebca6SAkhil Goyal sess_conf->macsec.sci = mcs_port_params[portid].sci; 476322ebca6SAkhil Goyal sess_conf->macsec.sc_id = mcs_port_params[portid].sc_id; 477322ebca6SAkhil Goyal if (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_TX) { 478322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.mtu = mcs_port_params[portid].mtu; 479322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.sectag_off = 480322ebca6SAkhil Goyal (mcs_port_params[portid].sectag_insert_mode == 1) ? 481322ebca6SAkhil Goyal 2 * RTE_ETHER_ADDR_LEN : RTE_VLAN_HLEN; 482322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.sectag_insert_mode = 483322ebca6SAkhil Goyal mcs_port_params[portid].sectag_insert_mode; 484322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.ctrl_port_enable = 1; 485322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.sectag_version = 0; 486322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.end_station = mcs_port_params[portid].end_station; 487322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.send_sci = mcs_port_params[portid].send_sci; 488322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.scb = mcs_port_params[portid].scb; 489322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.encrypt = mcs_port_params[portid].encrypt; 490322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.protect_frames = mcs_port_params[portid].protect_frames; 491322ebca6SAkhil Goyal sess_conf->macsec.tx_secy.icv_include_da_sa = 1; 492322ebca6SAkhil Goyal } else { 493322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.replay_win_sz = mcs_port_params[portid].replay_win_sz; 494322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.replay_protect = mcs_port_params[portid].replay_protect; 495322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.icv_include_da_sa = 1; 496322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.ctrl_port_enable = 1; 497322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.preserve_sectag = 0; 498322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.preserve_icv = 0; 499322ebca6SAkhil Goyal sess_conf->macsec.rx_secy.validate_frames = mcs_port_params[portid].val_frames; 500322ebca6SAkhil Goyal } 501322ebca6SAkhil Goyal 502322ebca6SAkhil Goyal return 0; 503322ebca6SAkhil Goyal } 504322ebca6SAkhil Goyal 505322ebca6SAkhil Goyal static int 506322ebca6SAkhil Goyal create_default_flow(uint16_t portid) 507322ebca6SAkhil Goyal { 508322ebca6SAkhil Goyal struct rte_flow_action action[2]; 509322ebca6SAkhil Goyal struct rte_flow_item pattern[2]; 510322ebca6SAkhil Goyal struct rte_flow_attr attr = {0}; 511322ebca6SAkhil Goyal struct rte_flow_error err; 512322ebca6SAkhil Goyal struct rte_flow *flow; 513322ebca6SAkhil Goyal struct rte_flow_item_eth eth; 514322ebca6SAkhil Goyal static const struct rte_flow_item_eth eth_mask = { 515*e0d947a1SFerruh Yigit .hdr.dst_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 516*e0d947a1SFerruh Yigit .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 517322ebca6SAkhil Goyal .hdr.ether_type = RTE_BE16(0xFFFF), 518322ebca6SAkhil Goyal }; 519322ebca6SAkhil Goyal int ret; 520322ebca6SAkhil Goyal 521322ebca6SAkhil Goyal eth.has_vlan = 0; 522322ebca6SAkhil Goyal memcpy(ð.hdr, mcs_port_params[portid].eth_hdr, RTE_ETHER_HDR_LEN); 523322ebca6SAkhil Goyal 524322ebca6SAkhil Goyal printf("Creating flow on port %u with DST MAC address: " RTE_ETHER_ADDR_PRT_FMT 525322ebca6SAkhil Goyal ", SRC MAC address: "RTE_ETHER_ADDR_PRT_FMT"\n\n", 526322ebca6SAkhil Goyal portid, 527322ebca6SAkhil Goyal RTE_ETHER_ADDR_BYTES(ð.hdr.dst_addr), 528322ebca6SAkhil Goyal RTE_ETHER_ADDR_BYTES(ð.hdr.src_addr)); 529322ebca6SAkhil Goyal 530322ebca6SAkhil Goyal pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 531322ebca6SAkhil Goyal pattern[0].spec = ð 532322ebca6SAkhil Goyal pattern[0].mask = ð_mask; 533322ebca6SAkhil Goyal pattern[0].last = NULL; 534322ebca6SAkhil Goyal pattern[1].type = RTE_FLOW_ITEM_TYPE_END; 535322ebca6SAkhil Goyal 536322ebca6SAkhil Goyal action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY; 537322ebca6SAkhil Goyal action[0].conf = mcs_port_params[portid].sess; 538322ebca6SAkhil Goyal action[1].type = RTE_FLOW_ACTION_TYPE_END; 539322ebca6SAkhil Goyal action[1].conf = NULL; 540322ebca6SAkhil Goyal 541322ebca6SAkhil Goyal attr.ingress = (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_RX) ? 1 : 0; 542322ebca6SAkhil Goyal attr.egress = (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_TX) ? 1 : 0; 543322ebca6SAkhil Goyal 544322ebca6SAkhil Goyal ret = rte_flow_validate(portid, &attr, pattern, action, &err); 545322ebca6SAkhil Goyal if (ret) { 546322ebca6SAkhil Goyal printf("\nValidate flow failed, ret = %d\n", ret); 547322ebca6SAkhil Goyal return -1; 548322ebca6SAkhil Goyal } 549322ebca6SAkhil Goyal flow = rte_flow_create(portid, &attr, pattern, action, &err); 550322ebca6SAkhil Goyal if (flow == NULL) { 551322ebca6SAkhil Goyal printf("\nDefault flow rule create failed\n"); 552322ebca6SAkhil Goyal return -1; 553322ebca6SAkhil Goyal } 554322ebca6SAkhil Goyal 555322ebca6SAkhil Goyal if (mcs_port_params[portid].dir == RTE_SECURITY_MACSEC_DIR_TX) 556322ebca6SAkhil Goyal mcs_port_params[portid].tx_flow = flow; 557322ebca6SAkhil Goyal else 558322ebca6SAkhil Goyal mcs_port_params[portid].rx_flow = flow; 559322ebca6SAkhil Goyal 560322ebca6SAkhil Goyal return 0; 561322ebca6SAkhil Goyal } 562322ebca6SAkhil Goyal 563322ebca6SAkhil Goyal static void 564322ebca6SAkhil Goyal destroy_default_flow(uint16_t portid) 565322ebca6SAkhil Goyal { 566322ebca6SAkhil Goyal struct rte_flow_error err; 567322ebca6SAkhil Goyal int ret; 568322ebca6SAkhil Goyal 569322ebca6SAkhil Goyal if (mcs_port_params[portid].tx_flow) { 570322ebca6SAkhil Goyal ret = rte_flow_destroy(portid, mcs_port_params[portid].tx_flow, &err); 571322ebca6SAkhil Goyal if (ret) { 572322ebca6SAkhil Goyal printf("\nDefault Tx flow rule destroy failed\n"); 573322ebca6SAkhil Goyal return; 574322ebca6SAkhil Goyal } 575322ebca6SAkhil Goyal mcs_port_params[portid].tx_flow = NULL; 576322ebca6SAkhil Goyal } 577322ebca6SAkhil Goyal if (mcs_port_params[portid].rx_flow) { 578322ebca6SAkhil Goyal ret = rte_flow_destroy(portid, mcs_port_params[portid].rx_flow, &err); 579322ebca6SAkhil Goyal if (ret) { 580322ebca6SAkhil Goyal printf("\nDefault Rx flow rule destroy failed\n"); 581322ebca6SAkhil Goyal return; 582322ebca6SAkhil Goyal } 583322ebca6SAkhil Goyal mcs_port_params[portid].rx_flow = NULL; 584322ebca6SAkhil Goyal } 585322ebca6SAkhil Goyal } 586322ebca6SAkhil Goyal 587322ebca6SAkhil Goyal static void 588322ebca6SAkhil Goyal clean_macsec_resources(uint16_t portid) 589322ebca6SAkhil Goyal { 590322ebca6SAkhil Goyal uint8_t an; 591322ebca6SAkhil Goyal 592322ebca6SAkhil Goyal destroy_default_flow(portid); 593322ebca6SAkhil Goyal rte_security_session_destroy(mcs_port_params[portid].sec_ctx, 594322ebca6SAkhil Goyal mcs_port_params[portid].sess); 595322ebca6SAkhil Goyal rte_security_macsec_sc_destroy(mcs_port_params[portid].sec_ctx, 596322ebca6SAkhil Goyal mcs_port_params[portid].sc_id, 597322ebca6SAkhil Goyal mcs_port_params[portid].dir); 598322ebca6SAkhil Goyal for (an = 0; an < RTE_SECURITY_MACSEC_NUM_AN; an++) { 599322ebca6SAkhil Goyal if (mcs_port_params[portid].sa_id[an] != 0xFFFF) 600322ebca6SAkhil Goyal rte_security_macsec_sa_destroy(mcs_port_params[portid].sec_ctx, 601322ebca6SAkhil Goyal mcs_port_params[portid].sa_id[an], 602322ebca6SAkhil Goyal mcs_port_params[portid].dir); 603322ebca6SAkhil Goyal } 604322ebca6SAkhil Goyal } 605322ebca6SAkhil Goyal 606322ebca6SAkhil Goyal static int 607322ebca6SAkhil Goyal initialize_macsec_session(uint8_t portid) 608322ebca6SAkhil Goyal { 609322ebca6SAkhil Goyal struct rte_security_session_conf sess_conf = {0}; 610322ebca6SAkhil Goyal struct rte_security_macsec_sa sa_conf = {0}; 611322ebca6SAkhil Goyal struct rte_security_macsec_sc sc_conf = {0}; 612322ebca6SAkhil Goyal int id, ret; 613322ebca6SAkhil Goyal 614322ebca6SAkhil Goyal /* Create MACsec SA. */ 615322ebca6SAkhil Goyal fill_macsec_sa_conf(portid, &sa_conf); 616322ebca6SAkhil Goyal id = rte_security_macsec_sa_create(mcs_port_params[portid].sec_ctx, &sa_conf); 617322ebca6SAkhil Goyal if (id < 0) { 618322ebca6SAkhil Goyal printf("MACsec SA create failed : %d.\n", id); 619322ebca6SAkhil Goyal return -1; 620322ebca6SAkhil Goyal } 621322ebca6SAkhil Goyal mcs_port_params[portid].sa_id[0] = (uint16_t)id; 622322ebca6SAkhil Goyal mcs_port_params[portid].sa_id[1] = 0xFFFF; 623322ebca6SAkhil Goyal mcs_port_params[portid].sa_id[2] = 0xFFFF; 624322ebca6SAkhil Goyal mcs_port_params[portid].sa_id[3] = 0xFFFF; 625322ebca6SAkhil Goyal 626322ebca6SAkhil Goyal printf("\nsa_id %d created.\n", mcs_port_params[portid].sa_id[0]); 627322ebca6SAkhil Goyal 628322ebca6SAkhil Goyal /* Create MACsec SC. */ 629322ebca6SAkhil Goyal fill_macsec_sc_conf(portid, &sc_conf); 630322ebca6SAkhil Goyal id = rte_security_macsec_sc_create(mcs_port_params[portid].sec_ctx, &sc_conf); 631322ebca6SAkhil Goyal if (id < 0) { 632322ebca6SAkhil Goyal printf("MACsec SC create failed : %d.\n", id); 633322ebca6SAkhil Goyal goto out; 634322ebca6SAkhil Goyal } 635322ebca6SAkhil Goyal mcs_port_params[portid].sc_id = (uint16_t)id; 636322ebca6SAkhil Goyal printf("\nsc_id %d created.\n", mcs_port_params[portid].sc_id); 637322ebca6SAkhil Goyal 638322ebca6SAkhil Goyal /* Create Inline MACsec session. */ 639322ebca6SAkhil Goyal ret = fill_session_conf(portid, &sess_conf); 640322ebca6SAkhil Goyal if (ret) { 641322ebca6SAkhil Goyal printf("MACsec Session conf failed.\n"); 642322ebca6SAkhil Goyal goto out; 643322ebca6SAkhil Goyal } 644322ebca6SAkhil Goyal mcs_port_params[portid].sess = 645322ebca6SAkhil Goyal rte_security_session_create(mcs_port_params[portid].sec_ctx, 646322ebca6SAkhil Goyal &sess_conf, mcs_port_params[portid].sess_pool); 647322ebca6SAkhil Goyal if (mcs_port_params[portid].sess == NULL) { 648322ebca6SAkhil Goyal printf("MACSEC Session init failed errno: %d.\n", rte_errno); 649322ebca6SAkhil Goyal goto out; 650322ebca6SAkhil Goyal } 651322ebca6SAkhil Goyal 652322ebca6SAkhil Goyal /* Create MACsec flow. */ 653322ebca6SAkhil Goyal ret = create_default_flow(portid); 654322ebca6SAkhil Goyal if (ret) 655322ebca6SAkhil Goyal goto out; 656322ebca6SAkhil Goyal 657322ebca6SAkhil Goyal return 0; 658322ebca6SAkhil Goyal out: 659322ebca6SAkhil Goyal clean_macsec_resources(portid); 660322ebca6SAkhil Goyal return -1; 661322ebca6SAkhil Goyal } 662322ebca6SAkhil Goyal 663322ebca6SAkhil Goyal /* main processing loop */ 664322ebca6SAkhil Goyal static void 665322ebca6SAkhil Goyal l2fwd_main_loop(void) 666322ebca6SAkhil Goyal { 667322ebca6SAkhil Goyal struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 668322ebca6SAkhil Goyal struct rte_mbuf *m; 669322ebca6SAkhil Goyal int sent; 670322ebca6SAkhil Goyal unsigned int lcore_id; 671322ebca6SAkhil Goyal uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; 672322ebca6SAkhil Goyal unsigned int i, j, portid, nb_rx; 673322ebca6SAkhil Goyal struct lcore_queue_conf *qconf; 674322ebca6SAkhil Goyal const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * 675322ebca6SAkhil Goyal BURST_TX_DRAIN_US; 676322ebca6SAkhil Goyal struct rte_eth_dev_tx_buffer *buffer; 677322ebca6SAkhil Goyal 678322ebca6SAkhil Goyal prev_tsc = 0; 679322ebca6SAkhil Goyal timer_tsc = 0; 680322ebca6SAkhil Goyal 681322ebca6SAkhil Goyal lcore_id = rte_lcore_id(); 682322ebca6SAkhil Goyal qconf = &lcore_queue_conf[lcore_id]; 683322ebca6SAkhil Goyal 684322ebca6SAkhil Goyal if (qconf->n_rx_port == 0) { 685322ebca6SAkhil Goyal RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); 686322ebca6SAkhil Goyal return; 687322ebca6SAkhil Goyal } 688322ebca6SAkhil Goyal 689322ebca6SAkhil Goyal RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); 690322ebca6SAkhil Goyal 691322ebca6SAkhil Goyal for (i = 0; i < qconf->n_rx_port; i++) { 692322ebca6SAkhil Goyal 693322ebca6SAkhil Goyal portid = qconf->rx_port_list[i]; 694322ebca6SAkhil Goyal 695322ebca6SAkhil Goyal RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, 696322ebca6SAkhil Goyal portid); 697322ebca6SAkhil Goyal } 698322ebca6SAkhil Goyal 699322ebca6SAkhil Goyal while (!force_quit) { 700322ebca6SAkhil Goyal 701322ebca6SAkhil Goyal /* Drains TX queue in its main loop. 8< */ 702322ebca6SAkhil Goyal cur_tsc = rte_rdtsc(); 703322ebca6SAkhil Goyal 704322ebca6SAkhil Goyal /* 705322ebca6SAkhil Goyal * TX burst queue drain 706322ebca6SAkhil Goyal */ 707322ebca6SAkhil Goyal diff_tsc = cur_tsc - prev_tsc; 708322ebca6SAkhil Goyal if (unlikely(diff_tsc > drain_tsc)) { 709322ebca6SAkhil Goyal 710322ebca6SAkhil Goyal for (i = 0; i < qconf->n_rx_port; i++) { 711322ebca6SAkhil Goyal 712322ebca6SAkhil Goyal portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; 713322ebca6SAkhil Goyal buffer = tx_buffer[portid]; 714322ebca6SAkhil Goyal 715322ebca6SAkhil Goyal sent = rte_eth_tx_buffer_flush(portid, 0, buffer); 716322ebca6SAkhil Goyal if (sent) 717322ebca6SAkhil Goyal port_statistics[portid].tx += sent; 718322ebca6SAkhil Goyal 719322ebca6SAkhil Goyal } 720322ebca6SAkhil Goyal 721322ebca6SAkhil Goyal /* if timer is enabled */ 722322ebca6SAkhil Goyal if (timer_period > 0) { 723322ebca6SAkhil Goyal 724322ebca6SAkhil Goyal /* advance the timer */ 725322ebca6SAkhil Goyal timer_tsc += diff_tsc; 726322ebca6SAkhil Goyal 727322ebca6SAkhil Goyal /* if timer has reached its timeout */ 728322ebca6SAkhil Goyal if (unlikely(timer_tsc >= timer_period)) { 729322ebca6SAkhil Goyal 730322ebca6SAkhil Goyal /* do this only on main core */ 731322ebca6SAkhil Goyal if (lcore_id == rte_get_main_lcore()) { 732322ebca6SAkhil Goyal print_stats(); 733322ebca6SAkhil Goyal /* reset the timer */ 734322ebca6SAkhil Goyal timer_tsc = 0; 735322ebca6SAkhil Goyal } 736322ebca6SAkhil Goyal } 737322ebca6SAkhil Goyal } 738322ebca6SAkhil Goyal 739322ebca6SAkhil Goyal prev_tsc = cur_tsc; 740322ebca6SAkhil Goyal } 741322ebca6SAkhil Goyal /* >8 End of draining TX queue. */ 742322ebca6SAkhil Goyal 743322ebca6SAkhil Goyal /* Read packet from RX queues. 8< */ 744322ebca6SAkhil Goyal for (i = 0; i < qconf->n_rx_port; i++) { 745322ebca6SAkhil Goyal 746322ebca6SAkhil Goyal portid = qconf->rx_port_list[i]; 747322ebca6SAkhil Goyal nb_rx = rte_eth_rx_burst(portid, 0, 748322ebca6SAkhil Goyal pkts_burst, MAX_PKT_BURST); 749322ebca6SAkhil Goyal 750322ebca6SAkhil Goyal if (unlikely(nb_rx == 0)) 751322ebca6SAkhil Goyal continue; 752322ebca6SAkhil Goyal 753322ebca6SAkhil Goyal port_statistics[portid].rx += nb_rx; 754322ebca6SAkhil Goyal 755322ebca6SAkhil Goyal for (j = 0; j < nb_rx; j++) { 756322ebca6SAkhil Goyal m = pkts_burst[j]; 757322ebca6SAkhil Goyal rte_prefetch0(rte_pktmbuf_mtod(m, void *)); 758322ebca6SAkhil Goyal l2fwd_simple_forward(m, portid); 759322ebca6SAkhil Goyal } 760322ebca6SAkhil Goyal } 761322ebca6SAkhil Goyal /* >8 End of read packet from RX queues. */ 762322ebca6SAkhil Goyal } 763322ebca6SAkhil Goyal if (force_quit) { 764322ebca6SAkhil Goyal for (i = 0; i < qconf->n_rx_port; i++) { 765322ebca6SAkhil Goyal portid = qconf->rx_port_list[i]; 766322ebca6SAkhil Goyal clean_macsec_resources(portid); 767322ebca6SAkhil Goyal } 768322ebca6SAkhil Goyal } 769322ebca6SAkhil Goyal } 770322ebca6SAkhil Goyal static int 771322ebca6SAkhil Goyal l2fwd_launch_one_lcore(__rte_unused void *arg) 772322ebca6SAkhil Goyal { 773322ebca6SAkhil Goyal l2fwd_main_loop(); 774322ebca6SAkhil Goyal return 0; 775322ebca6SAkhil Goyal } 776322ebca6SAkhil Goyal 777322ebca6SAkhil Goyal /* display usage */ 778322ebca6SAkhil Goyal static void 779322ebca6SAkhil Goyal l2fwd_usage(const char *prgname) 780322ebca6SAkhil Goyal { 781322ebca6SAkhil Goyal printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" 782322ebca6SAkhil Goyal " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 783322ebca6SAkhil Goyal " -q NQ: number of queue (=ports) per lcore (default is 1)\n" 784322ebca6SAkhil Goyal " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" 785322ebca6SAkhil Goyal " --mcs-tx-portmask: Hexadecimal bitmask for MACsec Tx(Encap) ports\n" 786322ebca6SAkhil Goyal " --mcs-rx-portmask: Hexadecimal bitmask for MACsec Rx(Decap) ports\n" 787322ebca6SAkhil Goyal " --mcs-port-config '(<port>,<src-mac>,<dst-mac>)'\n" 788322ebca6SAkhil Goyal " --portmap: Configure forwarding port pair mapping\n" 789322ebca6SAkhil Goyal " Default: alternate port pairs\n\n", 790322ebca6SAkhil Goyal prgname); 791322ebca6SAkhil Goyal } 792322ebca6SAkhil Goyal 793322ebca6SAkhil Goyal static int 794322ebca6SAkhil Goyal l2fwd_parse_portmask(const char *portmask) 795322ebca6SAkhil Goyal { 796322ebca6SAkhil Goyal char *end = NULL; 797322ebca6SAkhil Goyal unsigned long pm; 798322ebca6SAkhil Goyal 799322ebca6SAkhil Goyal /* parse hexadecimal string */ 800322ebca6SAkhil Goyal pm = strtoul(portmask, &end, 16); 801322ebca6SAkhil Goyal if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 802322ebca6SAkhil Goyal return 0; 803322ebca6SAkhil Goyal 804322ebca6SAkhil Goyal return pm; 805322ebca6SAkhil Goyal } 806322ebca6SAkhil Goyal 807322ebca6SAkhil Goyal static int 808322ebca6SAkhil Goyal l2fwd_parse_port_pair_config(const char *q_arg) 809322ebca6SAkhil Goyal { 810322ebca6SAkhil Goyal enum fieldnames { 811322ebca6SAkhil Goyal FLD_PORT1 = 0, 812322ebca6SAkhil Goyal FLD_PORT2, 813322ebca6SAkhil Goyal _NUM_FLD 814322ebca6SAkhil Goyal }; 815322ebca6SAkhil Goyal unsigned long int_fld[_NUM_FLD]; 816322ebca6SAkhil Goyal const char *p, *p0 = q_arg; 817322ebca6SAkhil Goyal char *str_fld[_NUM_FLD]; 818322ebca6SAkhil Goyal unsigned int size; 819322ebca6SAkhil Goyal char s[256]; 820322ebca6SAkhil Goyal char *end; 821322ebca6SAkhil Goyal int i; 822322ebca6SAkhil Goyal 823322ebca6SAkhil Goyal nb_port_pair_params = 0; 824322ebca6SAkhil Goyal 825322ebca6SAkhil Goyal while ((p = strchr(p0, '(')) != NULL) { 826322ebca6SAkhil Goyal ++p; 827322ebca6SAkhil Goyal p0 = strchr(p, ')'); 828322ebca6SAkhil Goyal if (p0 == NULL) 829322ebca6SAkhil Goyal return -1; 830322ebca6SAkhil Goyal 831322ebca6SAkhil Goyal size = p0 - p; 832322ebca6SAkhil Goyal if (size >= sizeof(s)) 833322ebca6SAkhil Goyal return -1; 834322ebca6SAkhil Goyal 835322ebca6SAkhil Goyal memcpy(s, p, size); 836322ebca6SAkhil Goyal s[size] = '\0'; 837322ebca6SAkhil Goyal if (rte_strsplit(s, sizeof(s), str_fld, 838322ebca6SAkhil Goyal _NUM_FLD, ',') != _NUM_FLD) 839322ebca6SAkhil Goyal return -1; 840322ebca6SAkhil Goyal for (i = 0; i < _NUM_FLD; i++) { 841322ebca6SAkhil Goyal errno = 0; 842322ebca6SAkhil Goyal int_fld[i] = strtoul(str_fld[i], &end, 0); 843322ebca6SAkhil Goyal if (errno != 0 || end == str_fld[i] || 844322ebca6SAkhil Goyal int_fld[i] >= RTE_MAX_ETHPORTS) 845322ebca6SAkhil Goyal return -1; 846322ebca6SAkhil Goyal } 847322ebca6SAkhil Goyal if (nb_port_pair_params >= RTE_MAX_ETHPORTS/2) { 848322ebca6SAkhil Goyal printf("exceeded max number of port pair params: %hu\n", 849322ebca6SAkhil Goyal nb_port_pair_params); 850322ebca6SAkhil Goyal return -1; 851322ebca6SAkhil Goyal } 852322ebca6SAkhil Goyal port_pair_params_array[nb_port_pair_params].port[0] = 853322ebca6SAkhil Goyal (uint16_t)int_fld[FLD_PORT1]; 854322ebca6SAkhil Goyal port_pair_params_array[nb_port_pair_params].port[1] = 855322ebca6SAkhil Goyal (uint16_t)int_fld[FLD_PORT2]; 856322ebca6SAkhil Goyal ++nb_port_pair_params; 857322ebca6SAkhil Goyal } 858322ebca6SAkhil Goyal port_pair_params = port_pair_params_array; 859322ebca6SAkhil Goyal return 0; 860322ebca6SAkhil Goyal } 861322ebca6SAkhil Goyal 862322ebca6SAkhil Goyal static int 863322ebca6SAkhil Goyal l2fwd_parse_macsec_port_config(const char *q_arg) 864322ebca6SAkhil Goyal { 865322ebca6SAkhil Goyal enum fieldnames { 866322ebca6SAkhil Goyal FLD_PORT = 0, 867322ebca6SAkhil Goyal FLD_SRC, 868322ebca6SAkhil Goyal FLD_DST, 869322ebca6SAkhil Goyal _NUM_FLD 870322ebca6SAkhil Goyal }; 871322ebca6SAkhil Goyal unsigned int portid; 872322ebca6SAkhil Goyal struct rte_ether_addr src, dst; 873322ebca6SAkhil Goyal const char *p, *p0 = q_arg; 874322ebca6SAkhil Goyal char *str_fld[_NUM_FLD]; 875322ebca6SAkhil Goyal unsigned int size; 876322ebca6SAkhil Goyal char s[256]; 877322ebca6SAkhil Goyal char *end; 878322ebca6SAkhil Goyal 879322ebca6SAkhil Goyal nb_port_pair_params = 0; 880322ebca6SAkhil Goyal 881322ebca6SAkhil Goyal while ((p = strchr(p0, '(')) != NULL) { 882322ebca6SAkhil Goyal ++p; 883322ebca6SAkhil Goyal p0 = strchr(p, ')'); 884322ebca6SAkhil Goyal if (p0 == NULL) 885322ebca6SAkhil Goyal return -1; 886322ebca6SAkhil Goyal 887322ebca6SAkhil Goyal size = p0 - p; 888322ebca6SAkhil Goyal if (size >= sizeof(s)) 889322ebca6SAkhil Goyal return -1; 890322ebca6SAkhil Goyal 891322ebca6SAkhil Goyal memcpy(s, p, size); 892322ebca6SAkhil Goyal s[size] = '\0'; 893322ebca6SAkhil Goyal if (rte_strsplit(s, sizeof(s), str_fld, 894322ebca6SAkhil Goyal _NUM_FLD, ',') != _NUM_FLD) 895322ebca6SAkhil Goyal return -1; 896322ebca6SAkhil Goyal errno = 0; 897322ebca6SAkhil Goyal portid = strtoul(str_fld[FLD_PORT], &end, 0); 898322ebca6SAkhil Goyal if (errno != 0 || end == str_fld[FLD_PORT] || portid >= RTE_MAX_ETHPORTS) 899322ebca6SAkhil Goyal return -1; 900322ebca6SAkhil Goyal if (port_ether_hdr_config[portid].ether_type == 0x0800) { 901322ebca6SAkhil Goyal printf("MACsec src-dst MAC addr already parsed for port: %d\n", 902322ebca6SAkhil Goyal portid); 903322ebca6SAkhil Goyal return -1; 904322ebca6SAkhil Goyal } 905322ebca6SAkhil Goyal if (rte_ether_unformat_addr(str_fld[FLD_SRC], &src) || 906322ebca6SAkhil Goyal rte_ether_unformat_addr(str_fld[FLD_DST], &dst)) 907322ebca6SAkhil Goyal return -1; 908322ebca6SAkhil Goyal 909322ebca6SAkhil Goyal memcpy(&port_ether_hdr_config[portid].src_addr, &src, sizeof(src)); 910322ebca6SAkhil Goyal memcpy(&port_ether_hdr_config[portid].dst_addr, &dst, sizeof(dst)); 911322ebca6SAkhil Goyal port_ether_hdr_config[portid].ether_type = 0x0800; 912322ebca6SAkhil Goyal } 913322ebca6SAkhil Goyal 914322ebca6SAkhil Goyal return 0; 915322ebca6SAkhil Goyal } 916322ebca6SAkhil Goyal 917322ebca6SAkhil Goyal 918322ebca6SAkhil Goyal static unsigned int 919322ebca6SAkhil Goyal l2fwd_parse_nqueue(const char *q_arg) 920322ebca6SAkhil Goyal { 921322ebca6SAkhil Goyal char *end = NULL; 922322ebca6SAkhil Goyal unsigned long n; 923322ebca6SAkhil Goyal 924322ebca6SAkhil Goyal /* parse hexadecimal string */ 925322ebca6SAkhil Goyal n = strtoul(q_arg, &end, 10); 926322ebca6SAkhil Goyal if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 927322ebca6SAkhil Goyal return 0; 928322ebca6SAkhil Goyal if (n == 0) 929322ebca6SAkhil Goyal return 0; 930322ebca6SAkhil Goyal if (n >= MAX_RX_QUEUE_PER_LCORE) 931322ebca6SAkhil Goyal return 0; 932322ebca6SAkhil Goyal 933322ebca6SAkhil Goyal return n; 934322ebca6SAkhil Goyal } 935322ebca6SAkhil Goyal 936322ebca6SAkhil Goyal static int 937322ebca6SAkhil Goyal l2fwd_parse_timer_period(const char *q_arg) 938322ebca6SAkhil Goyal { 939322ebca6SAkhil Goyal char *end = NULL; 940322ebca6SAkhil Goyal int n; 941322ebca6SAkhil Goyal 942322ebca6SAkhil Goyal /* parse number string */ 943322ebca6SAkhil Goyal n = strtol(q_arg, &end, 10); 944322ebca6SAkhil Goyal if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 945322ebca6SAkhil Goyal return -1; 946322ebca6SAkhil Goyal if (n >= MAX_TIMER_PERIOD) 947322ebca6SAkhil Goyal return -1; 948322ebca6SAkhil Goyal 949322ebca6SAkhil Goyal return n; 950322ebca6SAkhil Goyal } 951322ebca6SAkhil Goyal 952322ebca6SAkhil Goyal static const char short_options[] = 953322ebca6SAkhil Goyal "p:" /* portmask */ 954322ebca6SAkhil Goyal "P" /* promiscuous */ 955322ebca6SAkhil Goyal "q:" /* number of queues */ 956322ebca6SAkhil Goyal "T:" /* timer period */ 957322ebca6SAkhil Goyal ; 958322ebca6SAkhil Goyal 959322ebca6SAkhil Goyal #define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" 960322ebca6SAkhil Goyal #define CMD_LINE_OPT_PORTMAP_CONFIG "portmap" 961322ebca6SAkhil Goyal #define CMD_LINE_OPT_MACSEC_TX_PORTMASK "mcs-tx-portmask" 962322ebca6SAkhil Goyal #define CMD_LINE_OPT_MACSEC_RX_PORTMASK "mcs-rx-portmask" 963322ebca6SAkhil Goyal #define CMD_LINE_OPT_MACSEC_PORT_CONFIG "mcs-port-config" 964322ebca6SAkhil Goyal 965322ebca6SAkhil Goyal enum { 966322ebca6SAkhil Goyal /* Long options mapped to a short option. 967322ebca6SAkhil Goyal * First long only option value must be >= 256, 968322ebca6SAkhil Goyal * so that we won't conflict with short options. 969322ebca6SAkhil Goyal */ 970322ebca6SAkhil Goyal CMD_LINE_OPT_NO_MAC_UPDATING_NUM = 256, 971322ebca6SAkhil Goyal CMD_LINE_OPT_PORTMAP_NUM, 972322ebca6SAkhil Goyal CMD_LINE_OPT_MACSEC_TX_PORTMASK_NUM, 973322ebca6SAkhil Goyal CMD_LINE_OPT_MACSEC_RX_PORTMASK_NUM, 974322ebca6SAkhil Goyal CMD_LINE_OPT_MACSEC_PORT_CFG_NUM, 975322ebca6SAkhil Goyal }; 976322ebca6SAkhil Goyal 977322ebca6SAkhil Goyal static const struct option lgopts[] = { 978322ebca6SAkhil Goyal { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, 0, 979322ebca6SAkhil Goyal CMD_LINE_OPT_NO_MAC_UPDATING_NUM}, 980322ebca6SAkhil Goyal { CMD_LINE_OPT_PORTMAP_CONFIG, 1, 0, CMD_LINE_OPT_PORTMAP_NUM}, 981322ebca6SAkhil Goyal { CMD_LINE_OPT_MACSEC_TX_PORTMASK, required_argument, 0, 982322ebca6SAkhil Goyal CMD_LINE_OPT_MACSEC_TX_PORTMASK_NUM}, 983322ebca6SAkhil Goyal { CMD_LINE_OPT_MACSEC_RX_PORTMASK, required_argument, 0, 984322ebca6SAkhil Goyal CMD_LINE_OPT_MACSEC_RX_PORTMASK_NUM}, 985322ebca6SAkhil Goyal { CMD_LINE_OPT_MACSEC_PORT_CONFIG, 1, 0, CMD_LINE_OPT_MACSEC_PORT_CFG_NUM}, 986322ebca6SAkhil Goyal {NULL, 0, 0, 0} 987322ebca6SAkhil Goyal }; 988322ebca6SAkhil Goyal 989322ebca6SAkhil Goyal /** Generate default options for application. */ 990322ebca6SAkhil Goyal static void 991322ebca6SAkhil Goyal l2fwd_macsec_default_options(struct l2fwd_macsec_options *options) 992322ebca6SAkhil Goyal { 993322ebca6SAkhil Goyal uint16_t portid; 994322ebca6SAkhil Goyal uint8_t salt[MCS_SALT_LEN] = {0}; 995322ebca6SAkhil Goyal uint8_t key[16] = { 996322ebca6SAkhil Goyal 0x07, 0x1B, 0x11, 0x3B, 0x0C, 0xA7, 0x43, 0xFE, 997322ebca6SAkhil Goyal 0xCC, 0xCF, 0x3D, 0x05, 0x1F, 0x73, 0x73, 0x82 998322ebca6SAkhil Goyal }; 999322ebca6SAkhil Goyal 1000322ebca6SAkhil Goyal options->portmask = 0xffffffff; 1001322ebca6SAkhil Goyal options->nb_ports_per_lcore = 1; 1002322ebca6SAkhil Goyal options->single_lcore = 0; 1003322ebca6SAkhil Goyal 1004322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1005322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 1006322ebca6SAkhil Goyal continue; 1007322ebca6SAkhil Goyal if ((options->tx_portmask & (1 << portid)) != 0) 1008322ebca6SAkhil Goyal mcs_port_params[portid].dir = RTE_SECURITY_MACSEC_DIR_TX; 1009322ebca6SAkhil Goyal 1010322ebca6SAkhil Goyal if ((options->rx_portmask & (1 << portid)) != 0) 1011322ebca6SAkhil Goyal mcs_port_params[portid].dir = RTE_SECURITY_MACSEC_DIR_RX; 1012322ebca6SAkhil Goyal 10130d187ba8SAkhil Goyal mcs_port_params[portid].alg = RTE_SECURITY_MACSEC_ALG_GCM_XPN_128; 1014322ebca6SAkhil Goyal memcpy(mcs_port_params[portid].sa_key.data, key, 16); 1015322ebca6SAkhil Goyal mcs_port_params[portid].sa_key.len = 16; 1016322ebca6SAkhil Goyal memcpy(mcs_port_params[portid].salt, salt, MCS_SALT_LEN); 1017322ebca6SAkhil Goyal 1018322ebca6SAkhil Goyal memcpy(mcs_port_params[portid].eth_hdr, &port_ether_hdr_config[portid], 1019322ebca6SAkhil Goyal RTE_ETHER_HDR_LEN); 1020322ebca6SAkhil Goyal 1021322ebca6SAkhil Goyal mcs_port_params[portid].ssci = 0; 1022322ebca6SAkhil Goyal mcs_port_params[portid].pn_threshold = 0xffffffffffffffff; 1023322ebca6SAkhil Goyal mcs_port_params[portid].xpn = 0; 1024322ebca6SAkhil Goyal mcs_port_params[portid].next_pn = 1; 1025322ebca6SAkhil Goyal mcs_port_params[portid].mtu = 1500; 1026322ebca6SAkhil Goyal mcs_port_params[portid].sectag_insert_mode = 1; 1027322ebca6SAkhil Goyal mcs_port_params[portid].encrypt = true; 1028322ebca6SAkhil Goyal mcs_port_params[portid].protect_frames = true; 1029322ebca6SAkhil Goyal mcs_port_params[portid].replay_protect = false; 1030322ebca6SAkhil Goyal mcs_port_params[portid].val_frames = RTE_SECURITY_MACSEC_VALIDATE_STRICT; 1031322ebca6SAkhil Goyal mcs_port_params[portid].send_sci = true; 1032322ebca6SAkhil Goyal mcs_port_params[portid].end_station = false; 1033322ebca6SAkhil Goyal mcs_port_params[portid].scb = false; 1034322ebca6SAkhil Goyal } 1035322ebca6SAkhil Goyal } 1036322ebca6SAkhil Goyal 1037322ebca6SAkhil Goyal /* Parse the argument given in the command line of the application */ 1038322ebca6SAkhil Goyal static int 1039322ebca6SAkhil Goyal l2fwd_parse_args(struct l2fwd_macsec_options *options, 1040322ebca6SAkhil Goyal int argc, char **argv) 1041322ebca6SAkhil Goyal { 1042322ebca6SAkhil Goyal int opt, ret, timer_secs; 1043322ebca6SAkhil Goyal char **argvopt; 1044322ebca6SAkhil Goyal int option_index; 1045322ebca6SAkhil Goyal char *prgname = argv[0]; 1046322ebca6SAkhil Goyal 1047322ebca6SAkhil Goyal argvopt = argv; 1048322ebca6SAkhil Goyal port_pair_params = NULL; 1049322ebca6SAkhil Goyal 1050322ebca6SAkhil Goyal while ((opt = getopt_long(argc, argvopt, short_options, 1051322ebca6SAkhil Goyal lgopts, &option_index)) != EOF) { 1052322ebca6SAkhil Goyal 1053322ebca6SAkhil Goyal switch (opt) { 1054322ebca6SAkhil Goyal /* portmask */ 1055322ebca6SAkhil Goyal case 'p': 1056322ebca6SAkhil Goyal l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); 1057322ebca6SAkhil Goyal if (l2fwd_enabled_port_mask == 0) { 1058322ebca6SAkhil Goyal printf("invalid portmask\n"); 1059322ebca6SAkhil Goyal l2fwd_usage(prgname); 1060322ebca6SAkhil Goyal return -1; 1061322ebca6SAkhil Goyal } 1062322ebca6SAkhil Goyal break; 1063322ebca6SAkhil Goyal case 'P': 1064322ebca6SAkhil Goyal promiscuous_on = 1; 1065322ebca6SAkhil Goyal break; 1066322ebca6SAkhil Goyal 1067322ebca6SAkhil Goyal /* nqueue */ 1068322ebca6SAkhil Goyal case 'q': 1069322ebca6SAkhil Goyal l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); 1070322ebca6SAkhil Goyal if (l2fwd_rx_queue_per_lcore == 0) { 1071322ebca6SAkhil Goyal printf("invalid queue number\n"); 1072322ebca6SAkhil Goyal l2fwd_usage(prgname); 1073322ebca6SAkhil Goyal return -1; 1074322ebca6SAkhil Goyal } 1075322ebca6SAkhil Goyal break; 1076322ebca6SAkhil Goyal 1077322ebca6SAkhil Goyal /* timer period */ 1078322ebca6SAkhil Goyal case 'T': 1079322ebca6SAkhil Goyal timer_secs = l2fwd_parse_timer_period(optarg); 1080322ebca6SAkhil Goyal if (timer_secs < 0) { 1081322ebca6SAkhil Goyal printf("invalid timer period\n"); 1082322ebca6SAkhil Goyal l2fwd_usage(prgname); 1083322ebca6SAkhil Goyal return -1; 1084322ebca6SAkhil Goyal } 1085322ebca6SAkhil Goyal timer_period = timer_secs; 1086322ebca6SAkhil Goyal break; 1087322ebca6SAkhil Goyal 1088322ebca6SAkhil Goyal /* long options */ 1089322ebca6SAkhil Goyal case CMD_LINE_OPT_PORTMAP_NUM: 1090322ebca6SAkhil Goyal ret = l2fwd_parse_port_pair_config(optarg); 1091322ebca6SAkhil Goyal if (ret) { 1092322ebca6SAkhil Goyal fprintf(stderr, "Invalid config\n"); 1093322ebca6SAkhil Goyal l2fwd_usage(prgname); 1094322ebca6SAkhil Goyal return -1; 1095322ebca6SAkhil Goyal } 1096322ebca6SAkhil Goyal break; 1097322ebca6SAkhil Goyal 1098322ebca6SAkhil Goyal case CMD_LINE_OPT_NO_MAC_UPDATING_NUM: 1099322ebca6SAkhil Goyal mac_updating = 0; 1100322ebca6SAkhil Goyal break; 1101322ebca6SAkhil Goyal 1102322ebca6SAkhil Goyal case CMD_LINE_OPT_MACSEC_TX_PORTMASK_NUM: 1103322ebca6SAkhil Goyal options->tx_portmask = l2fwd_parse_portmask(optarg); 1104322ebca6SAkhil Goyal if (options->tx_portmask == 0) { 1105322ebca6SAkhil Goyal l2fwd_usage(prgname); 1106322ebca6SAkhil Goyal return -1; 1107322ebca6SAkhil Goyal } 1108322ebca6SAkhil Goyal break; 1109322ebca6SAkhil Goyal 1110322ebca6SAkhil Goyal case CMD_LINE_OPT_MACSEC_RX_PORTMASK_NUM: 1111322ebca6SAkhil Goyal options->rx_portmask = l2fwd_parse_portmask(optarg); 1112322ebca6SAkhil Goyal if (options->rx_portmask == 0) { 1113322ebca6SAkhil Goyal l2fwd_usage(prgname); 1114322ebca6SAkhil Goyal return -1; 1115322ebca6SAkhil Goyal } 1116322ebca6SAkhil Goyal break; 1117322ebca6SAkhil Goyal 1118322ebca6SAkhil Goyal case CMD_LINE_OPT_MACSEC_PORT_CFG_NUM: 1119322ebca6SAkhil Goyal ret = l2fwd_parse_macsec_port_config(optarg); 1120322ebca6SAkhil Goyal if (ret) { 1121322ebca6SAkhil Goyal fprintf(stderr, "Invalid MACsec port config\n"); 1122322ebca6SAkhil Goyal l2fwd_usage(prgname); 1123322ebca6SAkhil Goyal return -1; 1124322ebca6SAkhil Goyal } 1125322ebca6SAkhil Goyal break; 1126322ebca6SAkhil Goyal 1127322ebca6SAkhil Goyal default: 1128322ebca6SAkhil Goyal l2fwd_usage(prgname); 1129322ebca6SAkhil Goyal return -1; 1130322ebca6SAkhil Goyal } 1131322ebca6SAkhil Goyal } 1132322ebca6SAkhil Goyal l2fwd_macsec_default_options(options); 1133322ebca6SAkhil Goyal 1134322ebca6SAkhil Goyal if (optind >= 0) 1135322ebca6SAkhil Goyal argv[optind-1] = prgname; 1136322ebca6SAkhil Goyal 1137322ebca6SAkhil Goyal ret = optind-1; 1138322ebca6SAkhil Goyal optind = 1; /* reset getopt lib */ 1139322ebca6SAkhil Goyal return ret; 1140322ebca6SAkhil Goyal } 1141322ebca6SAkhil Goyal 1142322ebca6SAkhil Goyal /* 1143322ebca6SAkhil Goyal * Check port pair config with enabled port mask, 1144322ebca6SAkhil Goyal * and for valid port pair combinations. 1145322ebca6SAkhil Goyal */ 1146322ebca6SAkhil Goyal static int 1147322ebca6SAkhil Goyal check_port_pair_config(void) 1148322ebca6SAkhil Goyal { 1149322ebca6SAkhil Goyal uint32_t port_pair_config_mask = 0; 1150322ebca6SAkhil Goyal uint32_t port_pair_mask = 0; 1151322ebca6SAkhil Goyal uint16_t index, i, portid; 1152322ebca6SAkhil Goyal 1153322ebca6SAkhil Goyal for (index = 0; index < nb_port_pair_params; index++) { 1154322ebca6SAkhil Goyal port_pair_mask = 0; 1155322ebca6SAkhil Goyal 1156322ebca6SAkhil Goyal for (i = 0; i < NUM_PORTS; i++) { 1157322ebca6SAkhil Goyal portid = port_pair_params[index].port[i]; 1158322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { 1159322ebca6SAkhil Goyal printf("port %u is not enabled in port mask\n", 1160322ebca6SAkhil Goyal portid); 1161322ebca6SAkhil Goyal return -1; 1162322ebca6SAkhil Goyal } 1163322ebca6SAkhil Goyal if (!rte_eth_dev_is_valid_port(portid)) { 1164322ebca6SAkhil Goyal printf("port %u is not present on the board\n", 1165322ebca6SAkhil Goyal portid); 1166322ebca6SAkhil Goyal return -1; 1167322ebca6SAkhil Goyal } 1168322ebca6SAkhil Goyal 1169322ebca6SAkhil Goyal port_pair_mask |= 1 << portid; 1170322ebca6SAkhil Goyal } 1171322ebca6SAkhil Goyal 1172322ebca6SAkhil Goyal if (port_pair_config_mask & port_pair_mask) { 1173322ebca6SAkhil Goyal printf("port %u is used in other port pairs\n", portid); 1174322ebca6SAkhil Goyal return -1; 1175322ebca6SAkhil Goyal } 1176322ebca6SAkhil Goyal port_pair_config_mask |= port_pair_mask; 1177322ebca6SAkhil Goyal } 1178322ebca6SAkhil Goyal 1179322ebca6SAkhil Goyal l2fwd_enabled_port_mask &= port_pair_config_mask; 1180322ebca6SAkhil Goyal 1181322ebca6SAkhil Goyal return 0; 1182322ebca6SAkhil Goyal } 1183322ebca6SAkhil Goyal 1184322ebca6SAkhil Goyal /* Check the link status of all ports in up to 9s, and print them finally */ 1185322ebca6SAkhil Goyal static void 1186322ebca6SAkhil Goyal check_all_ports_link_status(uint32_t port_mask) 1187322ebca6SAkhil Goyal { 1188322ebca6SAkhil Goyal #define CHECK_INTERVAL 100 /* 100ms */ 1189322ebca6SAkhil Goyal #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1190322ebca6SAkhil Goyal uint16_t portid; 1191322ebca6SAkhil Goyal uint8_t count, all_ports_up, print_flag = 0; 1192322ebca6SAkhil Goyal struct rte_eth_link link; 1193322ebca6SAkhil Goyal int ret; 1194322ebca6SAkhil Goyal char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 1195322ebca6SAkhil Goyal 1196322ebca6SAkhil Goyal printf("\nChecking link status"); 1197322ebca6SAkhil Goyal fflush(stdout); 1198322ebca6SAkhil Goyal for (count = 0; count <= MAX_CHECK_TIME; count++) { 1199322ebca6SAkhil Goyal if (force_quit) 1200322ebca6SAkhil Goyal return; 1201322ebca6SAkhil Goyal all_ports_up = 1; 1202322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1203322ebca6SAkhil Goyal if (force_quit) 1204322ebca6SAkhil Goyal return; 1205322ebca6SAkhil Goyal if ((port_mask & (1 << portid)) == 0) 1206322ebca6SAkhil Goyal continue; 1207322ebca6SAkhil Goyal memset(&link, 0, sizeof(link)); 1208322ebca6SAkhil Goyal ret = rte_eth_link_get_nowait(portid, &link); 1209322ebca6SAkhil Goyal if (ret < 0) { 1210322ebca6SAkhil Goyal all_ports_up = 0; 1211322ebca6SAkhil Goyal if (print_flag == 1) 1212322ebca6SAkhil Goyal printf("Port %u link get failed: %s\n", 1213322ebca6SAkhil Goyal portid, rte_strerror(-ret)); 1214322ebca6SAkhil Goyal continue; 1215322ebca6SAkhil Goyal } 1216322ebca6SAkhil Goyal /* print link status if flag set */ 1217322ebca6SAkhil Goyal if (print_flag == 1) { 1218322ebca6SAkhil Goyal rte_eth_link_to_str(link_status_text, 1219322ebca6SAkhil Goyal sizeof(link_status_text), &link); 1220322ebca6SAkhil Goyal printf("Port %d %s\n", portid, 1221322ebca6SAkhil Goyal link_status_text); 1222322ebca6SAkhil Goyal continue; 1223322ebca6SAkhil Goyal } 1224322ebca6SAkhil Goyal /* clear all_ports_up flag if any link down */ 1225322ebca6SAkhil Goyal if (link.link_status == RTE_ETH_LINK_DOWN) { 1226322ebca6SAkhil Goyal all_ports_up = 0; 1227322ebca6SAkhil Goyal break; 1228322ebca6SAkhil Goyal } 1229322ebca6SAkhil Goyal } 1230322ebca6SAkhil Goyal /* after finally printing all link status, get out */ 1231322ebca6SAkhil Goyal if (print_flag == 1) 1232322ebca6SAkhil Goyal break; 1233322ebca6SAkhil Goyal 1234322ebca6SAkhil Goyal if (all_ports_up == 0) { 1235322ebca6SAkhil Goyal printf("."); 1236322ebca6SAkhil Goyal fflush(stdout); 1237322ebca6SAkhil Goyal rte_delay_ms(CHECK_INTERVAL); 1238322ebca6SAkhil Goyal } 1239322ebca6SAkhil Goyal 1240322ebca6SAkhil Goyal /* set the print_flag if all ports up or timeout */ 1241322ebca6SAkhil Goyal if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1242322ebca6SAkhil Goyal print_flag = 1; 1243322ebca6SAkhil Goyal printf("done\n"); 1244322ebca6SAkhil Goyal } 1245322ebca6SAkhil Goyal } 1246322ebca6SAkhil Goyal } 1247322ebca6SAkhil Goyal 1248322ebca6SAkhil Goyal static void 1249322ebca6SAkhil Goyal signal_handler(int signum) 1250322ebca6SAkhil Goyal { 1251322ebca6SAkhil Goyal if (signum == SIGINT || signum == SIGTERM) { 1252322ebca6SAkhil Goyal printf("\n\nSignal %d received, preparing to exit...\n", 1253322ebca6SAkhil Goyal signum); 1254322ebca6SAkhil Goyal force_quit = true; 1255322ebca6SAkhil Goyal } 1256322ebca6SAkhil Goyal } 1257322ebca6SAkhil Goyal 1258322ebca6SAkhil Goyal int 1259322ebca6SAkhil Goyal main(int argc, char **argv) 1260322ebca6SAkhil Goyal { 1261322ebca6SAkhil Goyal struct l2fwd_macsec_options options = {0}; 1262322ebca6SAkhil Goyal struct lcore_queue_conf *qconf; 1263322ebca6SAkhil Goyal int ret; 1264322ebca6SAkhil Goyal uint16_t nb_ports; 1265322ebca6SAkhil Goyal uint16_t nb_ports_available = 0; 1266322ebca6SAkhil Goyal uint16_t portid, last_port; 1267322ebca6SAkhil Goyal unsigned int lcore_id, rx_lcore_id; 1268322ebca6SAkhil Goyal unsigned int nb_ports_in_mask = 0; 1269322ebca6SAkhil Goyal unsigned int nb_lcores = 0; 1270322ebca6SAkhil Goyal unsigned int nb_mbufs; 1271322ebca6SAkhil Goyal uint16_t nb_sess = 512; 1272322ebca6SAkhil Goyal uint32_t sess_sz; 1273322ebca6SAkhil Goyal char s[64]; 1274322ebca6SAkhil Goyal 1275322ebca6SAkhil Goyal /* Init EAL. 8< */ 1276322ebca6SAkhil Goyal ret = rte_eal_init(argc, argv); 1277322ebca6SAkhil Goyal if (ret < 0) 1278322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); 1279322ebca6SAkhil Goyal argc -= ret; 1280322ebca6SAkhil Goyal argv += ret; 1281322ebca6SAkhil Goyal 1282322ebca6SAkhil Goyal force_quit = false; 1283322ebca6SAkhil Goyal signal(SIGINT, signal_handler); 1284322ebca6SAkhil Goyal signal(SIGTERM, signal_handler); 1285322ebca6SAkhil Goyal 1286322ebca6SAkhil Goyal /* parse application arguments (after the EAL ones) */ 1287322ebca6SAkhil Goyal ret = l2fwd_parse_args(&options, argc, argv); 1288322ebca6SAkhil Goyal if (ret < 0) 1289322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); 1290322ebca6SAkhil Goyal /* >8 End of init EAL. */ 1291322ebca6SAkhil Goyal 1292322ebca6SAkhil Goyal printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); 1293322ebca6SAkhil Goyal 1294322ebca6SAkhil Goyal /* convert to number of cycles */ 1295322ebca6SAkhil Goyal timer_period *= rte_get_timer_hz(); 1296322ebca6SAkhil Goyal 1297322ebca6SAkhil Goyal nb_ports = rte_eth_dev_count_avail(); 1298322ebca6SAkhil Goyal if (nb_ports == 0) 1299322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); 1300322ebca6SAkhil Goyal 1301322ebca6SAkhil Goyal if (port_pair_params != NULL) { 1302322ebca6SAkhil Goyal if (check_port_pair_config() < 0) 1303322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Invalid port pair config\n"); 1304322ebca6SAkhil Goyal } 1305322ebca6SAkhil Goyal 1306322ebca6SAkhil Goyal /* check port mask to possible port mask */ 1307322ebca6SAkhil Goyal if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) 1308322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", 1309322ebca6SAkhil Goyal (1 << nb_ports) - 1); 1310322ebca6SAkhil Goyal 1311322ebca6SAkhil Goyal /* Initialization of the driver. 8< */ 1312322ebca6SAkhil Goyal 1313322ebca6SAkhil Goyal /* reset l2fwd_dst_ports */ 1314322ebca6SAkhil Goyal for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) 1315322ebca6SAkhil Goyal l2fwd_dst_ports[portid] = 0; 1316322ebca6SAkhil Goyal last_port = 0; 1317322ebca6SAkhil Goyal 1318322ebca6SAkhil Goyal /* populate destination port details */ 1319322ebca6SAkhil Goyal if (port_pair_params != NULL) { 1320322ebca6SAkhil Goyal uint16_t idx, p; 1321322ebca6SAkhil Goyal 1322322ebca6SAkhil Goyal for (idx = 0; idx < (nb_port_pair_params << 1); idx++) { 1323322ebca6SAkhil Goyal p = idx & 1; 1324322ebca6SAkhil Goyal portid = port_pair_params[idx >> 1].port[p]; 1325322ebca6SAkhil Goyal l2fwd_dst_ports[portid] = 1326322ebca6SAkhil Goyal port_pair_params[idx >> 1].port[p ^ 1]; 1327322ebca6SAkhil Goyal } 1328322ebca6SAkhil Goyal } else { 1329322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1330322ebca6SAkhil Goyal /* skip ports that are not enabled */ 1331322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 1332322ebca6SAkhil Goyal continue; 1333322ebca6SAkhil Goyal 1334322ebca6SAkhil Goyal if (nb_ports_in_mask % 2) { 1335322ebca6SAkhil Goyal l2fwd_dst_ports[portid] = last_port; 1336322ebca6SAkhil Goyal l2fwd_dst_ports[last_port] = portid; 1337322ebca6SAkhil Goyal } else { 1338322ebca6SAkhil Goyal last_port = portid; 1339322ebca6SAkhil Goyal } 1340322ebca6SAkhil Goyal 1341322ebca6SAkhil Goyal nb_ports_in_mask++; 1342322ebca6SAkhil Goyal } 1343322ebca6SAkhil Goyal if (nb_ports_in_mask % 2) { 1344322ebca6SAkhil Goyal printf("Notice: odd number of ports in portmask.\n"); 1345322ebca6SAkhil Goyal l2fwd_dst_ports[last_port] = last_port; 1346322ebca6SAkhil Goyal } 1347322ebca6SAkhil Goyal } 1348322ebca6SAkhil Goyal /* >8 End of initialization of the driver. */ 1349322ebca6SAkhil Goyal 1350322ebca6SAkhil Goyal rx_lcore_id = 0; 1351322ebca6SAkhil Goyal qconf = NULL; 1352322ebca6SAkhil Goyal 1353322ebca6SAkhil Goyal /* Initialize the port/queue configuration of each logical core */ 1354322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1355322ebca6SAkhil Goyal /* skip ports that are not enabled */ 1356322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 1357322ebca6SAkhil Goyal continue; 1358322ebca6SAkhil Goyal 1359322ebca6SAkhil Goyal /* get the lcore_id for this port */ 1360322ebca6SAkhil Goyal while (rte_lcore_is_enabled(rx_lcore_id) == 0 || 1361322ebca6SAkhil Goyal lcore_queue_conf[rx_lcore_id].n_rx_port == 1362322ebca6SAkhil Goyal l2fwd_rx_queue_per_lcore) { 1363322ebca6SAkhil Goyal rx_lcore_id++; 1364322ebca6SAkhil Goyal if (rx_lcore_id >= RTE_MAX_LCORE) 1365322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Not enough cores\n"); 1366322ebca6SAkhil Goyal } 1367322ebca6SAkhil Goyal 1368322ebca6SAkhil Goyal if (qconf != &lcore_queue_conf[rx_lcore_id]) { 1369322ebca6SAkhil Goyal /* Assigned a new logical core in the loop above. */ 1370322ebca6SAkhil Goyal qconf = &lcore_queue_conf[rx_lcore_id]; 1371322ebca6SAkhil Goyal nb_lcores++; 1372322ebca6SAkhil Goyal } 1373322ebca6SAkhil Goyal 1374322ebca6SAkhil Goyal qconf->rx_port_list[qconf->n_rx_port] = portid; 1375322ebca6SAkhil Goyal qconf->n_rx_port++; 1376322ebca6SAkhil Goyal printf("Lcore %u: RX port %u TX port %u\n", rx_lcore_id, 1377322ebca6SAkhil Goyal portid, l2fwd_dst_ports[portid]); 1378322ebca6SAkhil Goyal } 1379322ebca6SAkhil Goyal 1380322ebca6SAkhil Goyal nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + 1381322ebca6SAkhil Goyal nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); 1382322ebca6SAkhil Goyal 1383322ebca6SAkhil Goyal /* Create the mbuf pool. 8< */ 1384322ebca6SAkhil Goyal l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, 1385322ebca6SAkhil Goyal MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, 1386322ebca6SAkhil Goyal rte_socket_id()); 1387322ebca6SAkhil Goyal if (l2fwd_pktmbuf_pool == NULL) 1388322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 1389322ebca6SAkhil Goyal /* >8 End of create the mbuf pool. */ 1390322ebca6SAkhil Goyal 1391322ebca6SAkhil Goyal /* Initialise each port */ 1392322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1393322ebca6SAkhil Goyal struct rte_eth_rxconf rxq_conf; 1394322ebca6SAkhil Goyal struct rte_eth_txconf txq_conf; 1395322ebca6SAkhil Goyal struct rte_eth_conf local_port_conf = port_conf; 1396322ebca6SAkhil Goyal struct rte_eth_dev_info dev_info; 1397322ebca6SAkhil Goyal 1398322ebca6SAkhil Goyal /* skip ports that are not enabled */ 1399322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { 1400322ebca6SAkhil Goyal printf("Skipping disabled port %u\n", portid); 1401322ebca6SAkhil Goyal continue; 1402322ebca6SAkhil Goyal } 1403322ebca6SAkhil Goyal nb_ports_available++; 1404322ebca6SAkhil Goyal 1405322ebca6SAkhil Goyal /* init port */ 1406322ebca6SAkhil Goyal printf("Initializing port %u... ", portid); 1407322ebca6SAkhil Goyal fflush(stdout); 1408322ebca6SAkhil Goyal 1409322ebca6SAkhil Goyal ret = rte_eth_dev_info_get(portid, &dev_info); 1410322ebca6SAkhil Goyal if (ret != 0) 1411322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1412322ebca6SAkhil Goyal "Error during getting device (port %u) info: %s\n", 1413322ebca6SAkhil Goyal portid, strerror(-ret)); 1414322ebca6SAkhil Goyal 1415322ebca6SAkhil Goyal if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) 1416322ebca6SAkhil Goyal local_port_conf.txmode.offloads |= 1417322ebca6SAkhil Goyal RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 1418322ebca6SAkhil Goyal /* Configure the number of queues for a port. */ 1419322ebca6SAkhil Goyal ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); 1420322ebca6SAkhil Goyal if (ret < 0) 1421322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", 1422322ebca6SAkhil Goyal ret, portid); 1423322ebca6SAkhil Goyal /* >8 End of configuration of the number of queues for a port. */ 1424322ebca6SAkhil Goyal 1425322ebca6SAkhil Goyal ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 1426322ebca6SAkhil Goyal &nb_txd); 1427322ebca6SAkhil Goyal if (ret < 0) 1428322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1429322ebca6SAkhil Goyal "Cannot adjust number of descriptors: err=%d, port=%u\n", 1430322ebca6SAkhil Goyal ret, portid); 1431322ebca6SAkhil Goyal 1432322ebca6SAkhil Goyal ret = rte_eth_macaddr_get(portid, 1433322ebca6SAkhil Goyal &l2fwd_ports_eth_addr[portid]); 1434322ebca6SAkhil Goyal if (ret < 0) 1435322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1436322ebca6SAkhil Goyal "Cannot get MAC address: err=%d, port=%u\n", 1437322ebca6SAkhil Goyal ret, portid); 1438322ebca6SAkhil Goyal 1439322ebca6SAkhil Goyal /* init one RX queue */ 1440322ebca6SAkhil Goyal fflush(stdout); 1441322ebca6SAkhil Goyal rxq_conf = dev_info.default_rxconf; 1442322ebca6SAkhil Goyal rxq_conf.offloads = local_port_conf.rxmode.offloads; 1443322ebca6SAkhil Goyal /* RX queue setup. 8< */ 1444322ebca6SAkhil Goyal ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, 1445322ebca6SAkhil Goyal rte_eth_dev_socket_id(portid), 1446322ebca6SAkhil Goyal &rxq_conf, 1447322ebca6SAkhil Goyal l2fwd_pktmbuf_pool); 1448322ebca6SAkhil Goyal if (ret < 0) 1449322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", 1450322ebca6SAkhil Goyal ret, portid); 1451322ebca6SAkhil Goyal /* >8 End of RX queue setup. */ 1452322ebca6SAkhil Goyal 1453322ebca6SAkhil Goyal /* Init one TX queue on each port. 8< */ 1454322ebca6SAkhil Goyal fflush(stdout); 1455322ebca6SAkhil Goyal txq_conf = dev_info.default_txconf; 1456322ebca6SAkhil Goyal txq_conf.offloads = local_port_conf.txmode.offloads; 1457322ebca6SAkhil Goyal ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, 1458322ebca6SAkhil Goyal rte_eth_dev_socket_id(portid), 1459322ebca6SAkhil Goyal &txq_conf); 1460322ebca6SAkhil Goyal if (ret < 0) 1461322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", 1462322ebca6SAkhil Goyal ret, portid); 1463322ebca6SAkhil Goyal /* >8 End of init one TX queue on each port. */ 1464322ebca6SAkhil Goyal 1465322ebca6SAkhil Goyal /* Initialize TX buffers */ 1466322ebca6SAkhil Goyal tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", 1467322ebca6SAkhil Goyal RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, 1468322ebca6SAkhil Goyal rte_eth_dev_socket_id(portid)); 1469322ebca6SAkhil Goyal if (tx_buffer[portid] == NULL) 1470322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 1471322ebca6SAkhil Goyal portid); 1472322ebca6SAkhil Goyal 1473322ebca6SAkhil Goyal rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); 1474322ebca6SAkhil Goyal 1475322ebca6SAkhil Goyal ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], 1476322ebca6SAkhil Goyal rte_eth_tx_buffer_count_callback, 1477322ebca6SAkhil Goyal &port_statistics[portid].dropped); 1478322ebca6SAkhil Goyal if (ret < 0) 1479322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1480322ebca6SAkhil Goyal "Cannot set error callback for tx buffer on port %u\n", 1481322ebca6SAkhil Goyal portid); 1482322ebca6SAkhil Goyal 1483322ebca6SAkhil Goyal ret = rte_eth_dev_set_ptypes(portid, RTE_PTYPE_UNKNOWN, NULL, 1484322ebca6SAkhil Goyal 0); 1485322ebca6SAkhil Goyal if (ret < 0) 1486322ebca6SAkhil Goyal printf("Port %u, Failed to disable Ptype parsing\n", 1487322ebca6SAkhil Goyal portid); 1488322ebca6SAkhil Goyal /* Start device */ 1489322ebca6SAkhil Goyal ret = rte_eth_dev_start(portid); 1490322ebca6SAkhil Goyal if (ret < 0) 1491322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", 1492322ebca6SAkhil Goyal ret, portid); 1493322ebca6SAkhil Goyal 1494322ebca6SAkhil Goyal printf("done:\n"); 1495322ebca6SAkhil Goyal if (promiscuous_on) { 1496322ebca6SAkhil Goyal ret = rte_eth_promiscuous_enable(portid); 1497322ebca6SAkhil Goyal if (ret != 0) 1498322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1499322ebca6SAkhil Goyal "rte_eth_promiscuous_enable:err=%s, port=%u\n", 1500322ebca6SAkhil Goyal rte_strerror(-ret), portid); 1501322ebca6SAkhil Goyal } 1502322ebca6SAkhil Goyal 1503322ebca6SAkhil Goyal printf("Port %u, MAC address: " RTE_ETHER_ADDR_PRT_FMT "\n\n", 1504322ebca6SAkhil Goyal portid, 1505322ebca6SAkhil Goyal RTE_ETHER_ADDR_BYTES(&l2fwd_ports_eth_addr[portid])); 1506322ebca6SAkhil Goyal 1507322ebca6SAkhil Goyal /* initialize port stats */ 1508322ebca6SAkhil Goyal memset(&port_statistics, 0, sizeof(port_statistics)); 1509322ebca6SAkhil Goyal 1510322ebca6SAkhil Goyal mcs_port_params[portid].sec_ctx = rte_eth_dev_get_sec_ctx(portid); 1511322ebca6SAkhil Goyal if (mcs_port_params[portid].sec_ctx == NULL) 1512322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Device does not support Security ctx\n"); 1513322ebca6SAkhil Goyal 1514322ebca6SAkhil Goyal sess_sz = rte_security_session_get_size(mcs_port_params[portid].sec_ctx); 1515322ebca6SAkhil Goyal if (mcs_port_params[portid].sess_pool == NULL) { 1516322ebca6SAkhil Goyal snprintf(s, sizeof(s), "sess_pool_p%d", portid); 1517322ebca6SAkhil Goyal mcs_port_params[portid].sess_pool = rte_mempool_create(s, 1518322ebca6SAkhil Goyal nb_sess, sess_sz, 1519322ebca6SAkhil Goyal SESSION_POOL_CACHE_SIZE, 0, 1520322ebca6SAkhil Goyal NULL, NULL, NULL, NULL, 1521322ebca6SAkhil Goyal SOCKET_ID_ANY, 0); 1522322ebca6SAkhil Goyal if (mcs_port_params[portid].sess_pool == NULL) 1523322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, "Cannot init sess pool\n"); 1524322ebca6SAkhil Goyal 1525322ebca6SAkhil Goyal printf("Allocated sess pool\n"); 1526322ebca6SAkhil Goyal } 1527322ebca6SAkhil Goyal 1528322ebca6SAkhil Goyal if (((options.tx_portmask & (1 << portid)) != 0) || 1529322ebca6SAkhil Goyal ((options.rx_portmask & (1 << portid)) != 0)) { 1530322ebca6SAkhil Goyal ret = initialize_macsec_session(portid); 1531322ebca6SAkhil Goyal if (ret < 0) 1532322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1533322ebca6SAkhil Goyal "Failed to initialize MACsec session for port: %d\n", 1534322ebca6SAkhil Goyal portid); 1535322ebca6SAkhil Goyal } 1536322ebca6SAkhil Goyal } 1537322ebca6SAkhil Goyal 1538322ebca6SAkhil Goyal if (!nb_ports_available) { 1539322ebca6SAkhil Goyal rte_exit(EXIT_FAILURE, 1540322ebca6SAkhil Goyal "All available ports are disabled. Please set portmask.\n"); 1541322ebca6SAkhil Goyal } 1542322ebca6SAkhil Goyal 1543322ebca6SAkhil Goyal check_all_ports_link_status(l2fwd_enabled_port_mask); 1544322ebca6SAkhil Goyal 1545322ebca6SAkhil Goyal ret = 0; 1546322ebca6SAkhil Goyal /* launch per-lcore init on every lcore */ 1547322ebca6SAkhil Goyal rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MAIN); 1548322ebca6SAkhil Goyal RTE_LCORE_FOREACH_WORKER(lcore_id) { 1549322ebca6SAkhil Goyal if (rte_eal_wait_lcore(lcore_id) < 0) { 1550322ebca6SAkhil Goyal ret = -1; 1551322ebca6SAkhil Goyal break; 1552322ebca6SAkhil Goyal } 1553322ebca6SAkhil Goyal } 1554322ebca6SAkhil Goyal 1555322ebca6SAkhil Goyal RTE_ETH_FOREACH_DEV(portid) { 1556322ebca6SAkhil Goyal if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 1557322ebca6SAkhil Goyal continue; 1558322ebca6SAkhil Goyal printf("Closing port %d...", portid); 1559322ebca6SAkhil Goyal ret = rte_eth_dev_stop(portid); 1560322ebca6SAkhil Goyal if (ret != 0) 1561322ebca6SAkhil Goyal printf("rte_eth_dev_stop: err=%d, port=%d\n", 1562322ebca6SAkhil Goyal ret, portid); 1563322ebca6SAkhil Goyal rte_eth_dev_close(portid); 1564322ebca6SAkhil Goyal printf(" Done\n"); 1565322ebca6SAkhil Goyal } 1566322ebca6SAkhil Goyal 1567322ebca6SAkhil Goyal /* clean up the EAL */ 1568322ebca6SAkhil Goyal rte_eal_cleanup(); 1569322ebca6SAkhil Goyal printf("Bye...\n"); 1570322ebca6SAkhil Goyal 1571322ebca6SAkhil Goyal return ret; 1572322ebca6SAkhil Goyal } 1573