13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2f88e7c17SRadu Nicolau * Copyright(c) 2010-2018 Intel Corporation 3d7937e2eSIntel */ 4d7937e2eSIntel 5d7937e2eSIntel #include <stdio.h> 6d7937e2eSIntel #include <stdlib.h> 7d7937e2eSIntel #include <stdint.h> 8d7937e2eSIntel #include <inttypes.h> 9d7937e2eSIntel #include <sys/types.h> 10d7937e2eSIntel #include <string.h> 11d7937e2eSIntel #include <sys/queue.h> 12d7937e2eSIntel #include <stdarg.h> 13d7937e2eSIntel #include <errno.h> 14d7937e2eSIntel #include <getopt.h> 15d7937e2eSIntel #include <unistd.h> 16d7937e2eSIntel #include <signal.h> 17609e7984SReshma Pattan #include <math.h> 18d7937e2eSIntel 19d7937e2eSIntel #include <rte_common.h> 20d7937e2eSIntel #include <rte_byteorder.h> 21d7937e2eSIntel #include <rte_log.h> 22e2366e74STomasz Kulasek #include <rte_malloc.h> 23d7937e2eSIntel #include <rte_memory.h> 24d7937e2eSIntel #include <rte_memcpy.h> 25d7937e2eSIntel #include <rte_eal.h> 26d7937e2eSIntel #include <rte_launch.h> 27d7937e2eSIntel #include <rte_atomic.h> 28d7937e2eSIntel #include <rte_cycles.h> 29d7937e2eSIntel #include <rte_prefetch.h> 30d7937e2eSIntel #include <rte_lcore.h> 31d7937e2eSIntel #include <rte_per_lcore.h> 32d7937e2eSIntel #include <rte_branch_prediction.h> 33d7937e2eSIntel #include <rte_interrupts.h> 34d7937e2eSIntel #include <rte_random.h> 35d7937e2eSIntel #include <rte_debug.h> 36d7937e2eSIntel #include <rte_ether.h> 37d7937e2eSIntel #include <rte_ethdev.h> 38d7937e2eSIntel #include <rte_mempool.h> 39d7937e2eSIntel #include <rte_mbuf.h> 40d7937e2eSIntel #include <rte_ip.h> 41d7937e2eSIntel #include <rte_tcp.h> 42d7937e2eSIntel #include <rte_udp.h> 43d7937e2eSIntel #include <rte_string_fns.h> 44d7937e2eSIntel #include <rte_timer.h> 45d7937e2eSIntel #include <rte_power.h> 46aee3bc79SCunming Liang #include <rte_spinlock.h> 47a137d012SLiang Ma #include <rte_power_empty_poll.h> 48609e7984SReshma Pattan #include <rte_metrics.h> 49d7937e2eSIntel 50f88e7c17SRadu Nicolau #include "perf_core.h" 51f88e7c17SRadu Nicolau #include "main.h" 52f88e7c17SRadu Nicolau 53d7937e2eSIntel #define RTE_LOGTYPE_L3FWD_POWER RTE_LOGTYPE_USER1 54d7937e2eSIntel 55d7937e2eSIntel #define MAX_PKT_BURST 32 56d7937e2eSIntel 57aee3bc79SCunming Liang #define MIN_ZERO_POLL_COUNT 10 58d7937e2eSIntel 59d7937e2eSIntel /* 100 ms interval */ 60d7937e2eSIntel #define TIMER_NUMBER_PER_SECOND 10 61a137d012SLiang Ma /* (10ms) */ 62a137d012SLiang Ma #define INTERVALS_PER_SECOND 100 63d7937e2eSIntel /* 100000 us */ 64d7937e2eSIntel #define SCALING_PERIOD (1000000/TIMER_NUMBER_PER_SECOND) 65d7937e2eSIntel #define SCALING_DOWN_TIME_RATIO_THRESHOLD 0.25 66d7937e2eSIntel 67d7937e2eSIntel #define APP_LOOKUP_EXACT_MATCH 0 68d7937e2eSIntel #define APP_LOOKUP_LPM 1 69d7937e2eSIntel #define DO_RFC_1812_CHECKS 70d7937e2eSIntel 71d7937e2eSIntel #ifndef APP_LOOKUP_METHOD 72d7937e2eSIntel #define APP_LOOKUP_METHOD APP_LOOKUP_LPM 73d7937e2eSIntel #endif 74d7937e2eSIntel 75d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 76d7937e2eSIntel #include <rte_hash.h> 77d7937e2eSIntel #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 78d7937e2eSIntel #include <rte_lpm.h> 79d7937e2eSIntel #else 80d7937e2eSIntel #error "APP_LOOKUP_METHOD set to incorrect value" 81d7937e2eSIntel #endif 82d7937e2eSIntel 83d7937e2eSIntel #ifndef IPv6_BYTES 84d7937e2eSIntel #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ 85d7937e2eSIntel "%02x%02x:%02x%02x:%02x%02x:%02x%02x" 86d7937e2eSIntel #define IPv6_BYTES(addr) \ 87d7937e2eSIntel addr[0], addr[1], addr[2], addr[3], \ 88d7937e2eSIntel addr[4], addr[5], addr[6], addr[7], \ 89d7937e2eSIntel addr[8], addr[9], addr[10], addr[11],\ 90d7937e2eSIntel addr[12], addr[13],addr[14], addr[15] 91d7937e2eSIntel #endif 92d7937e2eSIntel 93d7937e2eSIntel #define MAX_JUMBO_PKT_LEN 9600 94d7937e2eSIntel 95d7937e2eSIntel #define IPV6_ADDR_LEN 16 96d7937e2eSIntel 97d7937e2eSIntel #define MEMPOOL_CACHE_SIZE 256 98d7937e2eSIntel 99d7937e2eSIntel /* 100d7937e2eSIntel * This expression is used to calculate the number of mbufs needed depending on 101d7937e2eSIntel * user input, taking into account memory for rx and tx hardware rings, cache 102d7937e2eSIntel * per lcore and mtable per port per lcore. RTE_MAX is used to ensure that 103d7937e2eSIntel * NB_MBUF never goes below a minimum value of 8192. 104d7937e2eSIntel */ 105d7937e2eSIntel 106d7937e2eSIntel #define NB_MBUF RTE_MAX ( \ 10760efb44fSRoman Zhukov (nb_ports*nb_rx_queue*nb_rxd + \ 108d7937e2eSIntel nb_ports*nb_lcores*MAX_PKT_BURST + \ 10960efb44fSRoman Zhukov nb_ports*n_tx_queue*nb_txd + \ 110d7937e2eSIntel nb_lcores*MEMPOOL_CACHE_SIZE), \ 111d7937e2eSIntel (unsigned)8192) 112d7937e2eSIntel 113d7937e2eSIntel #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 114d7937e2eSIntel 115d7937e2eSIntel #define NB_SOCKETS 8 116d7937e2eSIntel 117d7937e2eSIntel /* Configure how many packets ahead to prefetch, when reading packets */ 118d7937e2eSIntel #define PREFETCH_OFFSET 3 119d7937e2eSIntel 120d7937e2eSIntel /* 121d7937e2eSIntel * Configurable number of RX/TX ring descriptors 122d7937e2eSIntel */ 123867a6c66SKevin Laatz #define RTE_TEST_RX_DESC_DEFAULT 1024 124867a6c66SKevin Laatz #define RTE_TEST_TX_DESC_DEFAULT 1024 125a137d012SLiang Ma 126a137d012SLiang Ma /* 127a137d012SLiang Ma * These two thresholds were decided on by running the training algorithm on 128a137d012SLiang Ma * a 2.5GHz Xeon. These defaults can be overridden by supplying non-zero values 129a137d012SLiang Ma * for the med_threshold and high_threshold parameters on the command line. 130a137d012SLiang Ma */ 131a137d012SLiang Ma #define EMPTY_POLL_MED_THRESHOLD 350000UL 132a137d012SLiang Ma #define EMPTY_POLL_HGH_THRESHOLD 580000UL 133a137d012SLiang Ma 134a137d012SLiang Ma 135a137d012SLiang Ma 136d7937e2eSIntel static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 137d7937e2eSIntel static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 138d7937e2eSIntel 139d7937e2eSIntel /* ethernet addresses of ports */ 1406d13ea8eSOlivier Matz static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 141d7937e2eSIntel 142aee3bc79SCunming Liang /* ethernet addresses of ports */ 143aee3bc79SCunming Liang static rte_spinlock_t locks[RTE_MAX_ETHPORTS]; 144aee3bc79SCunming Liang 145d7937e2eSIntel /* mask of enabled ports */ 146d7937e2eSIntel static uint32_t enabled_port_mask = 0; 147d7937e2eSIntel /* Ports set in promiscuous mode off by default. */ 148d7937e2eSIntel static int promiscuous_on = 0; 149d7937e2eSIntel /* NUMA is enabled by default. */ 150d7937e2eSIntel static int numa_on = 1; 151609e7984SReshma Pattan static bool empty_poll_stop; 152a137d012SLiang Ma static bool empty_poll_train; 153609e7984SReshma Pattan volatile bool quit_signal; 154a137d012SLiang Ma static struct ep_params *ep_params; 155a137d012SLiang Ma static struct ep_policy policy; 156a137d012SLiang Ma static long ep_med_edpi, ep_hgh_edpi; 157609e7984SReshma Pattan /* timer to update telemetry every 500ms */ 158609e7984SReshma Pattan static struct rte_timer telemetry_timer; 159609e7984SReshma Pattan 160609e7984SReshma Pattan /* stats index returned by metrics lib */ 161609e7984SReshma Pattan int telstats_index; 162609e7984SReshma Pattan 163609e7984SReshma Pattan struct telstats_name { 164609e7984SReshma Pattan char name[RTE_ETH_XSTATS_NAME_SIZE]; 165609e7984SReshma Pattan }; 166609e7984SReshma Pattan 167609e7984SReshma Pattan /* telemetry stats to be reported */ 168609e7984SReshma Pattan const struct telstats_name telstats_strings[] = { 169609e7984SReshma Pattan {"empty_poll"}, 170609e7984SReshma Pattan {"full_poll"}, 171609e7984SReshma Pattan {"busy_percent"} 172609e7984SReshma Pattan }; 173609e7984SReshma Pattan 174609e7984SReshma Pattan /* core busyness in percentage */ 175609e7984SReshma Pattan enum busy_rate { 176609e7984SReshma Pattan ZERO = 0, 177609e7984SReshma Pattan PARTIAL = 50, 178609e7984SReshma Pattan FULL = 100 179609e7984SReshma Pattan }; 180609e7984SReshma Pattan 181609e7984SReshma Pattan /* reference poll count to measure core busyness */ 182609e7984SReshma Pattan #define DEFAULT_COUNT 10000 183609e7984SReshma Pattan /* 184609e7984SReshma Pattan * reference CYCLES to be used to 185609e7984SReshma Pattan * measure core busyness based on poll count 186609e7984SReshma Pattan */ 187609e7984SReshma Pattan #define MIN_CYCLES 1500000ULL 188b55d8fecSDavid Hunt #define MAX_CYCLES 22000000ULL 189609e7984SReshma Pattan 190609e7984SReshma Pattan /* (500ms) */ 191609e7984SReshma Pattan #define TELEMETRY_INTERVALS_PER_SEC 2 192a137d012SLiang Ma 19382bea466SJianfeng Tan static int parse_ptype; /**< Parse packet type using rx callback, and */ 19482bea466SJianfeng Tan /**< disabled by default */ 195d7937e2eSIntel 196609e7984SReshma Pattan enum appmode { 197609e7984SReshma Pattan APP_MODE_LEGACY = 0, 198609e7984SReshma Pattan APP_MODE_EMPTY_POLL, 199609e7984SReshma Pattan APP_MODE_TELEMETRY 200609e7984SReshma Pattan }; 201609e7984SReshma Pattan 202609e7984SReshma Pattan enum appmode app_mode; 203609e7984SReshma Pattan 204d7937e2eSIntel enum freq_scale_hint_t 205d7937e2eSIntel { 206d7937e2eSIntel FREQ_LOWER = -1, 207d7937e2eSIntel FREQ_CURRENT = 0, 208d7937e2eSIntel FREQ_HIGHER = 1, 209d7937e2eSIntel FREQ_HIGHEST = 2 210d7937e2eSIntel }; 211d7937e2eSIntel 212d7937e2eSIntel struct lcore_rx_queue { 213f8244c63SZhiyong Yang uint16_t port_id; 214d7937e2eSIntel uint8_t queue_id; 215d7937e2eSIntel enum freq_scale_hint_t freq_up_hint; 216d7937e2eSIntel uint32_t zero_rx_packet_count; 217d7937e2eSIntel uint32_t idle_hint; 218d7937e2eSIntel } __rte_cache_aligned; 219d7937e2eSIntel 220d7937e2eSIntel #define MAX_RX_QUEUE_PER_LCORE 16 221d7937e2eSIntel #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 222d7937e2eSIntel #define MAX_RX_QUEUE_PER_PORT 128 223d7937e2eSIntel 224aee3bc79SCunming Liang #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16 225aee3bc79SCunming Liang 226aee3bc79SCunming Liang 227f88e7c17SRadu Nicolau struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 228d7937e2eSIntel static struct lcore_params lcore_params_array_default[] = { 229d7937e2eSIntel {0, 0, 2}, 230d7937e2eSIntel {0, 1, 2}, 231d7937e2eSIntel {0, 2, 2}, 232d7937e2eSIntel {1, 0, 2}, 233d7937e2eSIntel {1, 1, 2}, 234d7937e2eSIntel {1, 2, 2}, 235d7937e2eSIntel {2, 0, 2}, 236d7937e2eSIntel {3, 0, 3}, 237d7937e2eSIntel {3, 1, 3}, 238d7937e2eSIntel }; 239d7937e2eSIntel 240f88e7c17SRadu Nicolau struct lcore_params *lcore_params = lcore_params_array_default; 241f88e7c17SRadu Nicolau uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / 242d7937e2eSIntel sizeof(lcore_params_array_default[0]); 243d7937e2eSIntel 244d7937e2eSIntel static struct rte_eth_conf port_conf = { 245d7937e2eSIntel .rxmode = { 24613c4ebd6SBruce Richardson .mq_mode = ETH_MQ_RX_RSS, 24735b2d13fSOlivier Matz .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 248d7937e2eSIntel .split_hdr_size = 0, 249323e7b66SFerruh Yigit .offloads = DEV_RX_OFFLOAD_CHECKSUM, 250d7937e2eSIntel }, 251d7937e2eSIntel .rx_adv_conf = { 252d7937e2eSIntel .rss_conf = { 253d7937e2eSIntel .rss_key = NULL, 254aee3bc79SCunming Liang .rss_hf = ETH_RSS_UDP, 255d7937e2eSIntel }, 256d7937e2eSIntel }, 257d7937e2eSIntel .txmode = { 258aee3bc79SCunming Liang .mq_mode = ETH_MQ_TX_NONE, 259aee3bc79SCunming Liang }, 260aee3bc79SCunming Liang .intr_conf = { 261aee3bc79SCunming Liang .rxq = 1, 262d7937e2eSIntel }, 263d7937e2eSIntel }; 264d7937e2eSIntel 265d7937e2eSIntel static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; 266d7937e2eSIntel 267d7937e2eSIntel 268d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 269d7937e2eSIntel 270193f9ec5SBruce Richardson #ifdef RTE_ARCH_X86 271d7937e2eSIntel #include <rte_hash_crc.h> 272d7937e2eSIntel #define DEFAULT_HASH_FUNC rte_hash_crc 273d7937e2eSIntel #else 274d7937e2eSIntel #include <rte_jhash.h> 275d7937e2eSIntel #define DEFAULT_HASH_FUNC rte_jhash 276d7937e2eSIntel #endif 277d7937e2eSIntel 278d7937e2eSIntel struct ipv4_5tuple { 279d7937e2eSIntel uint32_t ip_dst; 280d7937e2eSIntel uint32_t ip_src; 281d7937e2eSIntel uint16_t port_dst; 282d7937e2eSIntel uint16_t port_src; 283d7937e2eSIntel uint8_t proto; 284d7937e2eSIntel } __attribute__((__packed__)); 285d7937e2eSIntel 286d7937e2eSIntel struct ipv6_5tuple { 287d7937e2eSIntel uint8_t ip_dst[IPV6_ADDR_LEN]; 288d7937e2eSIntel uint8_t ip_src[IPV6_ADDR_LEN]; 289d7937e2eSIntel uint16_t port_dst; 290d7937e2eSIntel uint16_t port_src; 291d7937e2eSIntel uint8_t proto; 292d7937e2eSIntel } __attribute__((__packed__)); 293d7937e2eSIntel 294d7937e2eSIntel struct ipv4_l3fwd_route { 295d7937e2eSIntel struct ipv4_5tuple key; 296d7937e2eSIntel uint8_t if_out; 297d7937e2eSIntel }; 298d7937e2eSIntel 299d7937e2eSIntel struct ipv6_l3fwd_route { 300d7937e2eSIntel struct ipv6_5tuple key; 301d7937e2eSIntel uint8_t if_out; 302d7937e2eSIntel }; 303d7937e2eSIntel 304d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { 3050c9da755SDavid Marchand {{RTE_IPV4(100,10,0,1), RTE_IPV4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0}, 3060c9da755SDavid Marchand {{RTE_IPV4(100,20,0,2), RTE_IPV4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1}, 3070c9da755SDavid Marchand {{RTE_IPV4(100,30,0,3), RTE_IPV4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2}, 3080c9da755SDavid Marchand {{RTE_IPV4(100,40,0,4), RTE_IPV4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3}, 309d7937e2eSIntel }; 310d7937e2eSIntel 311d7937e2eSIntel static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { 312d7937e2eSIntel { 313d7937e2eSIntel { 314d7937e2eSIntel {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 315d7937e2eSIntel 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 316d7937e2eSIntel {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317d7937e2eSIntel 0x02, 0x1e, 0x67, 0xff, 0xfe, 0x0d, 0xb6, 0x0a}, 318d7937e2eSIntel 1, 10, IPPROTO_UDP 319d7937e2eSIntel }, 4 320d7937e2eSIntel }, 321d7937e2eSIntel }; 322d7937e2eSIntel 323d7937e2eSIntel typedef struct rte_hash lookup_struct_t; 324d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; 325d7937e2eSIntel static lookup_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; 326d7937e2eSIntel 327d7937e2eSIntel #define L3FWD_HASH_ENTRIES 1024 328d7937e2eSIntel 329d7937e2eSIntel #define IPV4_L3FWD_NUM_ROUTES \ 330d7937e2eSIntel (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) 331d7937e2eSIntel 332d7937e2eSIntel #define IPV6_L3FWD_NUM_ROUTES \ 333d7937e2eSIntel (sizeof(ipv6_l3fwd_route_array) / sizeof(ipv6_l3fwd_route_array[0])) 334d7937e2eSIntel 335f8244c63SZhiyong Yang static uint16_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; 336f8244c63SZhiyong Yang static uint16_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; 337d7937e2eSIntel #endif 338d7937e2eSIntel 339d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 340d7937e2eSIntel struct ipv4_l3fwd_route { 341d7937e2eSIntel uint32_t ip; 342d7937e2eSIntel uint8_t depth; 343d7937e2eSIntel uint8_t if_out; 344d7937e2eSIntel }; 345d7937e2eSIntel 346d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { 3470c9da755SDavid Marchand {RTE_IPV4(1,1,1,0), 24, 0}, 3480c9da755SDavid Marchand {RTE_IPV4(2,1,1,0), 24, 1}, 3490c9da755SDavid Marchand {RTE_IPV4(3,1,1,0), 24, 2}, 3500c9da755SDavid Marchand {RTE_IPV4(4,1,1,0), 24, 3}, 3510c9da755SDavid Marchand {RTE_IPV4(5,1,1,0), 24, 4}, 3520c9da755SDavid Marchand {RTE_IPV4(6,1,1,0), 24, 5}, 3530c9da755SDavid Marchand {RTE_IPV4(7,1,1,0), 24, 6}, 3540c9da755SDavid Marchand {RTE_IPV4(8,1,1,0), 24, 7}, 355d7937e2eSIntel }; 356d7937e2eSIntel 357d7937e2eSIntel #define IPV4_L3FWD_NUM_ROUTES \ 358d7937e2eSIntel (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) 359d7937e2eSIntel 360d7937e2eSIntel #define IPV4_L3FWD_LPM_MAX_RULES 1024 361d7937e2eSIntel 362d7937e2eSIntel typedef struct rte_lpm lookup_struct_t; 363d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; 364d7937e2eSIntel #endif 365d7937e2eSIntel 366d7937e2eSIntel struct lcore_conf { 367d7937e2eSIntel uint16_t n_rx_queue; 368d7937e2eSIntel struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 369e2366e74STomasz Kulasek uint16_t n_tx_port; 370e2366e74STomasz Kulasek uint16_t tx_port_id[RTE_MAX_ETHPORTS]; 371d7937e2eSIntel uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 372e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 373d7937e2eSIntel lookup_struct_t * ipv4_lookup_struct; 374d7937e2eSIntel lookup_struct_t * ipv6_lookup_struct; 375d7937e2eSIntel } __rte_cache_aligned; 376d7937e2eSIntel 377d7937e2eSIntel struct lcore_stats { 378d7937e2eSIntel /* total sleep time in ms since last frequency scaling down */ 379d7937e2eSIntel uint32_t sleep_time; 380d7937e2eSIntel /* number of long sleep recently */ 381d7937e2eSIntel uint32_t nb_long_sleep; 382d7937e2eSIntel /* freq. scaling up trend */ 383d7937e2eSIntel uint32_t trend; 384d7937e2eSIntel /* total packet processed recently */ 385d7937e2eSIntel uint64_t nb_rx_processed; 386d7937e2eSIntel /* total iterations looped recently */ 387d7937e2eSIntel uint64_t nb_iteration_looped; 388609e7984SReshma Pattan /* 389609e7984SReshma Pattan * Represents empty and non empty polls 390609e7984SReshma Pattan * of rte_eth_rx_burst(); 391609e7984SReshma Pattan * ep_nep[0] holds non empty polls 392609e7984SReshma Pattan * i.e. 0 < nb_rx <= MAX_BURST 393609e7984SReshma Pattan * ep_nep[1] holds empty polls. 394609e7984SReshma Pattan * i.e. nb_rx == 0 395609e7984SReshma Pattan */ 396609e7984SReshma Pattan uint64_t ep_nep[2]; 397609e7984SReshma Pattan /* 398609e7984SReshma Pattan * Represents full and empty+partial 399609e7984SReshma Pattan * polls of rte_eth_rx_burst(); 400609e7984SReshma Pattan * ep_nep[0] holds empty+partial polls. 401609e7984SReshma Pattan * i.e. 0 <= nb_rx < MAX_BURST 402609e7984SReshma Pattan * ep_nep[1] holds full polls 403609e7984SReshma Pattan * i.e. nb_rx == MAX_BURST 404609e7984SReshma Pattan */ 405609e7984SReshma Pattan uint64_t fp_nfp[2]; 406609e7984SReshma Pattan enum busy_rate br; 407609e7984SReshma Pattan rte_spinlock_t telemetry_lock; 408d7937e2eSIntel } __rte_cache_aligned; 409d7937e2eSIntel 410d7937e2eSIntel static struct lcore_conf lcore_conf[RTE_MAX_LCORE] __rte_cache_aligned; 411d7937e2eSIntel static struct lcore_stats stats[RTE_MAX_LCORE] __rte_cache_aligned; 412d7937e2eSIntel static struct rte_timer power_timers[RTE_MAX_LCORE]; 413d7937e2eSIntel 414d7937e2eSIntel static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count); 415d7937e2eSIntel static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \ 416f8244c63SZhiyong Yang unsigned int lcore_id, uint16_t port_id, uint16_t queue_id); 417d7937e2eSIntel 418a137d012SLiang Ma 419a137d012SLiang Ma /* 420a137d012SLiang Ma * These defaults are using the max frequency index (1), a medium index (9) 421a137d012SLiang Ma * and a typical low frequency index (14). These can be adjusted to use 422a137d012SLiang Ma * different indexes using the relevant command line parameters. 423a137d012SLiang Ma */ 424a137d012SLiang Ma static uint8_t freq_tlb[] = {14, 9, 1}; 425a137d012SLiang Ma 426a137d012SLiang Ma static int is_done(void) 427a137d012SLiang Ma { 428609e7984SReshma Pattan return quit_signal; 429a137d012SLiang Ma } 430a137d012SLiang Ma 431d7937e2eSIntel /* exit signal handler */ 432d7937e2eSIntel static void 433d7937e2eSIntel signal_exit_now(int sigtype) 434d7937e2eSIntel { 435d7937e2eSIntel unsigned lcore_id; 4368728ccf3SThomas Monjalon unsigned int portid; 437d7937e2eSIntel int ret; 438d7937e2eSIntel 439d7937e2eSIntel if (sigtype == SIGINT) { 440609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL || 441609e7984SReshma Pattan app_mode == APP_MODE_TELEMETRY) 442609e7984SReshma Pattan quit_signal = true; 443a137d012SLiang Ma 444a137d012SLiang Ma 445d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 446d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 447d7937e2eSIntel continue; 448d7937e2eSIntel 449d7937e2eSIntel /* init power management library */ 450d7937e2eSIntel ret = rte_power_exit(lcore_id); 451d7937e2eSIntel if (ret) 452d7937e2eSIntel rte_exit(EXIT_FAILURE, "Power management " 453d7937e2eSIntel "library de-initialization failed on " 454d7937e2eSIntel "core%u\n", lcore_id); 455d7937e2eSIntel } 456e2a6f124SJianfeng Tan 457609e7984SReshma Pattan if (app_mode != APP_MODE_EMPTY_POLL) { 4588728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 459e2a6f124SJianfeng Tan if ((enabled_port_mask & (1 << portid)) == 0) 460e2a6f124SJianfeng Tan continue; 461e2a6f124SJianfeng Tan 462e2a6f124SJianfeng Tan rte_eth_dev_stop(portid); 463e2a6f124SJianfeng Tan rte_eth_dev_close(portid); 464e2a6f124SJianfeng Tan } 465d7937e2eSIntel } 466a137d012SLiang Ma } 467d7937e2eSIntel 468609e7984SReshma Pattan if (app_mode != APP_MODE_EMPTY_POLL) 469d7937e2eSIntel rte_exit(EXIT_SUCCESS, "User forced exit\n"); 470d7937e2eSIntel } 471d7937e2eSIntel 472d7937e2eSIntel /* Freqency scale down timer callback */ 473d7937e2eSIntel static void 474d7937e2eSIntel power_timer_cb(__attribute__((unused)) struct rte_timer *tim, 475d7937e2eSIntel __attribute__((unused)) void *arg) 476d7937e2eSIntel { 477d7937e2eSIntel uint64_t hz; 478d7937e2eSIntel float sleep_time_ratio; 479d7937e2eSIntel unsigned lcore_id = rte_lcore_id(); 480d7937e2eSIntel 481d7937e2eSIntel /* accumulate total execution time in us when callback is invoked */ 482d7937e2eSIntel sleep_time_ratio = (float)(stats[lcore_id].sleep_time) / 483d7937e2eSIntel (float)SCALING_PERIOD; 484d7937e2eSIntel /** 485d7937e2eSIntel * check whether need to scale down frequency a step if it sleep a lot. 486d7937e2eSIntel */ 487aee3bc79SCunming Liang if (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) { 488aee3bc79SCunming Liang if (rte_power_freq_down) 489d7937e2eSIntel rte_power_freq_down(lcore_id); 490aee3bc79SCunming Liang } 491d7937e2eSIntel else if ( (unsigned)(stats[lcore_id].nb_rx_processed / 492aee3bc79SCunming Liang stats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) { 493d7937e2eSIntel /** 494d7937e2eSIntel * scale down a step if average packet per iteration less 495d7937e2eSIntel * than expectation. 496d7937e2eSIntel */ 497aee3bc79SCunming Liang if (rte_power_freq_down) 498d7937e2eSIntel rte_power_freq_down(lcore_id); 499aee3bc79SCunming Liang } 500d7937e2eSIntel 501d7937e2eSIntel /** 502d7937e2eSIntel * initialize another timer according to current frequency to ensure 503d7937e2eSIntel * timer interval is relatively fixed. 504d7937e2eSIntel */ 505d7937e2eSIntel hz = rte_get_timer_hz(); 506d7937e2eSIntel rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, 507d7937e2eSIntel SINGLE, lcore_id, power_timer_cb, NULL); 508d7937e2eSIntel 509d7937e2eSIntel stats[lcore_id].nb_rx_processed = 0; 510d7937e2eSIntel stats[lcore_id].nb_iteration_looped = 0; 511d7937e2eSIntel 512d7937e2eSIntel stats[lcore_id].sleep_time = 0; 513d7937e2eSIntel } 514d7937e2eSIntel 515d7937e2eSIntel /* Enqueue a single packet, and send burst if queue is filled */ 516d7937e2eSIntel static inline int 51747523597SZhiyong Yang send_single_packet(struct rte_mbuf *m, uint16_t port) 518d7937e2eSIntel { 519d7937e2eSIntel uint32_t lcore_id; 520d7937e2eSIntel struct lcore_conf *qconf; 521d7937e2eSIntel 522d7937e2eSIntel lcore_id = rte_lcore_id(); 523d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 524d7937e2eSIntel 525e2366e74STomasz Kulasek rte_eth_tx_buffer(port, qconf->tx_queue_id[port], 526e2366e74STomasz Kulasek qconf->tx_buffer[port], m); 527d7937e2eSIntel 528d7937e2eSIntel return 0; 529d7937e2eSIntel } 530d7937e2eSIntel 531d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 532d7937e2eSIntel static inline int 533a7c528e5SOlivier Matz is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len) 534d7937e2eSIntel { 535d7937e2eSIntel /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ 536d7937e2eSIntel /* 537d7937e2eSIntel * 1. The packet length reported by the Link Layer must be large 538d7937e2eSIntel * enough to hold the minimum length legal IP datagram (20 bytes). 539d7937e2eSIntel */ 540a7c528e5SOlivier Matz if (link_len < sizeof(struct rte_ipv4_hdr)) 541d7937e2eSIntel return -1; 542d7937e2eSIntel 543d7937e2eSIntel /* 2. The IP checksum must be correct. */ 544d7937e2eSIntel /* this is checked in H/W */ 545d7937e2eSIntel 546d7937e2eSIntel /* 547d7937e2eSIntel * 3. The IP version number must be 4. If the version number is not 4 548d7937e2eSIntel * then the packet may be another version of IP, such as IPng or 549d7937e2eSIntel * ST-II. 550d7937e2eSIntel */ 551d7937e2eSIntel if (((pkt->version_ihl) >> 4) != 4) 552d7937e2eSIntel return -3; 553d7937e2eSIntel /* 554d7937e2eSIntel * 4. The IP header length field must be large enough to hold the 555d7937e2eSIntel * minimum length legal IP datagram (20 bytes = 5 words). 556d7937e2eSIntel */ 557d7937e2eSIntel if ((pkt->version_ihl & 0xf) < 5) 558d7937e2eSIntel return -4; 559d7937e2eSIntel 560d7937e2eSIntel /* 561d7937e2eSIntel * 5. The IP total length field must be large enough to hold the IP 562d7937e2eSIntel * datagram header, whose length is specified in the IP header length 563d7937e2eSIntel * field. 564d7937e2eSIntel */ 565a7c528e5SOlivier Matz if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) 566d7937e2eSIntel return -5; 567d7937e2eSIntel 568d7937e2eSIntel return 0; 569d7937e2eSIntel } 570d7937e2eSIntel #endif 571d7937e2eSIntel 572d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 573d7937e2eSIntel static void 574d7937e2eSIntel print_ipv4_key(struct ipv4_5tuple key) 575d7937e2eSIntel { 576d7937e2eSIntel printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, " 577d7937e2eSIntel "proto = %d\n", (unsigned)key.ip_dst, (unsigned)key.ip_src, 578d7937e2eSIntel key.port_dst, key.port_src, key.proto); 579d7937e2eSIntel } 580d7937e2eSIntel static void 581d7937e2eSIntel print_ipv6_key(struct ipv6_5tuple key) 582d7937e2eSIntel { 583d7937e2eSIntel printf( "IP dst = " IPv6_BYTES_FMT ", IP src = " IPv6_BYTES_FMT ", " 584d7937e2eSIntel "port dst = %d, port src = %d, proto = %d\n", 585d7937e2eSIntel IPv6_BYTES(key.ip_dst), IPv6_BYTES(key.ip_src), 586d7937e2eSIntel key.port_dst, key.port_src, key.proto); 587d7937e2eSIntel } 588d7937e2eSIntel 589f8244c63SZhiyong Yang static inline uint16_t 590a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, 591d7937e2eSIntel lookup_struct_t * ipv4_l3fwd_lookup_struct) 592d7937e2eSIntel { 593d7937e2eSIntel struct ipv4_5tuple key; 594f41b5156SOlivier Matz struct rte_tcp_hdr *tcp; 595e73e3547SOlivier Matz struct rte_udp_hdr *udp; 596d7937e2eSIntel int ret = 0; 597d7937e2eSIntel 598d7937e2eSIntel key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); 599d7937e2eSIntel key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr); 600d7937e2eSIntel key.proto = ipv4_hdr->next_proto_id; 601d7937e2eSIntel 602d7937e2eSIntel switch (ipv4_hdr->next_proto_id) { 603d7937e2eSIntel case IPPROTO_TCP: 604f41b5156SOlivier Matz tcp = (struct rte_tcp_hdr *)((unsigned char *)ipv4_hdr + 605a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr)); 606d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(tcp->dst_port); 607d7937e2eSIntel key.port_src = rte_be_to_cpu_16(tcp->src_port); 608d7937e2eSIntel break; 609d7937e2eSIntel 610d7937e2eSIntel case IPPROTO_UDP: 611e73e3547SOlivier Matz udp = (struct rte_udp_hdr *)((unsigned char *)ipv4_hdr + 612a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr)); 613d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(udp->dst_port); 614d7937e2eSIntel key.port_src = rte_be_to_cpu_16(udp->src_port); 615d7937e2eSIntel break; 616d7937e2eSIntel 617d7937e2eSIntel default: 618d7937e2eSIntel key.port_dst = 0; 619d7937e2eSIntel key.port_src = 0; 620d7937e2eSIntel break; 621d7937e2eSIntel } 622d7937e2eSIntel 623d7937e2eSIntel /* Find destination port */ 624d7937e2eSIntel ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key); 625f8244c63SZhiyong Yang return ((ret < 0) ? portid : ipv4_l3fwd_out_if[ret]); 626d7937e2eSIntel } 627d7937e2eSIntel 628f8244c63SZhiyong Yang static inline uint16_t 629a7c528e5SOlivier Matz get_ipv6_dst_port(struct rte_ipv6_hdr *ipv6_hdr, uint16_t portid, 630d7937e2eSIntel lookup_struct_t *ipv6_l3fwd_lookup_struct) 631d7937e2eSIntel { 632d7937e2eSIntel struct ipv6_5tuple key; 633f41b5156SOlivier Matz struct rte_tcp_hdr *tcp; 634e73e3547SOlivier Matz struct rte_udp_hdr *udp; 635d7937e2eSIntel int ret = 0; 636d7937e2eSIntel 637d7937e2eSIntel memcpy(key.ip_dst, ipv6_hdr->dst_addr, IPV6_ADDR_LEN); 638d7937e2eSIntel memcpy(key.ip_src, ipv6_hdr->src_addr, IPV6_ADDR_LEN); 639d7937e2eSIntel 640d7937e2eSIntel key.proto = ipv6_hdr->proto; 641d7937e2eSIntel 642d7937e2eSIntel switch (ipv6_hdr->proto) { 643d7937e2eSIntel case IPPROTO_TCP: 644f41b5156SOlivier Matz tcp = (struct rte_tcp_hdr *)((unsigned char *) ipv6_hdr + 645a7c528e5SOlivier Matz sizeof(struct rte_ipv6_hdr)); 646d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(tcp->dst_port); 647d7937e2eSIntel key.port_src = rte_be_to_cpu_16(tcp->src_port); 648d7937e2eSIntel break; 649d7937e2eSIntel 650d7937e2eSIntel case IPPROTO_UDP: 651e73e3547SOlivier Matz udp = (struct rte_udp_hdr *)((unsigned char *) ipv6_hdr + 652a7c528e5SOlivier Matz sizeof(struct rte_ipv6_hdr)); 653d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(udp->dst_port); 654d7937e2eSIntel key.port_src = rte_be_to_cpu_16(udp->src_port); 655d7937e2eSIntel break; 656d7937e2eSIntel 657d7937e2eSIntel default: 658d7937e2eSIntel key.port_dst = 0; 659d7937e2eSIntel key.port_src = 0; 660d7937e2eSIntel break; 661d7937e2eSIntel } 662d7937e2eSIntel 663d7937e2eSIntel /* Find destination port */ 664d7937e2eSIntel ret = rte_hash_lookup(ipv6_l3fwd_lookup_struct, (const void *)&key); 665f8244c63SZhiyong Yang return ((ret < 0) ? portid : ipv6_l3fwd_out_if[ret]); 666d7937e2eSIntel } 667d7937e2eSIntel #endif 668d7937e2eSIntel 669d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 670f8244c63SZhiyong Yang static inline uint16_t 671a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, 672d7937e2eSIntel lookup_struct_t *ipv4_l3fwd_lookup_struct) 673d7937e2eSIntel { 674dc81ebbaSMichal Kobylinski uint32_t next_hop; 675d7937e2eSIntel 676f8244c63SZhiyong Yang return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, 677d7937e2eSIntel rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? 678d7937e2eSIntel next_hop : portid); 679d7937e2eSIntel } 680d7937e2eSIntel #endif 681d7937e2eSIntel 682d7937e2eSIntel static inline void 68382bea466SJianfeng Tan parse_ptype_one(struct rte_mbuf *m) 68482bea466SJianfeng Tan { 6856d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 68682bea466SJianfeng Tan uint32_t packet_type = RTE_PTYPE_UNKNOWN; 68782bea466SJianfeng Tan uint16_t ether_type; 68882bea466SJianfeng Tan 6896d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 69082bea466SJianfeng Tan ether_type = eth_hdr->ether_type; 6910c9da755SDavid Marchand if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) 69282bea466SJianfeng Tan packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN; 6930c9da755SDavid Marchand else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) 69482bea466SJianfeng Tan packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; 69582bea466SJianfeng Tan 69682bea466SJianfeng Tan m->packet_type = packet_type; 69782bea466SJianfeng Tan } 69882bea466SJianfeng Tan 69982bea466SJianfeng Tan static uint16_t 700f8244c63SZhiyong Yang cb_parse_ptype(uint16_t port __rte_unused, uint16_t queue __rte_unused, 70182bea466SJianfeng Tan struct rte_mbuf *pkts[], uint16_t nb_pkts, 70282bea466SJianfeng Tan uint16_t max_pkts __rte_unused, 70382bea466SJianfeng Tan void *user_param __rte_unused) 70482bea466SJianfeng Tan { 70582bea466SJianfeng Tan unsigned int i; 70682bea466SJianfeng Tan 70782bea466SJianfeng Tan for (i = 0; i < nb_pkts; ++i) 70882bea466SJianfeng Tan parse_ptype_one(pkts[i]); 70982bea466SJianfeng Tan 71082bea466SJianfeng Tan return nb_pkts; 71182bea466SJianfeng Tan } 71282bea466SJianfeng Tan 71382bea466SJianfeng Tan static int 714f8244c63SZhiyong Yang add_cb_parse_ptype(uint16_t portid, uint16_t queueid) 71582bea466SJianfeng Tan { 71682bea466SJianfeng Tan printf("Port %d: softly parse packet type info\n", portid); 71782bea466SJianfeng Tan if (rte_eth_add_rx_callback(portid, queueid, cb_parse_ptype, NULL)) 71882bea466SJianfeng Tan return 0; 71982bea466SJianfeng Tan 72082bea466SJianfeng Tan printf("Failed to add rx callback: port=%d\n", portid); 72182bea466SJianfeng Tan return -1; 72282bea466SJianfeng Tan } 72382bea466SJianfeng Tan 72482bea466SJianfeng Tan static inline void 72547523597SZhiyong Yang l3fwd_simple_forward(struct rte_mbuf *m, uint16_t portid, 726d7937e2eSIntel struct lcore_conf *qconf) 727d7937e2eSIntel { 7286d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 729a7c528e5SOlivier Matz struct rte_ipv4_hdr *ipv4_hdr; 730d7937e2eSIntel void *d_addr_bytes; 731f8244c63SZhiyong Yang uint16_t dst_port; 732d7937e2eSIntel 7336d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 734d7937e2eSIntel 7353c0184ccSHelin Zhang if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { 736d7937e2eSIntel /* Handle IPv4 headers.*/ 737d7937e2eSIntel ipv4_hdr = 738a7c528e5SOlivier Matz rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, 7396d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr)); 740d7937e2eSIntel 741d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 742d7937e2eSIntel /* Check to make sure the packet is valid (RFC1812) */ 743ea672a8bSOlivier Matz if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { 744d7937e2eSIntel rte_pktmbuf_free(m); 745d7937e2eSIntel return; 746d7937e2eSIntel } 747d7937e2eSIntel #endif 748d7937e2eSIntel 749d7937e2eSIntel dst_port = get_ipv4_dst_port(ipv4_hdr, portid, 750d7937e2eSIntel qconf->ipv4_lookup_struct); 751d7937e2eSIntel if (dst_port >= RTE_MAX_ETHPORTS || 752d7937e2eSIntel (enabled_port_mask & 1 << dst_port) == 0) 753d7937e2eSIntel dst_port = portid; 754d7937e2eSIntel 755d7937e2eSIntel /* 02:00:00:00:00:xx */ 756d7937e2eSIntel d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; 757d7937e2eSIntel *((uint64_t *)d_addr_bytes) = 758d7937e2eSIntel 0x000000000002 + ((uint64_t)dst_port << 40); 759d7937e2eSIntel 760d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 761d7937e2eSIntel /* Update time to live and header checksum */ 762d7937e2eSIntel --(ipv4_hdr->time_to_live); 763d7937e2eSIntel ++(ipv4_hdr->hdr_checksum); 764d7937e2eSIntel #endif 765d7937e2eSIntel 766d7937e2eSIntel /* src addr */ 767538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port], 768538da7a1SOlivier Matz ð_hdr->s_addr); 769d7937e2eSIntel 770d7937e2eSIntel send_single_packet(m, dst_port); 7713c0184ccSHelin Zhang } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { 772d7937e2eSIntel /* Handle IPv6 headers.*/ 773d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 774a7c528e5SOlivier Matz struct rte_ipv6_hdr *ipv6_hdr; 775d7937e2eSIntel 776d7937e2eSIntel ipv6_hdr = 777a7c528e5SOlivier Matz rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, 7786d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr)); 779d7937e2eSIntel 780d7937e2eSIntel dst_port = get_ipv6_dst_port(ipv6_hdr, portid, 781d7937e2eSIntel qconf->ipv6_lookup_struct); 782d7937e2eSIntel 783d7937e2eSIntel if (dst_port >= RTE_MAX_ETHPORTS || 784d7937e2eSIntel (enabled_port_mask & 1 << dst_port) == 0) 785d7937e2eSIntel dst_port = portid; 786d7937e2eSIntel 787d7937e2eSIntel /* 02:00:00:00:00:xx */ 788d7937e2eSIntel d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; 789d7937e2eSIntel *((uint64_t *)d_addr_bytes) = 790d7937e2eSIntel 0x000000000002 + ((uint64_t)dst_port << 40); 791d7937e2eSIntel 792d7937e2eSIntel /* src addr */ 793538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port], 794538da7a1SOlivier Matz ð_hdr->s_addr); 795d7937e2eSIntel 796d7937e2eSIntel send_single_packet(m, dst_port); 797d7937e2eSIntel #else 798d7937e2eSIntel /* We don't currently handle IPv6 packets in LPM mode. */ 799d7937e2eSIntel rte_pktmbuf_free(m); 800d7937e2eSIntel #endif 801bec2f7dfSShaopeng He } else 802bec2f7dfSShaopeng He rte_pktmbuf_free(m); 803d7937e2eSIntel 804d7937e2eSIntel } 805d7937e2eSIntel 806aee3bc79SCunming Liang #define MINIMUM_SLEEP_TIME 1 807aee3bc79SCunming Liang #define SUSPEND_THRESHOLD 300 808d7937e2eSIntel 809d7937e2eSIntel static inline uint32_t 810d7937e2eSIntel power_idle_heuristic(uint32_t zero_rx_packet_count) 811d7937e2eSIntel { 812aee3bc79SCunming Liang /* If zero count is less than 100, sleep 1us */ 813aee3bc79SCunming Liang if (zero_rx_packet_count < SUSPEND_THRESHOLD) 814aee3bc79SCunming Liang return MINIMUM_SLEEP_TIME; 815aee3bc79SCunming Liang /* If zero count is less than 1000, sleep 100 us which is the 816aee3bc79SCunming Liang minimum latency switching from C3/C6 to C0 817aee3bc79SCunming Liang */ 818aee3bc79SCunming Liang else 819aee3bc79SCunming Liang return SUSPEND_THRESHOLD; 820d7937e2eSIntel } 821d7937e2eSIntel 822d7937e2eSIntel static inline enum freq_scale_hint_t 823b451aa39SIntel power_freq_scaleup_heuristic(unsigned lcore_id, 824f8244c63SZhiyong Yang uint16_t port_id, 825b451aa39SIntel uint16_t queue_id) 826d7937e2eSIntel { 82747d834baSNikhil Agarwal uint32_t rxq_count = rte_eth_rx_queue_count(port_id, queue_id); 828d7937e2eSIntel /** 829d7937e2eSIntel * HW Rx queue size is 128 by default, Rx burst read at maximum 32 entries 830d7937e2eSIntel * per iteration 831d7937e2eSIntel */ 832d7937e2eSIntel #define FREQ_GEAR1_RX_PACKET_THRESHOLD MAX_PKT_BURST 833b451aa39SIntel #define FREQ_GEAR2_RX_PACKET_THRESHOLD (MAX_PKT_BURST*2) 834b451aa39SIntel #define FREQ_GEAR3_RX_PACKET_THRESHOLD (MAX_PKT_BURST*3) 835d7937e2eSIntel #define FREQ_UP_TREND1_ACC 1 836d7937e2eSIntel #define FREQ_UP_TREND2_ACC 100 837d7937e2eSIntel #define FREQ_UP_THRESHOLD 10000 838d7937e2eSIntel 83947d834baSNikhil Agarwal if (likely(rxq_count > FREQ_GEAR3_RX_PACKET_THRESHOLD)) { 840d7937e2eSIntel stats[lcore_id].trend = 0; 841d7937e2eSIntel return FREQ_HIGHEST; 84247d834baSNikhil Agarwal } else if (likely(rxq_count > FREQ_GEAR2_RX_PACKET_THRESHOLD)) 843d7937e2eSIntel stats[lcore_id].trend += FREQ_UP_TREND2_ACC; 84447d834baSNikhil Agarwal else if (likely(rxq_count > FREQ_GEAR1_RX_PACKET_THRESHOLD)) 845d7937e2eSIntel stats[lcore_id].trend += FREQ_UP_TREND1_ACC; 846d7937e2eSIntel 847b451aa39SIntel if (likely(stats[lcore_id].trend > FREQ_UP_THRESHOLD)) { 848d7937e2eSIntel stats[lcore_id].trend = 0; 849d7937e2eSIntel return FREQ_HIGHER; 850d7937e2eSIntel } 851d7937e2eSIntel 852d7937e2eSIntel return FREQ_CURRENT; 853d7937e2eSIntel } 854d7937e2eSIntel 855aee3bc79SCunming Liang /** 856aee3bc79SCunming Liang * force polling thread sleep until one-shot rx interrupt triggers 857aee3bc79SCunming Liang * @param port_id 858aee3bc79SCunming Liang * Port id. 859aee3bc79SCunming Liang * @param queue_id 860aee3bc79SCunming Liang * Rx queue id. 861aee3bc79SCunming Liang * @return 862aee3bc79SCunming Liang * 0 on success 863aee3bc79SCunming Liang */ 864aee3bc79SCunming Liang static int 865aee3bc79SCunming Liang sleep_until_rx_interrupt(int num) 866aee3bc79SCunming Liang { 867aee3bc79SCunming Liang struct rte_epoll_event event[num]; 868aee3bc79SCunming Liang int n, i; 869f8244c63SZhiyong Yang uint16_t port_id; 870f8244c63SZhiyong Yang uint8_t queue_id; 871aee3bc79SCunming Liang void *data; 872aee3bc79SCunming Liang 873aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, 874aee3bc79SCunming Liang "lcore %u sleeps until interrupt triggers\n", 875aee3bc79SCunming Liang rte_lcore_id()); 876aee3bc79SCunming Liang 877aee3bc79SCunming Liang n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, -1); 878aee3bc79SCunming Liang for (i = 0; i < n; i++) { 879aee3bc79SCunming Liang data = event[i].epdata.data; 880aee3bc79SCunming Liang port_id = ((uintptr_t)data) >> CHAR_BIT; 881aee3bc79SCunming Liang queue_id = ((uintptr_t)data) & 882aee3bc79SCunming Liang RTE_LEN2MASK(CHAR_BIT, uint8_t); 883b736d647SYong Liu rte_eth_dev_rx_intr_disable(port_id, queue_id); 884aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, 885aee3bc79SCunming Liang "lcore %u is waked up from rx interrupt on" 886aee3bc79SCunming Liang " port %d queue %d\n", 887aee3bc79SCunming Liang rte_lcore_id(), port_id, queue_id); 888aee3bc79SCunming Liang } 889aee3bc79SCunming Liang 890aee3bc79SCunming Liang return 0; 891aee3bc79SCunming Liang } 892aee3bc79SCunming Liang 893aee3bc79SCunming Liang static void turn_on_intr(struct lcore_conf *qconf) 894aee3bc79SCunming Liang { 895aee3bc79SCunming Liang int i; 896aee3bc79SCunming Liang struct lcore_rx_queue *rx_queue; 897f8244c63SZhiyong Yang uint8_t queue_id; 898f8244c63SZhiyong Yang uint16_t port_id; 899aee3bc79SCunming Liang 900aee3bc79SCunming Liang for (i = 0; i < qconf->n_rx_queue; ++i) { 901aee3bc79SCunming Liang rx_queue = &(qconf->rx_queue_list[i]); 902aee3bc79SCunming Liang port_id = rx_queue->port_id; 903aee3bc79SCunming Liang queue_id = rx_queue->queue_id; 904aee3bc79SCunming Liang 905aee3bc79SCunming Liang rte_spinlock_lock(&(locks[port_id])); 906aee3bc79SCunming Liang rte_eth_dev_rx_intr_enable(port_id, queue_id); 907aee3bc79SCunming Liang rte_spinlock_unlock(&(locks[port_id])); 908aee3bc79SCunming Liang } 909aee3bc79SCunming Liang } 910aee3bc79SCunming Liang 911aee3bc79SCunming Liang static int event_register(struct lcore_conf *qconf) 912aee3bc79SCunming Liang { 913aee3bc79SCunming Liang struct lcore_rx_queue *rx_queue; 914f8244c63SZhiyong Yang uint8_t queueid; 915f8244c63SZhiyong Yang uint16_t portid; 916aee3bc79SCunming Liang uint32_t data; 917aee3bc79SCunming Liang int ret; 918aee3bc79SCunming Liang int i; 919aee3bc79SCunming Liang 920aee3bc79SCunming Liang for (i = 0; i < qconf->n_rx_queue; ++i) { 921aee3bc79SCunming Liang rx_queue = &(qconf->rx_queue_list[i]); 922aee3bc79SCunming Liang portid = rx_queue->port_id; 923aee3bc79SCunming Liang queueid = rx_queue->queue_id; 924aee3bc79SCunming Liang data = portid << CHAR_BIT | queueid; 925aee3bc79SCunming Liang 926aee3bc79SCunming Liang ret = rte_eth_dev_rx_intr_ctl_q(portid, queueid, 927aee3bc79SCunming Liang RTE_EPOLL_PER_THREAD, 928aee3bc79SCunming Liang RTE_INTR_EVENT_ADD, 929aee3bc79SCunming Liang (void *)((uintptr_t)data)); 930aee3bc79SCunming Liang if (ret) 931aee3bc79SCunming Liang return ret; 932aee3bc79SCunming Liang } 933aee3bc79SCunming Liang 934aee3bc79SCunming Liang return 0; 935aee3bc79SCunming Liang } 936a137d012SLiang Ma /* main processing loop */ 937a137d012SLiang Ma static int 938609e7984SReshma Pattan main_telemetry_loop(__attribute__((unused)) void *dummy) 939609e7984SReshma Pattan { 940609e7984SReshma Pattan struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 941609e7984SReshma Pattan unsigned int lcore_id; 942609e7984SReshma Pattan uint64_t prev_tsc, diff_tsc, cur_tsc, prev_tel_tsc; 943609e7984SReshma Pattan int i, j, nb_rx; 944609e7984SReshma Pattan uint8_t queueid; 945609e7984SReshma Pattan uint16_t portid; 946609e7984SReshma Pattan struct lcore_conf *qconf; 947609e7984SReshma Pattan struct lcore_rx_queue *rx_queue; 948609e7984SReshma Pattan uint64_t ep_nep[2] = {0}, fp_nfp[2] = {0}; 949609e7984SReshma Pattan uint64_t poll_count; 950609e7984SReshma Pattan enum busy_rate br; 951609e7984SReshma Pattan 952609e7984SReshma Pattan const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / 953609e7984SReshma Pattan US_PER_S * BURST_TX_DRAIN_US; 954609e7984SReshma Pattan 955609e7984SReshma Pattan poll_count = 0; 956609e7984SReshma Pattan prev_tsc = 0; 957609e7984SReshma Pattan prev_tel_tsc = 0; 958609e7984SReshma Pattan 959609e7984SReshma Pattan lcore_id = rte_lcore_id(); 960609e7984SReshma Pattan qconf = &lcore_conf[lcore_id]; 961609e7984SReshma Pattan 962609e7984SReshma Pattan if (qconf->n_rx_queue == 0) { 963609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", 964609e7984SReshma Pattan lcore_id); 965609e7984SReshma Pattan return 0; 966609e7984SReshma Pattan } 967609e7984SReshma Pattan 968609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, "entering main telemetry loop on lcore %u\n", 969609e7984SReshma Pattan lcore_id); 970609e7984SReshma Pattan 971609e7984SReshma Pattan for (i = 0; i < qconf->n_rx_queue; i++) { 972609e7984SReshma Pattan portid = qconf->rx_queue_list[i].port_id; 973609e7984SReshma Pattan queueid = qconf->rx_queue_list[i].queue_id; 974609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " 975609e7984SReshma Pattan "rxqueueid=%hhu\n", lcore_id, portid, queueid); 976609e7984SReshma Pattan } 977609e7984SReshma Pattan 978609e7984SReshma Pattan while (!is_done()) { 979609e7984SReshma Pattan 980609e7984SReshma Pattan cur_tsc = rte_rdtsc(); 981609e7984SReshma Pattan /* 982609e7984SReshma Pattan * TX burst queue drain 983609e7984SReshma Pattan */ 984609e7984SReshma Pattan diff_tsc = cur_tsc - prev_tsc; 985609e7984SReshma Pattan if (unlikely(diff_tsc > drain_tsc)) { 986609e7984SReshma Pattan for (i = 0; i < qconf->n_tx_port; ++i) { 987609e7984SReshma Pattan portid = qconf->tx_port_id[i]; 988609e7984SReshma Pattan rte_eth_tx_buffer_flush(portid, 989609e7984SReshma Pattan qconf->tx_queue_id[portid], 990609e7984SReshma Pattan qconf->tx_buffer[portid]); 991609e7984SReshma Pattan } 992609e7984SReshma Pattan prev_tsc = cur_tsc; 993609e7984SReshma Pattan } 994609e7984SReshma Pattan 995609e7984SReshma Pattan /* 996609e7984SReshma Pattan * Read packet from RX queues 997609e7984SReshma Pattan */ 998609e7984SReshma Pattan for (i = 0; i < qconf->n_rx_queue; ++i) { 999609e7984SReshma Pattan rx_queue = &(qconf->rx_queue_list[i]); 1000609e7984SReshma Pattan portid = rx_queue->port_id; 1001609e7984SReshma Pattan queueid = rx_queue->queue_id; 1002609e7984SReshma Pattan 1003609e7984SReshma Pattan nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 1004609e7984SReshma Pattan MAX_PKT_BURST); 1005609e7984SReshma Pattan ep_nep[nb_rx == 0]++; 1006609e7984SReshma Pattan fp_nfp[nb_rx == MAX_PKT_BURST]++; 1007609e7984SReshma Pattan poll_count++; 1008609e7984SReshma Pattan if (unlikely(nb_rx == 0)) 1009609e7984SReshma Pattan continue; 1010609e7984SReshma Pattan 1011609e7984SReshma Pattan /* Prefetch first packets */ 1012609e7984SReshma Pattan for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1013609e7984SReshma Pattan rte_prefetch0(rte_pktmbuf_mtod( 1014609e7984SReshma Pattan pkts_burst[j], void *)); 1015609e7984SReshma Pattan } 1016609e7984SReshma Pattan 1017609e7984SReshma Pattan /* Prefetch and forward already prefetched packets */ 1018609e7984SReshma Pattan for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1019609e7984SReshma Pattan rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1020609e7984SReshma Pattan j + PREFETCH_OFFSET], void *)); 1021609e7984SReshma Pattan l3fwd_simple_forward(pkts_burst[j], portid, 1022609e7984SReshma Pattan qconf); 1023609e7984SReshma Pattan } 1024609e7984SReshma Pattan 1025609e7984SReshma Pattan /* Forward remaining prefetched packets */ 1026609e7984SReshma Pattan for (; j < nb_rx; j++) { 1027609e7984SReshma Pattan l3fwd_simple_forward(pkts_burst[j], portid, 1028609e7984SReshma Pattan qconf); 1029609e7984SReshma Pattan } 1030609e7984SReshma Pattan } 1031609e7984SReshma Pattan if (unlikely(poll_count >= DEFAULT_COUNT)) { 1032609e7984SReshma Pattan diff_tsc = cur_tsc - prev_tel_tsc; 1033609e7984SReshma Pattan if (diff_tsc >= MAX_CYCLES) { 1034609e7984SReshma Pattan br = FULL; 1035609e7984SReshma Pattan } else if (diff_tsc > MIN_CYCLES && 1036609e7984SReshma Pattan diff_tsc < MAX_CYCLES) { 1037b55d8fecSDavid Hunt br = (diff_tsc * 100) / MAX_CYCLES; 1038609e7984SReshma Pattan } else { 1039609e7984SReshma Pattan br = ZERO; 1040609e7984SReshma Pattan } 1041609e7984SReshma Pattan poll_count = 0; 1042609e7984SReshma Pattan prev_tel_tsc = cur_tsc; 1043609e7984SReshma Pattan /* update stats for telemetry */ 1044609e7984SReshma Pattan rte_spinlock_lock(&stats[lcore_id].telemetry_lock); 1045609e7984SReshma Pattan stats[lcore_id].ep_nep[0] = ep_nep[0]; 1046609e7984SReshma Pattan stats[lcore_id].ep_nep[1] = ep_nep[1]; 1047609e7984SReshma Pattan stats[lcore_id].fp_nfp[0] = fp_nfp[0]; 1048609e7984SReshma Pattan stats[lcore_id].fp_nfp[1] = fp_nfp[1]; 1049609e7984SReshma Pattan stats[lcore_id].br = br; 1050609e7984SReshma Pattan rte_spinlock_unlock(&stats[lcore_id].telemetry_lock); 1051609e7984SReshma Pattan } 1052609e7984SReshma Pattan } 1053609e7984SReshma Pattan 1054609e7984SReshma Pattan return 0; 1055609e7984SReshma Pattan } 1056609e7984SReshma Pattan /* main processing loop */ 1057609e7984SReshma Pattan static int 1058a137d012SLiang Ma main_empty_poll_loop(__attribute__((unused)) void *dummy) 1059a137d012SLiang Ma { 1060a137d012SLiang Ma struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1061a137d012SLiang Ma unsigned int lcore_id; 1062a137d012SLiang Ma uint64_t prev_tsc, diff_tsc, cur_tsc; 1063a137d012SLiang Ma int i, j, nb_rx; 1064a137d012SLiang Ma uint8_t queueid; 1065a137d012SLiang Ma uint16_t portid; 1066a137d012SLiang Ma struct lcore_conf *qconf; 1067a137d012SLiang Ma struct lcore_rx_queue *rx_queue; 1068aee3bc79SCunming Liang 1069a137d012SLiang Ma const uint64_t drain_tsc = 1070a137d012SLiang Ma (rte_get_tsc_hz() + US_PER_S - 1) / 1071a137d012SLiang Ma US_PER_S * BURST_TX_DRAIN_US; 1072a137d012SLiang Ma 1073a137d012SLiang Ma prev_tsc = 0; 1074a137d012SLiang Ma 1075a137d012SLiang Ma lcore_id = rte_lcore_id(); 1076a137d012SLiang Ma qconf = &lcore_conf[lcore_id]; 1077a137d012SLiang Ma 1078a137d012SLiang Ma if (qconf->n_rx_queue == 0) { 1079a137d012SLiang Ma RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", 1080a137d012SLiang Ma lcore_id); 1081a137d012SLiang Ma return 0; 1082a137d012SLiang Ma } 1083a137d012SLiang Ma 1084a137d012SLiang Ma for (i = 0; i < qconf->n_rx_queue; i++) { 1085a137d012SLiang Ma portid = qconf->rx_queue_list[i].port_id; 1086a137d012SLiang Ma queueid = qconf->rx_queue_list[i].queue_id; 1087a137d012SLiang Ma RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " 1088a137d012SLiang Ma "rxqueueid=%hhu\n", lcore_id, portid, queueid); 1089a137d012SLiang Ma } 1090a137d012SLiang Ma 1091a137d012SLiang Ma while (!is_done()) { 1092a137d012SLiang Ma stats[lcore_id].nb_iteration_looped++; 1093a137d012SLiang Ma 1094a137d012SLiang Ma cur_tsc = rte_rdtsc(); 1095a137d012SLiang Ma /* 1096a137d012SLiang Ma * TX burst queue drain 1097a137d012SLiang Ma */ 1098a137d012SLiang Ma diff_tsc = cur_tsc - prev_tsc; 1099a137d012SLiang Ma if (unlikely(diff_tsc > drain_tsc)) { 1100a137d012SLiang Ma for (i = 0; i < qconf->n_tx_port; ++i) { 1101a137d012SLiang Ma portid = qconf->tx_port_id[i]; 1102a137d012SLiang Ma rte_eth_tx_buffer_flush(portid, 1103a137d012SLiang Ma qconf->tx_queue_id[portid], 1104a137d012SLiang Ma qconf->tx_buffer[portid]); 1105a137d012SLiang Ma } 1106a137d012SLiang Ma prev_tsc = cur_tsc; 1107a137d012SLiang Ma } 1108a137d012SLiang Ma 1109a137d012SLiang Ma /* 1110a137d012SLiang Ma * Read packet from RX queues 1111a137d012SLiang Ma */ 1112a137d012SLiang Ma for (i = 0; i < qconf->n_rx_queue; ++i) { 1113a137d012SLiang Ma rx_queue = &(qconf->rx_queue_list[i]); 1114a137d012SLiang Ma rx_queue->idle_hint = 0; 1115a137d012SLiang Ma portid = rx_queue->port_id; 1116a137d012SLiang Ma queueid = rx_queue->queue_id; 1117a137d012SLiang Ma 1118a137d012SLiang Ma nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 1119a137d012SLiang Ma MAX_PKT_BURST); 1120a137d012SLiang Ma 1121a137d012SLiang Ma stats[lcore_id].nb_rx_processed += nb_rx; 1122a137d012SLiang Ma 1123a137d012SLiang Ma if (nb_rx == 0) { 1124a137d012SLiang Ma 1125a137d012SLiang Ma rte_power_empty_poll_stat_update(lcore_id); 1126a137d012SLiang Ma 1127a137d012SLiang Ma continue; 1128a137d012SLiang Ma } else { 1129a137d012SLiang Ma rte_power_poll_stat_update(lcore_id, nb_rx); 1130a137d012SLiang Ma } 1131a137d012SLiang Ma 1132a137d012SLiang Ma 1133a137d012SLiang Ma /* Prefetch first packets */ 1134a137d012SLiang Ma for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1135a137d012SLiang Ma rte_prefetch0(rte_pktmbuf_mtod( 1136a137d012SLiang Ma pkts_burst[j], void *)); 1137a137d012SLiang Ma } 1138a137d012SLiang Ma 1139a137d012SLiang Ma /* Prefetch and forward already prefetched packets */ 1140a137d012SLiang Ma for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1141a137d012SLiang Ma rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1142a137d012SLiang Ma j + PREFETCH_OFFSET], 1143a137d012SLiang Ma void *)); 1144a137d012SLiang Ma l3fwd_simple_forward(pkts_burst[j], portid, 1145a137d012SLiang Ma qconf); 1146a137d012SLiang Ma } 1147a137d012SLiang Ma 1148a137d012SLiang Ma /* Forward remaining prefetched packets */ 1149a137d012SLiang Ma for (; j < nb_rx; j++) { 1150a137d012SLiang Ma l3fwd_simple_forward(pkts_burst[j], portid, 1151a137d012SLiang Ma qconf); 1152a137d012SLiang Ma } 1153a137d012SLiang Ma 1154a137d012SLiang Ma } 1155a137d012SLiang Ma 1156a137d012SLiang Ma } 1157a137d012SLiang Ma 1158a137d012SLiang Ma return 0; 1159a137d012SLiang Ma } 1160d7937e2eSIntel /* main processing loop */ 1161d7937e2eSIntel static int 1162d7937e2eSIntel main_loop(__attribute__((unused)) void *dummy) 1163d7937e2eSIntel { 1164d7937e2eSIntel struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1165d7937e2eSIntel unsigned lcore_id; 116663de7e6eSNikhil Agarwal uint64_t prev_tsc, diff_tsc, cur_tsc, tim_res_tsc, hz; 1167d7937e2eSIntel uint64_t prev_tsc_power = 0, cur_tsc_power, diff_tsc_power; 1168d7937e2eSIntel int i, j, nb_rx; 1169f8244c63SZhiyong Yang uint8_t queueid; 1170f8244c63SZhiyong Yang uint16_t portid; 1171d7937e2eSIntel struct lcore_conf *qconf; 1172d7937e2eSIntel struct lcore_rx_queue *rx_queue; 1173d7937e2eSIntel enum freq_scale_hint_t lcore_scaleup_hint; 1174d7937e2eSIntel uint32_t lcore_rx_idle_count = 0; 1175d7937e2eSIntel uint32_t lcore_idle_hint = 0; 1176aee3bc79SCunming Liang int intr_en = 0; 1177d7937e2eSIntel 1178d7937e2eSIntel const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; 1179d7937e2eSIntel 1180d7937e2eSIntel prev_tsc = 0; 118163de7e6eSNikhil Agarwal hz = rte_get_timer_hz(); 118263de7e6eSNikhil Agarwal tim_res_tsc = hz/TIMER_NUMBER_PER_SECOND; 1183d7937e2eSIntel 1184d7937e2eSIntel lcore_id = rte_lcore_id(); 1185d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 1186d7937e2eSIntel 1187d7937e2eSIntel if (qconf->n_rx_queue == 0) { 1188d7937e2eSIntel RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", lcore_id); 1189d7937e2eSIntel return 0; 1190d7937e2eSIntel } 1191d7937e2eSIntel 1192d7937e2eSIntel RTE_LOG(INFO, L3FWD_POWER, "entering main loop on lcore %u\n", lcore_id); 1193d7937e2eSIntel 1194d7937e2eSIntel for (i = 0; i < qconf->n_rx_queue; i++) { 1195d7937e2eSIntel portid = qconf->rx_queue_list[i].port_id; 1196d7937e2eSIntel queueid = qconf->rx_queue_list[i].queue_id; 1197f8244c63SZhiyong Yang RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " 1198d7937e2eSIntel "rxqueueid=%hhu\n", lcore_id, portid, queueid); 1199d7937e2eSIntel } 1200d7937e2eSIntel 1201aee3bc79SCunming Liang /* add into event wait list */ 1202aee3bc79SCunming Liang if (event_register(qconf) == 0) 1203aee3bc79SCunming Liang intr_en = 1; 1204aee3bc79SCunming Liang else 1205aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n"); 1206aee3bc79SCunming Liang 1207d7937e2eSIntel while (1) { 1208d7937e2eSIntel stats[lcore_id].nb_iteration_looped++; 1209d7937e2eSIntel 1210d7937e2eSIntel cur_tsc = rte_rdtsc(); 1211d7937e2eSIntel cur_tsc_power = cur_tsc; 1212d7937e2eSIntel 1213d7937e2eSIntel /* 1214d7937e2eSIntel * TX burst queue drain 1215d7937e2eSIntel */ 1216d7937e2eSIntel diff_tsc = cur_tsc - prev_tsc; 1217d7937e2eSIntel if (unlikely(diff_tsc > drain_tsc)) { 1218e2366e74STomasz Kulasek for (i = 0; i < qconf->n_tx_port; ++i) { 1219e2366e74STomasz Kulasek portid = qconf->tx_port_id[i]; 1220e2366e74STomasz Kulasek rte_eth_tx_buffer_flush(portid, 1221e2366e74STomasz Kulasek qconf->tx_queue_id[portid], 1222e2366e74STomasz Kulasek qconf->tx_buffer[portid]); 1223d7937e2eSIntel } 1224d7937e2eSIntel prev_tsc = cur_tsc; 1225d7937e2eSIntel } 1226d7937e2eSIntel 1227d7937e2eSIntel diff_tsc_power = cur_tsc_power - prev_tsc_power; 122863de7e6eSNikhil Agarwal if (diff_tsc_power > tim_res_tsc) { 1229d7937e2eSIntel rte_timer_manage(); 1230d7937e2eSIntel prev_tsc_power = cur_tsc_power; 1231d7937e2eSIntel } 1232d7937e2eSIntel 1233aee3bc79SCunming Liang start_rx: 1234d7937e2eSIntel /* 1235d7937e2eSIntel * Read packet from RX queues 1236d7937e2eSIntel */ 1237d7937e2eSIntel lcore_scaleup_hint = FREQ_CURRENT; 1238d7937e2eSIntel lcore_rx_idle_count = 0; 1239d7937e2eSIntel for (i = 0; i < qconf->n_rx_queue; ++i) { 1240d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1241d7937e2eSIntel rx_queue->idle_hint = 0; 1242d7937e2eSIntel portid = rx_queue->port_id; 1243d7937e2eSIntel queueid = rx_queue->queue_id; 1244d7937e2eSIntel 1245d7937e2eSIntel nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 1246d7937e2eSIntel MAX_PKT_BURST); 1247aee3bc79SCunming Liang 1248d7937e2eSIntel stats[lcore_id].nb_rx_processed += nb_rx; 1249d7937e2eSIntel if (unlikely(nb_rx == 0)) { 1250d7937e2eSIntel /** 1251d7937e2eSIntel * no packet received from rx queue, try to 1252d7937e2eSIntel * sleep for a while forcing CPU enter deeper 1253d7937e2eSIntel * C states. 1254d7937e2eSIntel */ 1255d7937e2eSIntel rx_queue->zero_rx_packet_count++; 1256d7937e2eSIntel 1257d7937e2eSIntel if (rx_queue->zero_rx_packet_count <= 1258d7937e2eSIntel MIN_ZERO_POLL_COUNT) 1259d7937e2eSIntel continue; 1260d7937e2eSIntel 1261d7937e2eSIntel rx_queue->idle_hint = power_idle_heuristic(\ 1262d7937e2eSIntel rx_queue->zero_rx_packet_count); 1263d7937e2eSIntel lcore_rx_idle_count++; 1264d7937e2eSIntel } else { 1265d7937e2eSIntel rx_queue->zero_rx_packet_count = 0; 1266d7937e2eSIntel 1267d7937e2eSIntel /** 1268d7937e2eSIntel * do not scale up frequency immediately as 1269d7937e2eSIntel * user to kernel space communication is costly 1270d7937e2eSIntel * which might impact packet I/O for received 1271d7937e2eSIntel * packets. 1272d7937e2eSIntel */ 1273d7937e2eSIntel rx_queue->freq_up_hint = 1274d7937e2eSIntel power_freq_scaleup_heuristic(lcore_id, 1275b451aa39SIntel portid, queueid); 1276d7937e2eSIntel } 1277d7937e2eSIntel 1278d7937e2eSIntel /* Prefetch first packets */ 1279d7937e2eSIntel for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1280d7937e2eSIntel rte_prefetch0(rte_pktmbuf_mtod( 1281d7937e2eSIntel pkts_burst[j], void *)); 1282d7937e2eSIntel } 1283d7937e2eSIntel 1284d7937e2eSIntel /* Prefetch and forward already prefetched packets */ 1285d7937e2eSIntel for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1286d7937e2eSIntel rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1287d7937e2eSIntel j + PREFETCH_OFFSET], void *)); 1288d7937e2eSIntel l3fwd_simple_forward(pkts_burst[j], portid, 1289d7937e2eSIntel qconf); 1290d7937e2eSIntel } 1291d7937e2eSIntel 1292d7937e2eSIntel /* Forward remaining prefetched packets */ 1293d7937e2eSIntel for (; j < nb_rx; j++) { 1294d7937e2eSIntel l3fwd_simple_forward(pkts_burst[j], portid, 1295d7937e2eSIntel qconf); 1296d7937e2eSIntel } 1297d7937e2eSIntel } 1298d7937e2eSIntel 1299d7937e2eSIntel if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) { 1300d7937e2eSIntel for (i = 1, lcore_scaleup_hint = 1301d7937e2eSIntel qconf->rx_queue_list[0].freq_up_hint; 1302d7937e2eSIntel i < qconf->n_rx_queue; ++i) { 1303d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1304d7937e2eSIntel if (rx_queue->freq_up_hint > 1305d7937e2eSIntel lcore_scaleup_hint) 1306d7937e2eSIntel lcore_scaleup_hint = 1307d7937e2eSIntel rx_queue->freq_up_hint; 1308d7937e2eSIntel } 1309d7937e2eSIntel 1310aee3bc79SCunming Liang if (lcore_scaleup_hint == FREQ_HIGHEST) { 1311aee3bc79SCunming Liang if (rte_power_freq_max) 1312d7937e2eSIntel rte_power_freq_max(lcore_id); 1313aee3bc79SCunming Liang } else if (lcore_scaleup_hint == FREQ_HIGHER) { 1314aee3bc79SCunming Liang if (rte_power_freq_up) 1315d7937e2eSIntel rte_power_freq_up(lcore_id); 1316aee3bc79SCunming Liang } 1317d7937e2eSIntel } else { 1318d7937e2eSIntel /** 1319d7937e2eSIntel * All Rx queues empty in recent consecutive polls, 1320d7937e2eSIntel * sleep in a conservative manner, meaning sleep as 1321d7937e2eSIntel * less as possible. 1322d7937e2eSIntel */ 1323d7937e2eSIntel for (i = 1, lcore_idle_hint = 1324d7937e2eSIntel qconf->rx_queue_list[0].idle_hint; 1325d7937e2eSIntel i < qconf->n_rx_queue; ++i) { 1326d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1327d7937e2eSIntel if (rx_queue->idle_hint < lcore_idle_hint) 1328d7937e2eSIntel lcore_idle_hint = rx_queue->idle_hint; 1329d7937e2eSIntel } 1330d7937e2eSIntel 1331aee3bc79SCunming Liang if (lcore_idle_hint < SUSPEND_THRESHOLD) 1332d7937e2eSIntel /** 1333d7937e2eSIntel * execute "pause" instruction to avoid context 1334aee3bc79SCunming Liang * switch which generally take hundred of 1335aee3bc79SCunming Liang * microseconds for short sleep. 1336d7937e2eSIntel */ 1337d7937e2eSIntel rte_delay_us(lcore_idle_hint); 1338aee3bc79SCunming Liang else { 1339aee3bc79SCunming Liang /* suspend until rx interrupt trigges */ 1340aee3bc79SCunming Liang if (intr_en) { 1341aee3bc79SCunming Liang turn_on_intr(qconf); 1342aee3bc79SCunming Liang sleep_until_rx_interrupt( 1343aee3bc79SCunming Liang qconf->n_rx_queue); 13444ffc0a88SNikhil Agarwal /** 13454ffc0a88SNikhil Agarwal * start receiving packets immediately 13464ffc0a88SNikhil Agarwal */ 1347aee3bc79SCunming Liang goto start_rx; 1348aee3bc79SCunming Liang } 13494ffc0a88SNikhil Agarwal } 1350d7937e2eSIntel stats[lcore_id].sleep_time += lcore_idle_hint; 1351d7937e2eSIntel } 1352d7937e2eSIntel } 1353d7937e2eSIntel } 1354d7937e2eSIntel 1355d7937e2eSIntel static int 1356d7937e2eSIntel check_lcore_params(void) 1357d7937e2eSIntel { 1358d7937e2eSIntel uint8_t queue, lcore; 1359d7937e2eSIntel uint16_t i; 1360d7937e2eSIntel int socketid; 1361d7937e2eSIntel 1362d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1363d7937e2eSIntel queue = lcore_params[i].queue_id; 1364d7937e2eSIntel if (queue >= MAX_RX_QUEUE_PER_PORT) { 1365d7937e2eSIntel printf("invalid queue number: %hhu\n", queue); 1366d7937e2eSIntel return -1; 1367d7937e2eSIntel } 1368d7937e2eSIntel lcore = lcore_params[i].lcore_id; 1369d7937e2eSIntel if (!rte_lcore_is_enabled(lcore)) { 1370d7937e2eSIntel printf("error: lcore %hhu is not enabled in lcore " 1371d7937e2eSIntel "mask\n", lcore); 1372d7937e2eSIntel return -1; 1373d7937e2eSIntel } 1374d7937e2eSIntel if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && 1375d7937e2eSIntel (numa_on == 0)) { 1376d7937e2eSIntel printf("warning: lcore %hhu is on socket %d with numa " 1377d7937e2eSIntel "off\n", lcore, socketid); 1378d7937e2eSIntel } 1379609e7984SReshma Pattan if (app_mode == APP_MODE_TELEMETRY && lcore == rte_lcore_id()) { 1380609e7984SReshma Pattan printf("cannot enable master core %d in config for telemetry mode\n", 1381609e7984SReshma Pattan rte_lcore_id()); 1382609e7984SReshma Pattan return -1; 1383609e7984SReshma Pattan } 1384d7937e2eSIntel } 1385d7937e2eSIntel return 0; 1386d7937e2eSIntel } 1387d7937e2eSIntel 1388d7937e2eSIntel static int 1389a9dbe180SThomas Monjalon check_port_config(void) 1390d7937e2eSIntel { 1391d7937e2eSIntel unsigned portid; 1392d7937e2eSIntel uint16_t i; 1393d7937e2eSIntel 1394d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1395d7937e2eSIntel portid = lcore_params[i].port_id; 1396d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 1397d7937e2eSIntel printf("port %u is not enabled in port mask\n", 1398d7937e2eSIntel portid); 1399d7937e2eSIntel return -1; 1400d7937e2eSIntel } 1401a9dbe180SThomas Monjalon if (!rte_eth_dev_is_valid_port(portid)) { 1402d7937e2eSIntel printf("port %u is not present on the board\n", 1403d7937e2eSIntel portid); 1404d7937e2eSIntel return -1; 1405d7937e2eSIntel } 1406d7937e2eSIntel } 1407d7937e2eSIntel return 0; 1408d7937e2eSIntel } 1409d7937e2eSIntel 1410d7937e2eSIntel static uint8_t 141147523597SZhiyong Yang get_port_n_rx_queues(const uint16_t port) 1412d7937e2eSIntel { 1413d7937e2eSIntel int queue = -1; 1414d7937e2eSIntel uint16_t i; 1415d7937e2eSIntel 1416d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1417d7937e2eSIntel if (lcore_params[i].port_id == port && 1418d7937e2eSIntel lcore_params[i].queue_id > queue) 1419d7937e2eSIntel queue = lcore_params[i].queue_id; 1420d7937e2eSIntel } 1421d7937e2eSIntel return (uint8_t)(++queue); 1422d7937e2eSIntel } 1423d7937e2eSIntel 1424d7937e2eSIntel static int 1425d7937e2eSIntel init_lcore_rx_queues(void) 1426d7937e2eSIntel { 1427d7937e2eSIntel uint16_t i, nb_rx_queue; 1428d7937e2eSIntel uint8_t lcore; 1429d7937e2eSIntel 1430d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1431d7937e2eSIntel lcore = lcore_params[i].lcore_id; 1432d7937e2eSIntel nb_rx_queue = lcore_conf[lcore].n_rx_queue; 1433d7937e2eSIntel if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 1434d7937e2eSIntel printf("error: too many queues (%u) for lcore: %u\n", 1435d7937e2eSIntel (unsigned)nb_rx_queue + 1, (unsigned)lcore); 1436d7937e2eSIntel return -1; 1437d7937e2eSIntel } else { 1438d7937e2eSIntel lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 1439d7937e2eSIntel lcore_params[i].port_id; 1440d7937e2eSIntel lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 1441d7937e2eSIntel lcore_params[i].queue_id; 1442d7937e2eSIntel lcore_conf[lcore].n_rx_queue++; 1443d7937e2eSIntel } 1444d7937e2eSIntel } 1445d7937e2eSIntel return 0; 1446d7937e2eSIntel } 1447d7937e2eSIntel 1448d7937e2eSIntel /* display usage */ 1449d7937e2eSIntel static void 1450d7937e2eSIntel print_usage(const char *prgname) 1451d7937e2eSIntel { 1452d7937e2eSIntel printf ("%s [EAL options] -- -p PORTMASK -P" 1453d7937e2eSIntel " [--config (port,queue,lcore)[,(port,queue,lcore]]" 1454f88e7c17SRadu Nicolau " [--high-perf-cores CORELIST" 1455f88e7c17SRadu Nicolau " [--perf-config (port,queue,hi_perf,lcore_index)[,(port,queue,hi_perf,lcore_index]]" 1456d7937e2eSIntel " [--enable-jumbo [--max-pkt-len PKTLEN]]\n" 1457d7937e2eSIntel " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 1458d7937e2eSIntel " -P : enable promiscuous mode\n" 1459d7937e2eSIntel " --config (port,queue,lcore): rx queues configuration\n" 1460f88e7c17SRadu Nicolau " --high-perf-cores CORELIST: list of high performance cores\n" 1461f88e7c17SRadu Nicolau " --perf-config: similar as config, cores specified as indices" 1462f88e7c17SRadu Nicolau " for bins containing high or regular performance cores\n" 1463d7937e2eSIntel " --no-numa: optional, disable numa awareness\n" 1464d7937e2eSIntel " --enable-jumbo: enable jumbo frame" 146582bea466SJianfeng Tan " which max packet len is PKTLEN in decimal (64-9600)\n" 1466a137d012SLiang Ma " --parse-ptype: parse packet type by software\n" 1467a137d012SLiang Ma " --empty-poll: enable empty poll detection" 1468609e7984SReshma Pattan " follow (training_flag, high_threshold, med_threshold)\n" 1469609e7984SReshma Pattan " --telemetry: enable telemetry mode, to update" 1470609e7984SReshma Pattan " empty polls, full polls, and core busyness to telemetry\n", 1471d7937e2eSIntel prgname); 1472d7937e2eSIntel } 1473d7937e2eSIntel 1474d7937e2eSIntel static int parse_max_pkt_len(const char *pktlen) 1475d7937e2eSIntel { 1476d7937e2eSIntel char *end = NULL; 1477d7937e2eSIntel unsigned long len; 1478d7937e2eSIntel 1479d7937e2eSIntel /* parse decimal string */ 1480d7937e2eSIntel len = strtoul(pktlen, &end, 10); 1481d7937e2eSIntel if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) 1482d7937e2eSIntel return -1; 1483d7937e2eSIntel 1484d7937e2eSIntel if (len == 0) 1485d7937e2eSIntel return -1; 1486d7937e2eSIntel 1487d7937e2eSIntel return len; 1488d7937e2eSIntel } 1489d7937e2eSIntel 1490d7937e2eSIntel static int 1491d7937e2eSIntel parse_portmask(const char *portmask) 1492d7937e2eSIntel { 1493d7937e2eSIntel char *end = NULL; 1494d7937e2eSIntel unsigned long pm; 1495d7937e2eSIntel 1496d7937e2eSIntel /* parse hexadecimal string */ 1497d7937e2eSIntel pm = strtoul(portmask, &end, 16); 1498d7937e2eSIntel if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 1499d7937e2eSIntel return -1; 1500d7937e2eSIntel 1501d7937e2eSIntel if (pm == 0) 1502d7937e2eSIntel return -1; 1503d7937e2eSIntel 1504d7937e2eSIntel return pm; 1505d7937e2eSIntel } 1506d7937e2eSIntel 1507d7937e2eSIntel static int 1508d7937e2eSIntel parse_config(const char *q_arg) 1509d7937e2eSIntel { 1510d7937e2eSIntel char s[256]; 1511d7937e2eSIntel const char *p, *p0 = q_arg; 1512d7937e2eSIntel char *end; 1513d7937e2eSIntel enum fieldnames { 1514d7937e2eSIntel FLD_PORT = 0, 1515d7937e2eSIntel FLD_QUEUE, 1516d7937e2eSIntel FLD_LCORE, 1517d7937e2eSIntel _NUM_FLD 1518d7937e2eSIntel }; 1519d7937e2eSIntel unsigned long int_fld[_NUM_FLD]; 1520d7937e2eSIntel char *str_fld[_NUM_FLD]; 1521d7937e2eSIntel int i; 1522d7937e2eSIntel unsigned size; 1523d7937e2eSIntel 1524d7937e2eSIntel nb_lcore_params = 0; 1525d7937e2eSIntel 1526d7937e2eSIntel while ((p = strchr(p0,'(')) != NULL) { 1527d7937e2eSIntel ++p; 1528d7937e2eSIntel if((p0 = strchr(p,')')) == NULL) 1529d7937e2eSIntel return -1; 1530d7937e2eSIntel 1531d7937e2eSIntel size = p0 - p; 1532d7937e2eSIntel if(size >= sizeof(s)) 1533d7937e2eSIntel return -1; 1534d7937e2eSIntel 15356f41fe75SStephen Hemminger snprintf(s, sizeof(s), "%.*s", size, p); 1536d7937e2eSIntel if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 1537d7937e2eSIntel _NUM_FLD) 1538d7937e2eSIntel return -1; 1539d7937e2eSIntel for (i = 0; i < _NUM_FLD; i++){ 1540d7937e2eSIntel errno = 0; 1541d7937e2eSIntel int_fld[i] = strtoul(str_fld[i], &end, 0); 1542d7937e2eSIntel if (errno != 0 || end == str_fld[i] || int_fld[i] > 1543d7937e2eSIntel 255) 1544d7937e2eSIntel return -1; 1545d7937e2eSIntel } 1546d7937e2eSIntel if (nb_lcore_params >= MAX_LCORE_PARAMS) { 1547d7937e2eSIntel printf("exceeded max number of lcore params: %hu\n", 1548d7937e2eSIntel nb_lcore_params); 1549d7937e2eSIntel return -1; 1550d7937e2eSIntel } 1551d7937e2eSIntel lcore_params_array[nb_lcore_params].port_id = 1552d7937e2eSIntel (uint8_t)int_fld[FLD_PORT]; 1553d7937e2eSIntel lcore_params_array[nb_lcore_params].queue_id = 1554d7937e2eSIntel (uint8_t)int_fld[FLD_QUEUE]; 1555d7937e2eSIntel lcore_params_array[nb_lcore_params].lcore_id = 1556d7937e2eSIntel (uint8_t)int_fld[FLD_LCORE]; 1557d7937e2eSIntel ++nb_lcore_params; 1558d7937e2eSIntel } 1559d7937e2eSIntel lcore_params = lcore_params_array; 1560d7937e2eSIntel 1561d7937e2eSIntel return 0; 1562d7937e2eSIntel } 1563a137d012SLiang Ma static int 1564a137d012SLiang Ma parse_ep_config(const char *q_arg) 1565a137d012SLiang Ma { 1566a137d012SLiang Ma char s[256]; 1567a137d012SLiang Ma const char *p = q_arg; 1568a137d012SLiang Ma char *end; 1569a137d012SLiang Ma int num_arg; 1570d7937e2eSIntel 1571a137d012SLiang Ma char *str_fld[3]; 1572a137d012SLiang Ma 1573a137d012SLiang Ma int training_flag; 1574a137d012SLiang Ma int med_edpi; 1575a137d012SLiang Ma int hgh_edpi; 1576a137d012SLiang Ma 1577a137d012SLiang Ma ep_med_edpi = EMPTY_POLL_MED_THRESHOLD; 1578a137d012SLiang Ma ep_hgh_edpi = EMPTY_POLL_MED_THRESHOLD; 1579a137d012SLiang Ma 1580f9acaf84SBruce Richardson strlcpy(s, p, sizeof(s)); 1581a137d012SLiang Ma 1582a137d012SLiang Ma num_arg = rte_strsplit(s, sizeof(s), str_fld, 3, ','); 1583a137d012SLiang Ma 1584a137d012SLiang Ma empty_poll_train = false; 1585a137d012SLiang Ma 1586a137d012SLiang Ma if (num_arg == 0) 1587a137d012SLiang Ma return 0; 1588a137d012SLiang Ma 1589a137d012SLiang Ma if (num_arg == 3) { 1590a137d012SLiang Ma 1591a137d012SLiang Ma training_flag = strtoul(str_fld[0], &end, 0); 1592a137d012SLiang Ma med_edpi = strtoul(str_fld[1], &end, 0); 1593a137d012SLiang Ma hgh_edpi = strtoul(str_fld[2], &end, 0); 1594a137d012SLiang Ma 1595a137d012SLiang Ma if (training_flag == 1) 1596a137d012SLiang Ma empty_poll_train = true; 1597a137d012SLiang Ma 1598a137d012SLiang Ma if (med_edpi > 0) 1599a137d012SLiang Ma ep_med_edpi = med_edpi; 1600a137d012SLiang Ma 1601a137d012SLiang Ma if (med_edpi > 0) 1602a137d012SLiang Ma ep_hgh_edpi = hgh_edpi; 1603a137d012SLiang Ma 1604a137d012SLiang Ma } else { 1605a137d012SLiang Ma 1606a137d012SLiang Ma return -1; 1607a137d012SLiang Ma } 1608a137d012SLiang Ma 1609a137d012SLiang Ma return 0; 1610a137d012SLiang Ma 1611a137d012SLiang Ma } 161282bea466SJianfeng Tan #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype" 1613609e7984SReshma Pattan #define CMD_LINE_OPT_TELEMETRY "telemetry" 161482bea466SJianfeng Tan 1615d7937e2eSIntel /* Parse the argument given in the command line of the application */ 1616d7937e2eSIntel static int 1617d7937e2eSIntel parse_args(int argc, char **argv) 1618d7937e2eSIntel { 1619d7937e2eSIntel int opt, ret; 1620d7937e2eSIntel char **argvopt; 1621d7937e2eSIntel int option_index; 1622a137d012SLiang Ma uint32_t limit; 1623d7937e2eSIntel char *prgname = argv[0]; 1624d7937e2eSIntel static struct option lgopts[] = { 1625d7937e2eSIntel {"config", 1, 0, 0}, 1626f88e7c17SRadu Nicolau {"perf-config", 1, 0, 0}, 1627f88e7c17SRadu Nicolau {"high-perf-cores", 1, 0, 0}, 1628d7937e2eSIntel {"no-numa", 0, 0, 0}, 1629d7937e2eSIntel {"enable-jumbo", 0, 0, 0}, 1630a137d012SLiang Ma {"empty-poll", 1, 0, 0}, 163182bea466SJianfeng Tan {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, 1632609e7984SReshma Pattan {CMD_LINE_OPT_TELEMETRY, 0, 0, 0}, 1633d7937e2eSIntel {NULL, 0, 0, 0} 1634d7937e2eSIntel }; 1635d7937e2eSIntel 1636d7937e2eSIntel argvopt = argv; 1637d7937e2eSIntel 1638a137d012SLiang Ma while ((opt = getopt_long(argc, argvopt, "p:l:m:h:P", 1639d7937e2eSIntel lgopts, &option_index)) != EOF) { 1640d7937e2eSIntel 1641d7937e2eSIntel switch (opt) { 1642d7937e2eSIntel /* portmask */ 1643d7937e2eSIntel case 'p': 1644d7937e2eSIntel enabled_port_mask = parse_portmask(optarg); 1645d7937e2eSIntel if (enabled_port_mask == 0) { 1646d7937e2eSIntel printf("invalid portmask\n"); 1647d7937e2eSIntel print_usage(prgname); 1648d7937e2eSIntel return -1; 1649d7937e2eSIntel } 1650d7937e2eSIntel break; 1651d7937e2eSIntel case 'P': 1652d7937e2eSIntel printf("Promiscuous mode selected\n"); 1653d7937e2eSIntel promiscuous_on = 1; 1654d7937e2eSIntel break; 1655a137d012SLiang Ma case 'l': 1656a137d012SLiang Ma limit = parse_max_pkt_len(optarg); 1657a137d012SLiang Ma freq_tlb[LOW] = limit; 1658a137d012SLiang Ma break; 1659a137d012SLiang Ma case 'm': 1660a137d012SLiang Ma limit = parse_max_pkt_len(optarg); 1661a137d012SLiang Ma freq_tlb[MED] = limit; 1662a137d012SLiang Ma break; 1663a137d012SLiang Ma case 'h': 1664a137d012SLiang Ma limit = parse_max_pkt_len(optarg); 1665a137d012SLiang Ma freq_tlb[HGH] = limit; 1666a137d012SLiang Ma break; 1667d7937e2eSIntel /* long options */ 1668d7937e2eSIntel case 0: 1669d7937e2eSIntel if (!strncmp(lgopts[option_index].name, "config", 6)) { 1670d7937e2eSIntel ret = parse_config(optarg); 1671d7937e2eSIntel if (ret) { 1672d7937e2eSIntel printf("invalid config\n"); 1673d7937e2eSIntel print_usage(prgname); 1674d7937e2eSIntel return -1; 1675d7937e2eSIntel } 1676d7937e2eSIntel } 1677d7937e2eSIntel 1678d7937e2eSIntel if (!strncmp(lgopts[option_index].name, 1679f88e7c17SRadu Nicolau "perf-config", 11)) { 1680f88e7c17SRadu Nicolau ret = parse_perf_config(optarg); 1681f88e7c17SRadu Nicolau if (ret) { 1682f88e7c17SRadu Nicolau printf("invalid perf-config\n"); 1683f88e7c17SRadu Nicolau print_usage(prgname); 1684f88e7c17SRadu Nicolau return -1; 1685f88e7c17SRadu Nicolau } 1686f88e7c17SRadu Nicolau } 1687f88e7c17SRadu Nicolau 1688f88e7c17SRadu Nicolau if (!strncmp(lgopts[option_index].name, 1689f88e7c17SRadu Nicolau "high-perf-cores", 15)) { 1690f88e7c17SRadu Nicolau ret = parse_perf_core_list(optarg); 1691f88e7c17SRadu Nicolau if (ret) { 1692f88e7c17SRadu Nicolau printf("invalid high-perf-cores\n"); 1693f88e7c17SRadu Nicolau print_usage(prgname); 1694f88e7c17SRadu Nicolau return -1; 1695f88e7c17SRadu Nicolau } 1696f88e7c17SRadu Nicolau } 1697f88e7c17SRadu Nicolau 1698f88e7c17SRadu Nicolau if (!strncmp(lgopts[option_index].name, 1699d7937e2eSIntel "no-numa", 7)) { 1700d7937e2eSIntel printf("numa is disabled \n"); 1701d7937e2eSIntel numa_on = 0; 1702d7937e2eSIntel } 1703d7937e2eSIntel 1704d7937e2eSIntel if (!strncmp(lgopts[option_index].name, 1705a137d012SLiang Ma "empty-poll", 10)) { 1706609e7984SReshma Pattan if (app_mode == APP_MODE_TELEMETRY) { 1707609e7984SReshma Pattan printf(" empty-poll cannot be enabled as telemetry mode is enabled\n"); 1708609e7984SReshma Pattan return -1; 1709609e7984SReshma Pattan } 1710609e7984SReshma Pattan app_mode = APP_MODE_EMPTY_POLL; 1711a137d012SLiang Ma ret = parse_ep_config(optarg); 1712a137d012SLiang Ma 1713a137d012SLiang Ma if (ret) { 1714a137d012SLiang Ma printf("invalid empty poll config\n"); 1715a137d012SLiang Ma print_usage(prgname); 1716a137d012SLiang Ma return -1; 1717a137d012SLiang Ma } 1718609e7984SReshma Pattan printf("empty-poll is enabled\n"); 1719609e7984SReshma Pattan } 1720a137d012SLiang Ma 1721609e7984SReshma Pattan if (!strncmp(lgopts[option_index].name, 1722609e7984SReshma Pattan CMD_LINE_OPT_TELEMETRY, 1723609e7984SReshma Pattan sizeof(CMD_LINE_OPT_TELEMETRY))) { 1724609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL) { 1725609e7984SReshma Pattan printf("telemetry mode cannot be enabled as empty poll mode is enabled\n"); 1726609e7984SReshma Pattan return -1; 1727609e7984SReshma Pattan } 1728609e7984SReshma Pattan app_mode = APP_MODE_TELEMETRY; 1729609e7984SReshma Pattan printf("telemetry mode is enabled\n"); 1730a137d012SLiang Ma } 1731a137d012SLiang Ma 1732a137d012SLiang Ma if (!strncmp(lgopts[option_index].name, 1733d7937e2eSIntel "enable-jumbo", 12)) { 1734d7937e2eSIntel struct option lenopts = 1735d7937e2eSIntel {"max-pkt-len", required_argument, \ 1736d7937e2eSIntel 0, 0}; 1737d7937e2eSIntel 1738d7937e2eSIntel printf("jumbo frame is enabled \n"); 173940df1d7aSShahaf Shuler port_conf.rxmode.offloads |= 174040df1d7aSShahaf Shuler DEV_RX_OFFLOAD_JUMBO_FRAME; 174140df1d7aSShahaf Shuler port_conf.txmode.offloads |= 174240df1d7aSShahaf Shuler DEV_TX_OFFLOAD_MULTI_SEGS; 1743d7937e2eSIntel 1744d7937e2eSIntel /** 1745d7937e2eSIntel * if no max-pkt-len set, use the default value 174635b2d13fSOlivier Matz * RTE_ETHER_MAX_LEN 1747d7937e2eSIntel */ 1748d7937e2eSIntel if (0 == getopt_long(argc, argvopt, "", 1749d7937e2eSIntel &lenopts, &option_index)) { 1750d7937e2eSIntel ret = parse_max_pkt_len(optarg); 1751d7937e2eSIntel if ((ret < 64) || 1752d7937e2eSIntel (ret > MAX_JUMBO_PKT_LEN)){ 1753d7937e2eSIntel printf("invalid packet " 1754d7937e2eSIntel "length\n"); 1755d7937e2eSIntel print_usage(prgname); 1756d7937e2eSIntel return -1; 1757d7937e2eSIntel } 1758d7937e2eSIntel port_conf.rxmode.max_rx_pkt_len = ret; 1759d7937e2eSIntel } 1760d7937e2eSIntel printf("set jumbo frame " 1761d7937e2eSIntel "max packet length to %u\n", 1762d7937e2eSIntel (unsigned int)port_conf.rxmode.max_rx_pkt_len); 1763d7937e2eSIntel } 1764d7937e2eSIntel 176582bea466SJianfeng Tan if (!strncmp(lgopts[option_index].name, 176682bea466SJianfeng Tan CMD_LINE_OPT_PARSE_PTYPE, 176782bea466SJianfeng Tan sizeof(CMD_LINE_OPT_PARSE_PTYPE))) { 176882bea466SJianfeng Tan printf("soft parse-ptype is enabled\n"); 176982bea466SJianfeng Tan parse_ptype = 1; 177082bea466SJianfeng Tan } 177182bea466SJianfeng Tan 1772d7937e2eSIntel break; 1773d7937e2eSIntel 1774d7937e2eSIntel default: 1775d7937e2eSIntel print_usage(prgname); 1776d7937e2eSIntel return -1; 1777d7937e2eSIntel } 1778d7937e2eSIntel } 1779d7937e2eSIntel 1780d7937e2eSIntel if (optind >= 0) 1781d7937e2eSIntel argv[optind-1] = prgname; 1782d7937e2eSIntel 1783d7937e2eSIntel ret = optind-1; 17849d5ca532SKeith Wiles optind = 1; /* reset getopt lib */ 1785d7937e2eSIntel return ret; 1786d7937e2eSIntel } 1787d7937e2eSIntel 1788d7937e2eSIntel static void 17896d13ea8eSOlivier Matz print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 1790d7937e2eSIntel { 179135b2d13fSOlivier Matz char buf[RTE_ETHER_ADDR_FMT_SIZE]; 179235b2d13fSOlivier Matz rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 1793ec3d82dbSCunming Liang printf("%s%s", name, buf); 1794d7937e2eSIntel } 1795d7937e2eSIntel 1796d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 1797d7937e2eSIntel static void 1798d7937e2eSIntel setup_hash(int socketid) 1799d7937e2eSIntel { 1800d7937e2eSIntel struct rte_hash_parameters ipv4_l3fwd_hash_params = { 1801d7937e2eSIntel .name = NULL, 1802d7937e2eSIntel .entries = L3FWD_HASH_ENTRIES, 1803d7937e2eSIntel .key_len = sizeof(struct ipv4_5tuple), 1804d7937e2eSIntel .hash_func = DEFAULT_HASH_FUNC, 1805d7937e2eSIntel .hash_func_init_val = 0, 1806d7937e2eSIntel }; 1807d7937e2eSIntel 1808d7937e2eSIntel struct rte_hash_parameters ipv6_l3fwd_hash_params = { 1809d7937e2eSIntel .name = NULL, 1810d7937e2eSIntel .entries = L3FWD_HASH_ENTRIES, 1811d7937e2eSIntel .key_len = sizeof(struct ipv6_5tuple), 1812d7937e2eSIntel .hash_func = DEFAULT_HASH_FUNC, 1813d7937e2eSIntel .hash_func_init_val = 0, 1814d7937e2eSIntel }; 1815d7937e2eSIntel 1816d7937e2eSIntel unsigned i; 1817d7937e2eSIntel int ret; 1818d7937e2eSIntel char s[64]; 1819d7937e2eSIntel 1820d7937e2eSIntel /* create ipv4 hash */ 1821a5cf3924SThomas Monjalon snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid); 1822d7937e2eSIntel ipv4_l3fwd_hash_params.name = s; 1823d7937e2eSIntel ipv4_l3fwd_hash_params.socket_id = socketid; 1824d7937e2eSIntel ipv4_l3fwd_lookup_struct[socketid] = 1825d7937e2eSIntel rte_hash_create(&ipv4_l3fwd_hash_params); 1826d7937e2eSIntel if (ipv4_l3fwd_lookup_struct[socketid] == NULL) 1827d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " 1828d7937e2eSIntel "socket %d\n", socketid); 1829d7937e2eSIntel 1830d7937e2eSIntel /* create ipv6 hash */ 1831a5cf3924SThomas Monjalon snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid); 1832d7937e2eSIntel ipv6_l3fwd_hash_params.name = s; 1833d7937e2eSIntel ipv6_l3fwd_hash_params.socket_id = socketid; 1834d7937e2eSIntel ipv6_l3fwd_lookup_struct[socketid] = 1835d7937e2eSIntel rte_hash_create(&ipv6_l3fwd_hash_params); 1836d7937e2eSIntel if (ipv6_l3fwd_lookup_struct[socketid] == NULL) 1837d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " 1838d7937e2eSIntel "socket %d\n", socketid); 1839d7937e2eSIntel 1840d7937e2eSIntel 1841d7937e2eSIntel /* populate the ipv4 hash */ 1842d7937e2eSIntel for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { 1843d7937e2eSIntel ret = rte_hash_add_key (ipv4_l3fwd_lookup_struct[socketid], 1844d7937e2eSIntel (void *) &ipv4_l3fwd_route_array[i].key); 1845d7937e2eSIntel if (ret < 0) { 1846d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" 1847d7937e2eSIntel "l3fwd hash on socket %d\n", i, socketid); 1848d7937e2eSIntel } 1849d7937e2eSIntel ipv4_l3fwd_out_if[ret] = ipv4_l3fwd_route_array[i].if_out; 1850d7937e2eSIntel printf("Hash: Adding key\n"); 1851d7937e2eSIntel print_ipv4_key(ipv4_l3fwd_route_array[i].key); 1852d7937e2eSIntel } 1853d7937e2eSIntel 1854d7937e2eSIntel /* populate the ipv6 hash */ 1855d7937e2eSIntel for (i = 0; i < IPV6_L3FWD_NUM_ROUTES; i++) { 1856d7937e2eSIntel ret = rte_hash_add_key (ipv6_l3fwd_lookup_struct[socketid], 1857d7937e2eSIntel (void *) &ipv6_l3fwd_route_array[i].key); 1858d7937e2eSIntel if (ret < 0) { 1859d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" 1860d7937e2eSIntel "l3fwd hash on socket %d\n", i, socketid); 1861d7937e2eSIntel } 1862d7937e2eSIntel ipv6_l3fwd_out_if[ret] = ipv6_l3fwd_route_array[i].if_out; 1863d7937e2eSIntel printf("Hash: Adding key\n"); 1864d7937e2eSIntel print_ipv6_key(ipv6_l3fwd_route_array[i].key); 1865d7937e2eSIntel } 1866d7937e2eSIntel } 1867d7937e2eSIntel #endif 1868d7937e2eSIntel 1869d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 1870d7937e2eSIntel static void 1871d7937e2eSIntel setup_lpm(int socketid) 1872d7937e2eSIntel { 1873d7937e2eSIntel unsigned i; 1874d7937e2eSIntel int ret; 1875d7937e2eSIntel char s[64]; 1876d7937e2eSIntel 1877d7937e2eSIntel /* create the LPM table */ 1878f1f72618SMichal Kobylinski struct rte_lpm_config lpm_ipv4_config; 1879f1f72618SMichal Kobylinski 1880f1f72618SMichal Kobylinski lpm_ipv4_config.max_rules = IPV4_L3FWD_LPM_MAX_RULES; 1881f1f72618SMichal Kobylinski lpm_ipv4_config.number_tbl8s = 256; 1882f1f72618SMichal Kobylinski lpm_ipv4_config.flags = 0; 1883f1f72618SMichal Kobylinski 18846f41fe75SStephen Hemminger snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid); 1885f1f72618SMichal Kobylinski ipv4_l3fwd_lookup_struct[socketid] = 1886f1f72618SMichal Kobylinski rte_lpm_create(s, socketid, &lpm_ipv4_config); 1887d7937e2eSIntel if (ipv4_l3fwd_lookup_struct[socketid] == NULL) 1888d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" 1889d7937e2eSIntel " on socket %d\n", socketid); 1890d7937e2eSIntel 1891d7937e2eSIntel /* populate the LPM table */ 1892d7937e2eSIntel for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { 1893d7937e2eSIntel ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid], 1894d7937e2eSIntel ipv4_l3fwd_route_array[i].ip, 1895d7937e2eSIntel ipv4_l3fwd_route_array[i].depth, 1896d7937e2eSIntel ipv4_l3fwd_route_array[i].if_out); 1897d7937e2eSIntel 1898d7937e2eSIntel if (ret < 0) { 1899d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " 1900d7937e2eSIntel "l3fwd LPM table on socket %d\n", 1901d7937e2eSIntel i, socketid); 1902d7937e2eSIntel } 1903d7937e2eSIntel 1904d7937e2eSIntel printf("LPM: Adding route 0x%08x / %d (%d)\n", 1905d7937e2eSIntel (unsigned)ipv4_l3fwd_route_array[i].ip, 1906d7937e2eSIntel ipv4_l3fwd_route_array[i].depth, 1907d7937e2eSIntel ipv4_l3fwd_route_array[i].if_out); 1908d7937e2eSIntel } 1909d7937e2eSIntel } 1910d7937e2eSIntel #endif 1911d7937e2eSIntel 1912d7937e2eSIntel static int 1913d7937e2eSIntel init_mem(unsigned nb_mbuf) 1914d7937e2eSIntel { 1915d7937e2eSIntel struct lcore_conf *qconf; 1916d7937e2eSIntel int socketid; 1917d7937e2eSIntel unsigned lcore_id; 1918d7937e2eSIntel char s[64]; 1919d7937e2eSIntel 1920d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 1921d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 1922d7937e2eSIntel continue; 1923d7937e2eSIntel 1924d7937e2eSIntel if (numa_on) 1925d7937e2eSIntel socketid = rte_lcore_to_socket_id(lcore_id); 1926d7937e2eSIntel else 1927d7937e2eSIntel socketid = 0; 1928d7937e2eSIntel 1929d7937e2eSIntel if (socketid >= NB_SOCKETS) { 1930d7937e2eSIntel rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is " 1931d7937e2eSIntel "out of range %d\n", socketid, 1932d7937e2eSIntel lcore_id, NB_SOCKETS); 1933d7937e2eSIntel } 1934d7937e2eSIntel if (pktmbuf_pool[socketid] == NULL) { 19356f41fe75SStephen Hemminger snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 1936d7937e2eSIntel pktmbuf_pool[socketid] = 1937ea0c20eaSOlivier Matz rte_pktmbuf_pool_create(s, nb_mbuf, 1938824cb29cSKonstantin Ananyev MEMPOOL_CACHE_SIZE, 0, 1939824cb29cSKonstantin Ananyev RTE_MBUF_DEFAULT_BUF_SIZE, 1940ea0c20eaSOlivier Matz socketid); 1941d7937e2eSIntel if (pktmbuf_pool[socketid] == NULL) 1942d7937e2eSIntel rte_exit(EXIT_FAILURE, 1943d7937e2eSIntel "Cannot init mbuf pool on socket %d\n", 1944d7937e2eSIntel socketid); 1945d7937e2eSIntel else 1946d7937e2eSIntel printf("Allocated mbuf pool on socket %d\n", 1947d7937e2eSIntel socketid); 1948d7937e2eSIntel 1949d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 1950d7937e2eSIntel setup_lpm(socketid); 1951d7937e2eSIntel #else 1952d7937e2eSIntel setup_hash(socketid); 1953d7937e2eSIntel #endif 1954d7937e2eSIntel } 1955d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 1956d7937e2eSIntel qconf->ipv4_lookup_struct = ipv4_l3fwd_lookup_struct[socketid]; 1957d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 1958d7937e2eSIntel qconf->ipv6_lookup_struct = ipv6_l3fwd_lookup_struct[socketid]; 1959d7937e2eSIntel #endif 1960d7937e2eSIntel } 1961d7937e2eSIntel return 0; 1962d7937e2eSIntel } 1963d7937e2eSIntel 1964d7937e2eSIntel /* Check the link status of all ports in up to 9s, and print them finally */ 1965d7937e2eSIntel static void 19668728ccf3SThomas Monjalon check_all_ports_link_status(uint32_t port_mask) 1967d7937e2eSIntel { 1968d7937e2eSIntel #define CHECK_INTERVAL 100 /* 100ms */ 1969d7937e2eSIntel #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1970f8244c63SZhiyong Yang uint8_t count, all_ports_up, print_flag = 0; 1971f8244c63SZhiyong Yang uint16_t portid; 1972d7937e2eSIntel struct rte_eth_link link; 1973d7937e2eSIntel 1974d7937e2eSIntel printf("\nChecking link status"); 1975d7937e2eSIntel fflush(stdout); 1976d7937e2eSIntel for (count = 0; count <= MAX_CHECK_TIME; count++) { 1977d7937e2eSIntel all_ports_up = 1; 19788728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 1979d7937e2eSIntel if ((port_mask & (1 << portid)) == 0) 1980d7937e2eSIntel continue; 1981d7937e2eSIntel memset(&link, 0, sizeof(link)); 1982d7937e2eSIntel rte_eth_link_get_nowait(portid, &link); 1983d7937e2eSIntel /* print link status if flag set */ 1984d7937e2eSIntel if (print_flag == 1) { 1985d7937e2eSIntel if (link.link_status) 1986d7937e2eSIntel printf("Port %d Link Up - speed %u " 1987d7937e2eSIntel "Mbps - %s\n", (uint8_t)portid, 1988d7937e2eSIntel (unsigned)link.link_speed, 1989d7937e2eSIntel (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1990d7937e2eSIntel ("full-duplex") : ("half-duplex\n")); 1991d7937e2eSIntel else 1992d7937e2eSIntel printf("Port %d Link Down\n", 1993d7937e2eSIntel (uint8_t)portid); 1994d7937e2eSIntel continue; 1995d7937e2eSIntel } 1996d7937e2eSIntel /* clear all_ports_up flag if any link down */ 199709419f23SThomas Monjalon if (link.link_status == ETH_LINK_DOWN) { 1998d7937e2eSIntel all_ports_up = 0; 1999d7937e2eSIntel break; 2000d7937e2eSIntel } 2001d7937e2eSIntel } 2002d7937e2eSIntel /* after finally printing all link status, get out */ 2003d7937e2eSIntel if (print_flag == 1) 2004d7937e2eSIntel break; 2005d7937e2eSIntel 2006d7937e2eSIntel if (all_ports_up == 0) { 2007d7937e2eSIntel printf("."); 2008d7937e2eSIntel fflush(stdout); 2009d7937e2eSIntel rte_delay_ms(CHECK_INTERVAL); 2010d7937e2eSIntel } 2011d7937e2eSIntel 2012d7937e2eSIntel /* set the print_flag if all ports up or timeout */ 2013d7937e2eSIntel if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 2014d7937e2eSIntel print_flag = 1; 2015d7937e2eSIntel printf("done\n"); 2016d7937e2eSIntel } 2017d7937e2eSIntel } 2018d7937e2eSIntel } 2019d7937e2eSIntel 202047523597SZhiyong Yang static int check_ptype(uint16_t portid) 202182bea466SJianfeng Tan { 202282bea466SJianfeng Tan int i, ret; 202382bea466SJianfeng Tan int ptype_l3_ipv4 = 0; 202482bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 202582bea466SJianfeng Tan int ptype_l3_ipv6 = 0; 202682bea466SJianfeng Tan #endif 202782bea466SJianfeng Tan uint32_t ptype_mask = RTE_PTYPE_L3_MASK; 202882bea466SJianfeng Tan 202982bea466SJianfeng Tan ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0); 203082bea466SJianfeng Tan if (ret <= 0) 203182bea466SJianfeng Tan return 0; 203282bea466SJianfeng Tan 203382bea466SJianfeng Tan uint32_t ptypes[ret]; 203482bea466SJianfeng Tan 203582bea466SJianfeng Tan ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, ret); 203682bea466SJianfeng Tan for (i = 0; i < ret; ++i) { 203782bea466SJianfeng Tan if (ptypes[i] & RTE_PTYPE_L3_IPV4) 203882bea466SJianfeng Tan ptype_l3_ipv4 = 1; 203982bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 204082bea466SJianfeng Tan if (ptypes[i] & RTE_PTYPE_L3_IPV6) 204182bea466SJianfeng Tan ptype_l3_ipv6 = 1; 204282bea466SJianfeng Tan #endif 204382bea466SJianfeng Tan } 204482bea466SJianfeng Tan 204582bea466SJianfeng Tan if (ptype_l3_ipv4 == 0) 204682bea466SJianfeng Tan printf("port %d cannot parse RTE_PTYPE_L3_IPV4\n", portid); 204782bea466SJianfeng Tan 204882bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 204982bea466SJianfeng Tan if (ptype_l3_ipv6 == 0) 205082bea466SJianfeng Tan printf("port %d cannot parse RTE_PTYPE_L3_IPV6\n", portid); 205182bea466SJianfeng Tan #endif 205282bea466SJianfeng Tan 205382bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 205482bea466SJianfeng Tan if (ptype_l3_ipv4) 205582bea466SJianfeng Tan #else /* APP_LOOKUP_EXACT_MATCH */ 205682bea466SJianfeng Tan if (ptype_l3_ipv4 && ptype_l3_ipv6) 205782bea466SJianfeng Tan #endif 205882bea466SJianfeng Tan return 1; 205982bea466SJianfeng Tan 206082bea466SJianfeng Tan return 0; 206182bea466SJianfeng Tan 206282bea466SJianfeng Tan } 206382bea466SJianfeng Tan 2064f88e7c17SRadu Nicolau static int 2065f88e7c17SRadu Nicolau init_power_library(void) 2066f88e7c17SRadu Nicolau { 2067f88e7c17SRadu Nicolau int ret = 0, lcore_id; 2068f88e7c17SRadu Nicolau for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2069f88e7c17SRadu Nicolau if (rte_lcore_is_enabled(lcore_id)) { 2070f88e7c17SRadu Nicolau /* init power management library */ 2071f88e7c17SRadu Nicolau ret = rte_power_init(lcore_id); 2072f88e7c17SRadu Nicolau if (ret) 2073f88e7c17SRadu Nicolau RTE_LOG(ERR, POWER, 2074f88e7c17SRadu Nicolau "Library initialization failed on core %u\n", 2075f88e7c17SRadu Nicolau lcore_id); 2076f88e7c17SRadu Nicolau } 2077f88e7c17SRadu Nicolau } 2078f88e7c17SRadu Nicolau return ret; 2079f88e7c17SRadu Nicolau } 2080a137d012SLiang Ma static void 2081609e7984SReshma Pattan update_telemetry(__attribute__((unused)) struct rte_timer *tim, 2082609e7984SReshma Pattan __attribute__((unused)) void *arg) 2083609e7984SReshma Pattan { 2084609e7984SReshma Pattan unsigned int lcore_id = rte_lcore_id(); 2085609e7984SReshma Pattan struct lcore_conf *qconf; 2086609e7984SReshma Pattan uint64_t app_eps = 0, app_fps = 0, app_br = 0; 2087609e7984SReshma Pattan uint64_t values[3] = {0}; 2088609e7984SReshma Pattan int ret; 2089609e7984SReshma Pattan uint64_t count = 0; 2090609e7984SReshma Pattan 2091609e7984SReshma Pattan RTE_LCORE_FOREACH_SLAVE(lcore_id) { 2092609e7984SReshma Pattan qconf = &lcore_conf[lcore_id]; 2093609e7984SReshma Pattan if (qconf->n_rx_queue == 0) 2094609e7984SReshma Pattan continue; 2095609e7984SReshma Pattan count++; 2096609e7984SReshma Pattan rte_spinlock_lock(&stats[lcore_id].telemetry_lock); 2097609e7984SReshma Pattan app_eps += stats[lcore_id].ep_nep[1]; 2098609e7984SReshma Pattan app_fps += stats[lcore_id].fp_nfp[1]; 2099609e7984SReshma Pattan app_br += stats[lcore_id].br; 2100609e7984SReshma Pattan rte_spinlock_unlock(&stats[lcore_id].telemetry_lock); 2101609e7984SReshma Pattan } 2102609e7984SReshma Pattan 2103018faf21SDavid Hunt if (count > 0) { 2104018faf21SDavid Hunt values[0] = app_eps/count; 2105018faf21SDavid Hunt values[1] = app_fps/count; 2106018faf21SDavid Hunt values[2] = app_br/count; 2107018faf21SDavid Hunt } else { 2108018faf21SDavid Hunt values[0] = 0; 2109018faf21SDavid Hunt values[1] = 0; 2110018faf21SDavid Hunt values[2] = 0; 2111018faf21SDavid Hunt } 2112018faf21SDavid Hunt 2113609e7984SReshma Pattan ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, telstats_index, 2114609e7984SReshma Pattan values, RTE_DIM(values)); 2115609e7984SReshma Pattan if (ret < 0) 2116609e7984SReshma Pattan RTE_LOG(WARNING, POWER, "failed to update metrcis\n"); 2117609e7984SReshma Pattan } 2118609e7984SReshma Pattan static void 2119609e7984SReshma Pattan telemetry_setup_timer(void) 2120609e7984SReshma Pattan { 2121609e7984SReshma Pattan int lcore_id = rte_lcore_id(); 2122609e7984SReshma Pattan uint64_t hz = rte_get_timer_hz(); 2123609e7984SReshma Pattan uint64_t ticks; 2124609e7984SReshma Pattan 2125609e7984SReshma Pattan ticks = hz / TELEMETRY_INTERVALS_PER_SEC; 2126609e7984SReshma Pattan rte_timer_reset_sync(&telemetry_timer, 2127609e7984SReshma Pattan ticks, 2128609e7984SReshma Pattan PERIODICAL, 2129609e7984SReshma Pattan lcore_id, 2130609e7984SReshma Pattan update_telemetry, 2131609e7984SReshma Pattan NULL); 2132609e7984SReshma Pattan } 2133609e7984SReshma Pattan static void 2134a137d012SLiang Ma empty_poll_setup_timer(void) 2135a137d012SLiang Ma { 2136a137d012SLiang Ma int lcore_id = rte_lcore_id(); 2137a137d012SLiang Ma uint64_t hz = rte_get_timer_hz(); 2138a137d012SLiang Ma 2139a137d012SLiang Ma struct ep_params *ep_ptr = ep_params; 2140a137d012SLiang Ma 2141a137d012SLiang Ma ep_ptr->interval_ticks = hz / INTERVALS_PER_SECOND; 2142a137d012SLiang Ma 2143a137d012SLiang Ma rte_timer_reset_sync(&ep_ptr->timer0, 2144a137d012SLiang Ma ep_ptr->interval_ticks, 2145a137d012SLiang Ma PERIODICAL, 2146a137d012SLiang Ma lcore_id, 2147a137d012SLiang Ma rte_empty_poll_detection, 2148a137d012SLiang Ma (void *)ep_ptr); 2149a137d012SLiang Ma 2150a137d012SLiang Ma } 2151a137d012SLiang Ma static int 2152a137d012SLiang Ma launch_timer(unsigned int lcore_id) 2153a137d012SLiang Ma { 2154a137d012SLiang Ma int64_t prev_tsc = 0, cur_tsc, diff_tsc, cycles_10ms; 2155a137d012SLiang Ma 2156a137d012SLiang Ma RTE_SET_USED(lcore_id); 2157a137d012SLiang Ma 2158a137d012SLiang Ma 2159a137d012SLiang Ma if (rte_get_master_lcore() != lcore_id) { 2160a137d012SLiang Ma rte_panic("timer on lcore:%d which is not master core:%d\n", 2161a137d012SLiang Ma lcore_id, 2162a137d012SLiang Ma rte_get_master_lcore()); 2163a137d012SLiang Ma } 2164a137d012SLiang Ma 2165a137d012SLiang Ma RTE_LOG(INFO, POWER, "Bring up the Timer\n"); 2166a137d012SLiang Ma 2167609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL) 2168a137d012SLiang Ma empty_poll_setup_timer(); 2169609e7984SReshma Pattan else 2170609e7984SReshma Pattan telemetry_setup_timer(); 2171a137d012SLiang Ma 2172a137d012SLiang Ma cycles_10ms = rte_get_timer_hz() / 100; 2173a137d012SLiang Ma 2174a137d012SLiang Ma while (!is_done()) { 2175a137d012SLiang Ma cur_tsc = rte_rdtsc(); 2176a137d012SLiang Ma diff_tsc = cur_tsc - prev_tsc; 2177a137d012SLiang Ma if (diff_tsc > cycles_10ms) { 2178a137d012SLiang Ma rte_timer_manage(); 2179a137d012SLiang Ma prev_tsc = cur_tsc; 2180a137d012SLiang Ma cycles_10ms = rte_get_timer_hz() / 100; 2181a137d012SLiang Ma } 2182a137d012SLiang Ma } 2183a137d012SLiang Ma 2184a137d012SLiang Ma RTE_LOG(INFO, POWER, "Timer_subsystem is done\n"); 2185a137d012SLiang Ma 2186a137d012SLiang Ma return 0; 2187a137d012SLiang Ma } 2188a137d012SLiang Ma 2189f88e7c17SRadu Nicolau 2190d7937e2eSIntel int 219198a16481SDavid Marchand main(int argc, char **argv) 2192d7937e2eSIntel { 2193d7937e2eSIntel struct lcore_conf *qconf; 219481f7ecd9SPablo de Lara struct rte_eth_dev_info dev_info; 219581f7ecd9SPablo de Lara struct rte_eth_txconf *txconf; 2196d7937e2eSIntel int ret; 219747523597SZhiyong Yang uint16_t nb_ports; 2198d7937e2eSIntel uint16_t queueid; 2199d7937e2eSIntel unsigned lcore_id; 2200d7937e2eSIntel uint64_t hz; 2201d7937e2eSIntel uint32_t n_tx_queue, nb_lcores; 2202aee3bc79SCunming Liang uint32_t dev_rxq_num, dev_txq_num; 2203f8244c63SZhiyong Yang uint8_t nb_rx_queue, queue, socketid; 2204f8244c63SZhiyong Yang uint16_t portid; 2205609e7984SReshma Pattan uint8_t num_telstats = RTE_DIM(telstats_strings); 2206609e7984SReshma Pattan const char *ptr_strings[num_telstats]; 2207d7937e2eSIntel 2208d7937e2eSIntel /* catch SIGINT and restore cpufreq governor to ondemand */ 2209d7937e2eSIntel signal(SIGINT, signal_exit_now); 2210d7937e2eSIntel 2211d7937e2eSIntel /* init EAL */ 2212d7937e2eSIntel ret = rte_eal_init(argc, argv); 2213d7937e2eSIntel if (ret < 0) 2214d7937e2eSIntel rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 2215d7937e2eSIntel argc -= ret; 2216d7937e2eSIntel argv += ret; 2217d7937e2eSIntel 2218d7937e2eSIntel /* init RTE timer library to be used late */ 2219d7937e2eSIntel rte_timer_subsystem_init(); 2220d7937e2eSIntel 2221d7937e2eSIntel /* parse application arguments (after the EAL ones) */ 2222d7937e2eSIntel ret = parse_args(argc, argv); 2223d7937e2eSIntel if (ret < 0) 2224d7937e2eSIntel rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); 2225d7937e2eSIntel 2226f88e7c17SRadu Nicolau if (init_power_library()) 22276265115fSMoti Haimovsky RTE_LOG(ERR, L3FWD_POWER, "init_power_library failed\n"); 2228f88e7c17SRadu Nicolau 2229f88e7c17SRadu Nicolau if (update_lcore_params() < 0) 2230f88e7c17SRadu Nicolau rte_exit(EXIT_FAILURE, "update_lcore_params failed\n"); 2231f88e7c17SRadu Nicolau 2232d7937e2eSIntel if (check_lcore_params() < 0) 2233d7937e2eSIntel rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); 2234d7937e2eSIntel 2235d7937e2eSIntel ret = init_lcore_rx_queues(); 2236d7937e2eSIntel if (ret < 0) 2237d7937e2eSIntel rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); 2238d7937e2eSIntel 2239d9a42a69SThomas Monjalon nb_ports = rte_eth_dev_count_avail(); 2240d7937e2eSIntel 2241a9dbe180SThomas Monjalon if (check_port_config() < 0) 2242d7937e2eSIntel rte_exit(EXIT_FAILURE, "check_port_config failed\n"); 2243d7937e2eSIntel 2244d7937e2eSIntel nb_lcores = rte_lcore_count(); 2245d7937e2eSIntel 2246d7937e2eSIntel /* initialize all ports */ 22478728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 224840df1d7aSShahaf Shuler struct rte_eth_conf local_port_conf = port_conf; 224940df1d7aSShahaf Shuler 2250d7937e2eSIntel /* skip ports that are not enabled */ 2251d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 2252d7937e2eSIntel printf("\nSkipping disabled port %d\n", portid); 2253d7937e2eSIntel continue; 2254d7937e2eSIntel } 2255d7937e2eSIntel 2256d7937e2eSIntel /* init port */ 2257d7937e2eSIntel printf("Initializing port %d ... ", portid ); 2258d7937e2eSIntel fflush(stdout); 2259d7937e2eSIntel 2260*089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2261*089e5ed7SIvan Ilchenko if (ret != 0) 2262*089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2263*089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2264*089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2265*089e5ed7SIvan Ilchenko 2266aee3bc79SCunming Liang dev_rxq_num = dev_info.max_rx_queues; 2267aee3bc79SCunming Liang dev_txq_num = dev_info.max_tx_queues; 2268aee3bc79SCunming Liang 2269d7937e2eSIntel nb_rx_queue = get_port_n_rx_queues(portid); 2270aee3bc79SCunming Liang if (nb_rx_queue > dev_rxq_num) 2271aee3bc79SCunming Liang rte_exit(EXIT_FAILURE, 2272aee3bc79SCunming Liang "Cannot configure not existed rxq: " 2273aee3bc79SCunming Liang "port=%d\n", portid); 2274aee3bc79SCunming Liang 2275d7937e2eSIntel n_tx_queue = nb_lcores; 2276aee3bc79SCunming Liang if (n_tx_queue > dev_txq_num) 2277aee3bc79SCunming Liang n_tx_queue = dev_txq_num; 2278d7937e2eSIntel printf("Creating queues: nb_rxq=%d nb_txq=%u... ", 2279d7937e2eSIntel nb_rx_queue, (unsigned)n_tx_queue ); 2280ddc554adSJingjing Wu /* If number of Rx queue is 0, no need to enable Rx interrupt */ 2281ddc554adSJingjing Wu if (nb_rx_queue == 0) 228240df1d7aSShahaf Shuler local_port_conf.intr_conf.rxq = 0; 2283*089e5ed7SIvan Ilchenko 2284*089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2285*089e5ed7SIvan Ilchenko if (ret != 0) 2286*089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2287*089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2288*089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2289*089e5ed7SIvan Ilchenko 229040df1d7aSShahaf Shuler if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 229140df1d7aSShahaf Shuler local_port_conf.txmode.offloads |= 229240df1d7aSShahaf Shuler DEV_TX_OFFLOAD_MBUF_FAST_FREE; 22934f5701f2SFerruh Yigit 22944f5701f2SFerruh Yigit local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 22954f5701f2SFerruh Yigit dev_info.flow_type_rss_offloads; 22964f5701f2SFerruh Yigit if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 22974f5701f2SFerruh Yigit port_conf.rx_adv_conf.rss_conf.rss_hf) { 22984f5701f2SFerruh Yigit printf("Port %u modified RSS hash function based on hardware support," 22994f5701f2SFerruh Yigit "requested:%#"PRIx64" configured:%#"PRIx64"\n", 23004f5701f2SFerruh Yigit portid, 23014f5701f2SFerruh Yigit port_conf.rx_adv_conf.rss_conf.rss_hf, 23024f5701f2SFerruh Yigit local_port_conf.rx_adv_conf.rss_conf.rss_hf); 23034f5701f2SFerruh Yigit } 23044f5701f2SFerruh Yigit 2305d7937e2eSIntel ret = rte_eth_dev_configure(portid, nb_rx_queue, 230640df1d7aSShahaf Shuler (uint16_t)n_tx_queue, &local_port_conf); 2307d7937e2eSIntel if (ret < 0) 2308d7937e2eSIntel rte_exit(EXIT_FAILURE, "Cannot configure device: " 2309d7937e2eSIntel "err=%d, port=%d\n", ret, portid); 2310d7937e2eSIntel 231160efb44fSRoman Zhukov ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 231260efb44fSRoman Zhukov &nb_txd); 231360efb44fSRoman Zhukov if (ret < 0) 231460efb44fSRoman Zhukov rte_exit(EXIT_FAILURE, 231560efb44fSRoman Zhukov "Cannot adjust number of descriptors: err=%d, port=%d\n", 231660efb44fSRoman Zhukov ret, portid); 231760efb44fSRoman Zhukov 2318d7937e2eSIntel rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 2319d7937e2eSIntel print_ethaddr(" Address:", &ports_eth_addr[portid]); 2320d7937e2eSIntel printf(", "); 2321d7937e2eSIntel 2322d7937e2eSIntel /* init memory */ 2323d7937e2eSIntel ret = init_mem(NB_MBUF); 2324d7937e2eSIntel if (ret < 0) 2325d7937e2eSIntel rte_exit(EXIT_FAILURE, "init_mem failed\n"); 2326d7937e2eSIntel 2327e2366e74STomasz Kulasek for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2328e2366e74STomasz Kulasek if (rte_lcore_is_enabled(lcore_id) == 0) 2329e2366e74STomasz Kulasek continue; 2330e2366e74STomasz Kulasek 2331e2366e74STomasz Kulasek /* Initialize TX buffers */ 2332e2366e74STomasz Kulasek qconf = &lcore_conf[lcore_id]; 2333e2366e74STomasz Kulasek qconf->tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", 2334e2366e74STomasz Kulasek RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, 2335e2366e74STomasz Kulasek rte_eth_dev_socket_id(portid)); 2336e2366e74STomasz Kulasek if (qconf->tx_buffer[portid] == NULL) 2337e2366e74STomasz Kulasek rte_exit(EXIT_FAILURE, "Can't allocate tx buffer for port %u\n", 2338f8244c63SZhiyong Yang portid); 2339e2366e74STomasz Kulasek 2340e2366e74STomasz Kulasek rte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST); 2341e2366e74STomasz Kulasek } 2342e2366e74STomasz Kulasek 2343d7937e2eSIntel /* init one TX queue per couple (lcore,port) */ 2344d7937e2eSIntel queueid = 0; 2345d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2346d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 2347d7937e2eSIntel continue; 2348d7937e2eSIntel 2349aee3bc79SCunming Liang if (queueid >= dev_txq_num) 2350aee3bc79SCunming Liang continue; 2351aee3bc79SCunming Liang 2352d7937e2eSIntel if (numa_on) 2353d7937e2eSIntel socketid = \ 2354d7937e2eSIntel (uint8_t)rte_lcore_to_socket_id(lcore_id); 2355d7937e2eSIntel else 2356d7937e2eSIntel socketid = 0; 2357d7937e2eSIntel 2358d7937e2eSIntel printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); 2359d7937e2eSIntel fflush(stdout); 236081f7ecd9SPablo de Lara 236181f7ecd9SPablo de Lara txconf = &dev_info.default_txconf; 236240df1d7aSShahaf Shuler txconf->offloads = local_port_conf.txmode.offloads; 2363d7937e2eSIntel ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 236481f7ecd9SPablo de Lara socketid, txconf); 2365d7937e2eSIntel if (ret < 0) 2366d7937e2eSIntel rte_exit(EXIT_FAILURE, 2367d7937e2eSIntel "rte_eth_tx_queue_setup: err=%d, " 2368d7937e2eSIntel "port=%d\n", ret, portid); 2369d7937e2eSIntel 2370d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 2371d7937e2eSIntel qconf->tx_queue_id[portid] = queueid; 2372d7937e2eSIntel queueid++; 2373e2366e74STomasz Kulasek 2374e2366e74STomasz Kulasek qconf->tx_port_id[qconf->n_tx_port] = portid; 2375dd1c68faSTomasz Kulasek qconf->n_tx_port++; 2376d7937e2eSIntel } 2377d7937e2eSIntel printf("\n"); 2378d7937e2eSIntel } 2379d7937e2eSIntel 2380d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2381d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 2382d7937e2eSIntel continue; 2383d7937e2eSIntel 2384609e7984SReshma Pattan if (app_mode == APP_MODE_LEGACY) { 2385d7937e2eSIntel /* init timer structures for each enabled lcore */ 2386d7937e2eSIntel rte_timer_init(&power_timers[lcore_id]); 2387d7937e2eSIntel hz = rte_get_timer_hz(); 2388d7937e2eSIntel rte_timer_reset(&power_timers[lcore_id], 2389a137d012SLiang Ma hz/TIMER_NUMBER_PER_SECOND, 2390a137d012SLiang Ma SINGLE, lcore_id, 2391d7937e2eSIntel power_timer_cb, NULL); 2392a137d012SLiang Ma } 2393d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 2394d7937e2eSIntel printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); 2395d7937e2eSIntel fflush(stdout); 2396d7937e2eSIntel /* init RX queues */ 2397d7937e2eSIntel for(queue = 0; queue < qconf->n_rx_queue; ++queue) { 239840df1d7aSShahaf Shuler struct rte_eth_rxconf rxq_conf; 239940df1d7aSShahaf Shuler 2400d7937e2eSIntel portid = qconf->rx_queue_list[queue].port_id; 2401d7937e2eSIntel queueid = qconf->rx_queue_list[queue].queue_id; 2402d7937e2eSIntel 2403d7937e2eSIntel if (numa_on) 2404d7937e2eSIntel socketid = \ 2405d7937e2eSIntel (uint8_t)rte_lcore_to_socket_id(lcore_id); 2406d7937e2eSIntel else 2407d7937e2eSIntel socketid = 0; 2408d7937e2eSIntel 2409d7937e2eSIntel printf("rxq=%d,%d,%d ", portid, queueid, socketid); 2410d7937e2eSIntel fflush(stdout); 2411d7937e2eSIntel 2412*089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2413*089e5ed7SIvan Ilchenko if (ret != 0) 2414*089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2415*089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2416*089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2417*089e5ed7SIvan Ilchenko 241840df1d7aSShahaf Shuler rxq_conf = dev_info.default_rxconf; 24195c5c1f99SMarcin Zapolski rxq_conf.offloads = port_conf.rxmode.offloads; 2420d7937e2eSIntel ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, 242140df1d7aSShahaf Shuler socketid, &rxq_conf, 242281f7ecd9SPablo de Lara pktmbuf_pool[socketid]); 2423d7937e2eSIntel if (ret < 0) 2424d7937e2eSIntel rte_exit(EXIT_FAILURE, 2425d7937e2eSIntel "rte_eth_rx_queue_setup: err=%d, " 2426d7937e2eSIntel "port=%d\n", ret, portid); 242782bea466SJianfeng Tan 242882bea466SJianfeng Tan if (parse_ptype) { 242982bea466SJianfeng Tan if (add_cb_parse_ptype(portid, queueid) < 0) 243082bea466SJianfeng Tan rte_exit(EXIT_FAILURE, 243182bea466SJianfeng Tan "Fail to add ptype cb\n"); 243282bea466SJianfeng Tan } else if (!check_ptype(portid)) 243382bea466SJianfeng Tan rte_exit(EXIT_FAILURE, 243482bea466SJianfeng Tan "PMD can not provide needed ptypes\n"); 2435d7937e2eSIntel } 2436d7937e2eSIntel } 2437d7937e2eSIntel 2438d7937e2eSIntel printf("\n"); 2439d7937e2eSIntel 2440d7937e2eSIntel /* start ports */ 24418728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 2442d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 2443d7937e2eSIntel continue; 2444d7937e2eSIntel } 2445d7937e2eSIntel /* Start device */ 2446d7937e2eSIntel ret = rte_eth_dev_start(portid); 2447d7937e2eSIntel if (ret < 0) 2448d7937e2eSIntel rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, " 2449d7937e2eSIntel "port=%d\n", ret, portid); 2450d7937e2eSIntel /* 2451d7937e2eSIntel * If enabled, put device in promiscuous mode. 2452d7937e2eSIntel * This allows IO forwarding mode to forward packets 2453d7937e2eSIntel * to itself through 2 cross-connected ports of the 2454d7937e2eSIntel * target machine. 2455d7937e2eSIntel */ 2456d7937e2eSIntel if (promiscuous_on) 2457d7937e2eSIntel rte_eth_promiscuous_enable(portid); 2458aee3bc79SCunming Liang /* initialize spinlock for each port */ 2459aee3bc79SCunming Liang rte_spinlock_init(&(locks[portid])); 2460d7937e2eSIntel } 2461d7937e2eSIntel 24628728ccf3SThomas Monjalon check_all_ports_link_status(enabled_port_mask); 2463d7937e2eSIntel 2464609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL) { 2465a137d012SLiang Ma 2466a137d012SLiang Ma if (empty_poll_train) { 2467a137d012SLiang Ma policy.state = TRAINING; 2468a137d012SLiang Ma } else { 2469a137d012SLiang Ma policy.state = MED_NORMAL; 2470a137d012SLiang Ma policy.med_base_edpi = ep_med_edpi; 2471a137d012SLiang Ma policy.hgh_base_edpi = ep_hgh_edpi; 2472a137d012SLiang Ma } 2473a137d012SLiang Ma 2474a137d012SLiang Ma ret = rte_power_empty_poll_stat_init(&ep_params, 2475a137d012SLiang Ma freq_tlb, 2476a137d012SLiang Ma &policy); 2477a137d012SLiang Ma if (ret < 0) 2478a137d012SLiang Ma rte_exit(EXIT_FAILURE, "empty poll init failed"); 2479a137d012SLiang Ma } 2480a137d012SLiang Ma 2481a137d012SLiang Ma 2482d7937e2eSIntel /* launch per-lcore init on every lcore */ 2483609e7984SReshma Pattan if (app_mode == APP_MODE_LEGACY) { 2484d7937e2eSIntel rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); 2485609e7984SReshma Pattan } else if (app_mode == APP_MODE_EMPTY_POLL) { 2486a137d012SLiang Ma empty_poll_stop = false; 2487a137d012SLiang Ma rte_eal_mp_remote_launch(main_empty_poll_loop, NULL, 2488a137d012SLiang Ma SKIP_MASTER); 2489609e7984SReshma Pattan } else { 2490292472baSThomas Monjalon unsigned int i; 2491292472baSThomas Monjalon 2492609e7984SReshma Pattan /* Init metrics library */ 2493609e7984SReshma Pattan rte_metrics_init(rte_socket_id()); 2494609e7984SReshma Pattan /** Register stats with metrics library */ 2495292472baSThomas Monjalon for (i = 0; i < num_telstats; i++) 2496609e7984SReshma Pattan ptr_strings[i] = telstats_strings[i].name; 2497609e7984SReshma Pattan 2498609e7984SReshma Pattan ret = rte_metrics_reg_names(ptr_strings, num_telstats); 2499609e7984SReshma Pattan if (ret >= 0) 2500609e7984SReshma Pattan telstats_index = ret; 2501609e7984SReshma Pattan else 2502609e7984SReshma Pattan rte_exit(EXIT_FAILURE, "failed to register metrics names"); 2503609e7984SReshma Pattan 2504609e7984SReshma Pattan RTE_LCORE_FOREACH_SLAVE(lcore_id) { 2505609e7984SReshma Pattan rte_spinlock_init(&stats[lcore_id].telemetry_lock); 2506609e7984SReshma Pattan } 2507609e7984SReshma Pattan rte_timer_init(&telemetry_timer); 2508609e7984SReshma Pattan rte_eal_mp_remote_launch(main_telemetry_loop, NULL, 2509609e7984SReshma Pattan SKIP_MASTER); 2510a137d012SLiang Ma } 2511a137d012SLiang Ma 2512609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL || app_mode == APP_MODE_TELEMETRY) 2513a137d012SLiang Ma launch_timer(rte_lcore_id()); 2514a137d012SLiang Ma 2515d7937e2eSIntel RTE_LCORE_FOREACH_SLAVE(lcore_id) { 2516d7937e2eSIntel if (rte_eal_wait_lcore(lcore_id) < 0) 2517d7937e2eSIntel return -1; 2518d7937e2eSIntel } 2519d7937e2eSIntel 2520609e7984SReshma Pattan if (app_mode == APP_MODE_EMPTY_POLL) 2521a137d012SLiang Ma rte_power_empty_poll_stat_free(); 2522a137d012SLiang Ma 2523d7937e2eSIntel return 0; 2524d7937e2eSIntel } 2525