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_cycles.h> 28d7937e2eSIntel #include <rte_prefetch.h> 29d7937e2eSIntel #include <rte_lcore.h> 30d7937e2eSIntel #include <rte_per_lcore.h> 31d7937e2eSIntel #include <rte_branch_prediction.h> 32d7937e2eSIntel #include <rte_interrupts.h> 33d7937e2eSIntel #include <rte_random.h> 34d7937e2eSIntel #include <rte_debug.h> 35d7937e2eSIntel #include <rte_ether.h> 36d7937e2eSIntel #include <rte_ethdev.h> 37d7937e2eSIntel #include <rte_mempool.h> 38d7937e2eSIntel #include <rte_mbuf.h> 39d7937e2eSIntel #include <rte_ip.h> 40d7937e2eSIntel #include <rte_tcp.h> 41d7937e2eSIntel #include <rte_udp.h> 42d7937e2eSIntel #include <rte_string_fns.h> 43d7937e2eSIntel #include <rte_timer.h> 44f30a1bbdSSivaprasad Tummala #include <rte_power_cpufreq.h> 45aee3bc79SCunming Liang #include <rte_spinlock.h> 46609e7984SReshma Pattan #include <rte_metrics.h> 47a35919a1SCiara Power #include <rte_telemetry.h> 4826fe454eSLiang Ma #include <rte_power_pmd_mgmt.h> 49ac1edcb6SSivaprasad Tummala #include <rte_power_uncore.h> 504d23d39fSHuisong Li #include <rte_power_qos.h> 51d7937e2eSIntel 52f88e7c17SRadu Nicolau #include "perf_core.h" 53f88e7c17SRadu Nicolau #include "main.h" 54f88e7c17SRadu Nicolau 558bae59edSStephen Hemminger RTE_LOG_REGISTER(l3fwd_power_logtype, l3fwd.power, INFO); 568bae59edSStephen Hemminger #define RTE_LOGTYPE_L3FWD_POWER l3fwd_power_logtype 57d7937e2eSIntel 58d7937e2eSIntel #define MAX_PKT_BURST 32 59d7937e2eSIntel 60aee3bc79SCunming Liang #define MIN_ZERO_POLL_COUNT 10 61d7937e2eSIntel 62d7937e2eSIntel /* 100 ms interval */ 63d7937e2eSIntel #define TIMER_NUMBER_PER_SECOND 10 64a137d012SLiang Ma /* (10ms) */ 65a137d012SLiang Ma #define INTERVALS_PER_SECOND 100 66d7937e2eSIntel /* 100000 us */ 67d7937e2eSIntel #define SCALING_PERIOD (1000000/TIMER_NUMBER_PER_SECOND) 68d7937e2eSIntel #define SCALING_DOWN_TIME_RATIO_THRESHOLD 0.25 69d7937e2eSIntel 70d7937e2eSIntel #define APP_LOOKUP_EXACT_MATCH 0 71d7937e2eSIntel #define APP_LOOKUP_LPM 1 72d7937e2eSIntel #define DO_RFC_1812_CHECKS 73d7937e2eSIntel 74d7937e2eSIntel #ifndef APP_LOOKUP_METHOD 75d7937e2eSIntel #define APP_LOOKUP_METHOD APP_LOOKUP_LPM 76d7937e2eSIntel #endif 77d7937e2eSIntel 78d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 79d7937e2eSIntel #include <rte_hash.h> 80d7937e2eSIntel #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 81d7937e2eSIntel #include <rte_lpm.h> 82d7937e2eSIntel #else 83d7937e2eSIntel #error "APP_LOOKUP_METHOD set to incorrect value" 84d7937e2eSIntel #endif 85d7937e2eSIntel 86d7937e2eSIntel #ifndef IPv6_BYTES 87d7937e2eSIntel #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ 88d7937e2eSIntel "%02x%02x:%02x%02x:%02x%02x:%02x%02x" 89d7937e2eSIntel #define IPv6_BYTES(addr) \ 90d7937e2eSIntel addr[0], addr[1], addr[2], addr[3], \ 91d7937e2eSIntel addr[4], addr[5], addr[6], addr[7], \ 92d7937e2eSIntel addr[8], addr[9], addr[10], addr[11],\ 93d7937e2eSIntel addr[12], addr[13],addr[14], addr[15] 94d7937e2eSIntel #endif 95d7937e2eSIntel 96d7937e2eSIntel #define MAX_JUMBO_PKT_LEN 9600 97d7937e2eSIntel 98d7937e2eSIntel #define IPV6_ADDR_LEN 16 99d7937e2eSIntel 100d7937e2eSIntel #define MEMPOOL_CACHE_SIZE 256 101d7937e2eSIntel 102d7937e2eSIntel /* 103d7937e2eSIntel * This expression is used to calculate the number of mbufs needed depending on 104d7937e2eSIntel * user input, taking into account memory for rx and tx hardware rings, cache 105d7937e2eSIntel * per lcore and mtable per port per lcore. RTE_MAX is used to ensure that 106d7937e2eSIntel * NB_MBUF never goes below a minimum value of 8192. 107d7937e2eSIntel */ 108d7937e2eSIntel 109d7937e2eSIntel #define NB_MBUF RTE_MAX ( \ 11060efb44fSRoman Zhukov (nb_ports*nb_rx_queue*nb_rxd + \ 111d7937e2eSIntel nb_ports*nb_lcores*MAX_PKT_BURST + \ 11260efb44fSRoman Zhukov nb_ports*n_tx_queue*nb_txd + \ 113d7937e2eSIntel nb_lcores*MEMPOOL_CACHE_SIZE), \ 114d7937e2eSIntel (unsigned)8192) 115d7937e2eSIntel 116d7937e2eSIntel #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 117d7937e2eSIntel 118d7937e2eSIntel #define NB_SOCKETS 8 119d7937e2eSIntel 120d7937e2eSIntel /* Configure how many packets ahead to prefetch, when reading packets */ 121d7937e2eSIntel #define PREFETCH_OFFSET 3 122d7937e2eSIntel 123d7937e2eSIntel /* 124d7937e2eSIntel * Configurable number of RX/TX ring descriptors 125d7937e2eSIntel */ 1264ed89049SDavid Marchand #define RX_DESC_DEFAULT 1024 1274ed89049SDavid Marchand #define TX_DESC_DEFAULT 1024 128a137d012SLiang Ma 129a35919a1SCiara Power #define NUM_TELSTATS RTE_DIM(telstats_strings) 130a137d012SLiang Ma 1314ed89049SDavid Marchand static uint16_t nb_rxd = RX_DESC_DEFAULT; 1324ed89049SDavid Marchand static uint16_t nb_txd = TX_DESC_DEFAULT; 133d7937e2eSIntel 134d7937e2eSIntel /* ethernet addresses of ports */ 1356d13ea8eSOlivier Matz static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 136d7937e2eSIntel 137aee3bc79SCunming Liang /* ethernet addresses of ports */ 138aee3bc79SCunming Liang static rte_spinlock_t locks[RTE_MAX_ETHPORTS]; 139aee3bc79SCunming Liang 140d7937e2eSIntel /* mask of enabled ports */ 141d7937e2eSIntel static uint32_t enabled_port_mask = 0; 142d7937e2eSIntel /* Ports set in promiscuous mode off by default. */ 143d7937e2eSIntel static int promiscuous_on = 0; 144d7937e2eSIntel /* NUMA is enabled by default. */ 145d7937e2eSIntel static int numa_on = 1; 146609e7984SReshma Pattan volatile bool quit_signal; 147609e7984SReshma Pattan /* timer to update telemetry every 500ms */ 148609e7984SReshma Pattan static struct rte_timer telemetry_timer; 149609e7984SReshma Pattan 150609e7984SReshma Pattan /* stats index returned by metrics lib */ 151609e7984SReshma Pattan int telstats_index; 152609e7984SReshma Pattan 15310db2a5bSTadhg Kearney /* flag to check if uncore option enabled */ 15410db2a5bSTadhg Kearney int enabled_uncore = -1; 15510db2a5bSTadhg Kearney 156609e7984SReshma Pattan struct telstats_name { 157609e7984SReshma Pattan char name[RTE_ETH_XSTATS_NAME_SIZE]; 158609e7984SReshma Pattan }; 159609e7984SReshma Pattan 160609e7984SReshma Pattan /* telemetry stats to be reported */ 161609e7984SReshma Pattan const struct telstats_name telstats_strings[] = { 162609e7984SReshma Pattan {"empty_poll"}, 163609e7984SReshma Pattan {"full_poll"}, 164609e7984SReshma Pattan {"busy_percent"} 165609e7984SReshma Pattan }; 166609e7984SReshma Pattan 167609e7984SReshma Pattan /* core busyness in percentage */ 168609e7984SReshma Pattan enum busy_rate { 169609e7984SReshma Pattan ZERO = 0, 170609e7984SReshma Pattan PARTIAL = 50, 171609e7984SReshma Pattan FULL = 100 172609e7984SReshma Pattan }; 173609e7984SReshma Pattan 17410db2a5bSTadhg Kearney enum uncore_choice { 17510db2a5bSTadhg Kearney UNCORE_MIN = 0, 17610db2a5bSTadhg Kearney UNCORE_MAX = 1, 17710db2a5bSTadhg Kearney UNCORE_IDX = 2 17810db2a5bSTadhg Kearney }; 17910db2a5bSTadhg Kearney 180609e7984SReshma Pattan /* reference poll count to measure core busyness */ 181609e7984SReshma Pattan #define DEFAULT_COUNT 10000 182609e7984SReshma Pattan /* 183609e7984SReshma Pattan * reference CYCLES to be used to 184609e7984SReshma Pattan * measure core busyness based on poll count 185609e7984SReshma Pattan */ 186609e7984SReshma Pattan #define MIN_CYCLES 1500000ULL 187b55d8fecSDavid Hunt #define MAX_CYCLES 22000000ULL 188609e7984SReshma Pattan 189609e7984SReshma Pattan /* (500ms) */ 190609e7984SReshma Pattan #define TELEMETRY_INTERVALS_PER_SEC 2 191a137d012SLiang Ma 19282bea466SJianfeng Tan static int parse_ptype; /**< Parse packet type using rx callback, and */ 19382bea466SJianfeng Tan /**< disabled by default */ 194d7937e2eSIntel 195609e7984SReshma Pattan enum appmode { 1962a0e2e2dSAnatoly Burakov APP_MODE_DEFAULT = 0, 1972a0e2e2dSAnatoly Burakov APP_MODE_LEGACY, 198e0194febSAnatoly Burakov APP_MODE_TELEMETRY, 19926fe454eSLiang Ma APP_MODE_INTERRUPT, 20026fe454eSLiang Ma APP_MODE_PMD_MGMT 201609e7984SReshma Pattan }; 202609e7984SReshma Pattan 203609e7984SReshma Pattan enum appmode app_mode; 204609e7984SReshma Pattan 20526fe454eSLiang Ma static enum rte_power_pmd_mgmt_type pmgmt_type; 206a9ea6070SDavid Hunt bool baseline_enabled; 20726fe454eSLiang Ma 208d7937e2eSIntel enum freq_scale_hint_t 209d7937e2eSIntel { 210d7937e2eSIntel FREQ_LOWER = -1, 211d7937e2eSIntel FREQ_CURRENT = 0, 212d7937e2eSIntel FREQ_HIGHER = 1, 213d7937e2eSIntel FREQ_HIGHEST = 2 214d7937e2eSIntel }; 215d7937e2eSIntel 2167e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_rx_queue { 217f8244c63SZhiyong Yang uint16_t port_id; 218b23c5bd7SSivaprasad Tummala uint16_t queue_id; 219d7937e2eSIntel enum freq_scale_hint_t freq_up_hint; 220d7937e2eSIntel uint32_t zero_rx_packet_count; 221d7937e2eSIntel uint32_t idle_hint; 2227e06c0deSTyler Retzlaff }; 223d7937e2eSIntel 224d7937e2eSIntel #define MAX_RX_QUEUE_PER_LCORE 16 225d7937e2eSIntel #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 226d7937e2eSIntel #define MAX_RX_QUEUE_PER_PORT 128 227d7937e2eSIntel 228aee3bc79SCunming Liang #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16 229aee3bc79SCunming Liang 230aee3bc79SCunming Liang 231f88e7c17SRadu Nicolau struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 232d7937e2eSIntel static struct lcore_params lcore_params_array_default[] = { 233d7937e2eSIntel {0, 0, 2}, 234d7937e2eSIntel {0, 1, 2}, 235d7937e2eSIntel {0, 2, 2}, 236d7937e2eSIntel {1, 0, 2}, 237d7937e2eSIntel {1, 1, 2}, 238d7937e2eSIntel {1, 2, 2}, 239d7937e2eSIntel {2, 0, 2}, 240d7937e2eSIntel {3, 0, 3}, 241d7937e2eSIntel {3, 1, 3}, 242d7937e2eSIntel }; 243d7937e2eSIntel 244f88e7c17SRadu Nicolau struct lcore_params *lcore_params = lcore_params_array_default; 2457efe28bdSPavan Nikhilesh uint16_t nb_lcore_params = RTE_DIM(lcore_params_array_default); 246d7937e2eSIntel 247d7937e2eSIntel static struct rte_eth_conf port_conf = { 248d7937e2eSIntel .rxmode = { 249295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_RX_RSS, 250295968d1SFerruh Yigit .offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM, 251d7937e2eSIntel }, 252d7937e2eSIntel .rx_adv_conf = { 253d7937e2eSIntel .rss_conf = { 254d7937e2eSIntel .rss_key = NULL, 255295968d1SFerruh Yigit .rss_hf = RTE_ETH_RSS_UDP, 256d7937e2eSIntel }, 257d7937e2eSIntel }, 258d7937e2eSIntel .txmode = { 259295968d1SFerruh Yigit .mq_mode = RTE_ETH_MQ_TX_NONE, 260f06493adSAnatoly Burakov } 261d7937e2eSIntel }; 262d7937e2eSIntel 2631bb4a528SFerruh Yigit static uint32_t max_pkt_len; 26459f2853cSKevin Laatz static uint32_t max_empty_polls = 512; 26559f2853cSKevin Laatz static uint32_t pause_duration = 1; 26659f2853cSKevin Laatz static uint32_t scale_freq_min; 26759f2853cSKevin Laatz static uint32_t scale_freq_max; 2681bb4a528SFerruh Yigit 2694d23d39fSHuisong Li static int cpu_resume_latency = -1; 2704d23d39fSHuisong Li static int resume_latency_bk[RTE_MAX_LCORE]; 2714d23d39fSHuisong Li 272d7937e2eSIntel static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; 273d7937e2eSIntel 274d7937e2eSIntel 275d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 276d7937e2eSIntel 277193f9ec5SBruce Richardson #ifdef RTE_ARCH_X86 278d7937e2eSIntel #include <rte_hash_crc.h> 279d7937e2eSIntel #define DEFAULT_HASH_FUNC rte_hash_crc 280d7937e2eSIntel #else 281d7937e2eSIntel #include <rte_jhash.h> 282d7937e2eSIntel #define DEFAULT_HASH_FUNC rte_jhash 283d7937e2eSIntel #endif 284d7937e2eSIntel 285*7f2a987cSAndre Muezerie struct __rte_packed_begin ipv4_5tuple { 286d7937e2eSIntel uint32_t ip_dst; 287d7937e2eSIntel uint32_t ip_src; 288d7937e2eSIntel uint16_t port_dst; 289d7937e2eSIntel uint16_t port_src; 290d7937e2eSIntel uint8_t proto; 291*7f2a987cSAndre Muezerie } __rte_packed_end; 292d7937e2eSIntel 293*7f2a987cSAndre Muezerie struct __rte_packed_begin ipv6_5tuple { 294d7937e2eSIntel uint8_t ip_dst[IPV6_ADDR_LEN]; 295d7937e2eSIntel uint8_t ip_src[IPV6_ADDR_LEN]; 296d7937e2eSIntel uint16_t port_dst; 297d7937e2eSIntel uint16_t port_src; 298d7937e2eSIntel uint8_t proto; 299*7f2a987cSAndre Muezerie } __rte_packed_end; 300d7937e2eSIntel 301d7937e2eSIntel struct ipv4_l3fwd_route { 302d7937e2eSIntel struct ipv4_5tuple key; 303d7937e2eSIntel uint8_t if_out; 304d7937e2eSIntel }; 305d7937e2eSIntel 306d7937e2eSIntel struct ipv6_l3fwd_route { 307d7937e2eSIntel struct ipv6_5tuple key; 308d7937e2eSIntel uint8_t if_out; 309d7937e2eSIntel }; 310d7937e2eSIntel 311d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { 3120c9da755SDavid Marchand {{RTE_IPV4(100,10,0,1), RTE_IPV4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0}, 3130c9da755SDavid Marchand {{RTE_IPV4(100,20,0,2), RTE_IPV4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1}, 3140c9da755SDavid Marchand {{RTE_IPV4(100,30,0,3), RTE_IPV4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2}, 3150c9da755SDavid Marchand {{RTE_IPV4(100,40,0,4), RTE_IPV4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3}, 316d7937e2eSIntel }; 317d7937e2eSIntel 318d7937e2eSIntel static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { 319d7937e2eSIntel { 320d7937e2eSIntel { 321d7937e2eSIntel {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 322d7937e2eSIntel 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 323d7937e2eSIntel {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 324d7937e2eSIntel 0x02, 0x1e, 0x67, 0xff, 0xfe, 0x0d, 0xb6, 0x0a}, 325d7937e2eSIntel 1, 10, IPPROTO_UDP 326d7937e2eSIntel }, 4 327d7937e2eSIntel }, 328d7937e2eSIntel }; 329d7937e2eSIntel 330d7937e2eSIntel typedef struct rte_hash lookup_struct_t; 331d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; 332d7937e2eSIntel static lookup_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; 333d7937e2eSIntel 334d7937e2eSIntel #define L3FWD_HASH_ENTRIES 1024 335d7937e2eSIntel 3367e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) uint16_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES]; 3377e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) uint16_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES]; 338d7937e2eSIntel #endif 339d7937e2eSIntel 340d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 341d7937e2eSIntel struct ipv4_l3fwd_route { 342d7937e2eSIntel uint32_t ip; 343d7937e2eSIntel uint8_t depth; 344d7937e2eSIntel uint8_t if_out; 345d7937e2eSIntel }; 346d7937e2eSIntel 347d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { 3480c9da755SDavid Marchand {RTE_IPV4(1,1,1,0), 24, 0}, 3490c9da755SDavid Marchand {RTE_IPV4(2,1,1,0), 24, 1}, 3500c9da755SDavid Marchand {RTE_IPV4(3,1,1,0), 24, 2}, 3510c9da755SDavid Marchand {RTE_IPV4(4,1,1,0), 24, 3}, 3520c9da755SDavid Marchand {RTE_IPV4(5,1,1,0), 24, 4}, 3530c9da755SDavid Marchand {RTE_IPV4(6,1,1,0), 24, 5}, 3540c9da755SDavid Marchand {RTE_IPV4(7,1,1,0), 24, 6}, 3550c9da755SDavid Marchand {RTE_IPV4(8,1,1,0), 24, 7}, 356d7937e2eSIntel }; 357d7937e2eSIntel 358d7937e2eSIntel #define IPV4_L3FWD_LPM_MAX_RULES 1024 359d7937e2eSIntel 360d7937e2eSIntel typedef struct rte_lpm lookup_struct_t; 361d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; 362d7937e2eSIntel #endif 363d7937e2eSIntel 3647e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_conf { 365d7937e2eSIntel uint16_t n_rx_queue; 366d7937e2eSIntel struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 367e2366e74STomasz Kulasek uint16_t n_tx_port; 368e2366e74STomasz Kulasek uint16_t tx_port_id[RTE_MAX_ETHPORTS]; 369d7937e2eSIntel uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; 370e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 371d7937e2eSIntel lookup_struct_t * ipv4_lookup_struct; 372d7937e2eSIntel lookup_struct_t * ipv6_lookup_struct; 3737e06c0deSTyler Retzlaff }; 374d7937e2eSIntel 3757e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_stats { 376d7937e2eSIntel /* total sleep time in ms since last frequency scaling down */ 377d7937e2eSIntel uint32_t sleep_time; 378d7937e2eSIntel /* number of long sleep recently */ 379d7937e2eSIntel uint32_t nb_long_sleep; 380d7937e2eSIntel /* freq. scaling up trend */ 381d7937e2eSIntel uint32_t trend; 382d7937e2eSIntel /* total packet processed recently */ 383d7937e2eSIntel uint64_t nb_rx_processed; 384d7937e2eSIntel /* total iterations looped recently */ 385d7937e2eSIntel uint64_t nb_iteration_looped; 386609e7984SReshma Pattan /* 387609e7984SReshma Pattan * Represents empty and non empty polls 388609e7984SReshma Pattan * of rte_eth_rx_burst(); 389609e7984SReshma Pattan * ep_nep[0] holds non empty polls 390609e7984SReshma Pattan * i.e. 0 < nb_rx <= MAX_BURST 391609e7984SReshma Pattan * ep_nep[1] holds empty polls. 392609e7984SReshma Pattan * i.e. nb_rx == 0 393609e7984SReshma Pattan */ 394609e7984SReshma Pattan uint64_t ep_nep[2]; 395609e7984SReshma Pattan /* 396609e7984SReshma Pattan * Represents full and empty+partial 397609e7984SReshma Pattan * polls of rte_eth_rx_burst(); 398609e7984SReshma Pattan * ep_nep[0] holds empty+partial polls. 399609e7984SReshma Pattan * i.e. 0 <= nb_rx < MAX_BURST 400609e7984SReshma Pattan * ep_nep[1] holds full polls 401609e7984SReshma Pattan * i.e. nb_rx == MAX_BURST 402609e7984SReshma Pattan */ 403609e7984SReshma Pattan uint64_t fp_nfp[2]; 404609e7984SReshma Pattan enum busy_rate br; 405609e7984SReshma Pattan rte_spinlock_t telemetry_lock; 4067e06c0deSTyler Retzlaff }; 407d7937e2eSIntel 4087e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 4097e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) struct lcore_stats stats[RTE_MAX_LCORE]; 410d7937e2eSIntel static struct rte_timer power_timers[RTE_MAX_LCORE]; 411d7937e2eSIntel 412d7937e2eSIntel static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count); 413d7937e2eSIntel static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \ 414f8244c63SZhiyong Yang unsigned int lcore_id, uint16_t port_id, uint16_t queue_id); 415d7937e2eSIntel 416a137d012SLiang Ma static int is_done(void) 417a137d012SLiang Ma { 418609e7984SReshma Pattan return quit_signal; 419a137d012SLiang Ma } 420a137d012SLiang Ma 421d7937e2eSIntel /* exit signal handler */ 422d7937e2eSIntel static void 423d7937e2eSIntel signal_exit_now(int sigtype) 424d7937e2eSIntel { 425d7937e2eSIntel 426613ce669SAnatoly Burakov if (sigtype == SIGINT) 427609e7984SReshma Pattan quit_signal = true; 428a137d012SLiang Ma 429d7937e2eSIntel } 430d7937e2eSIntel 4317be78d02SJosh Soref /* Frequency scale down timer callback */ 432d7937e2eSIntel static void 433f2fc83b4SThomas Monjalon power_timer_cb(__rte_unused struct rte_timer *tim, 434f2fc83b4SThomas Monjalon __rte_unused void *arg) 435d7937e2eSIntel { 436d7937e2eSIntel uint64_t hz; 437d7937e2eSIntel float sleep_time_ratio; 438d7937e2eSIntel unsigned lcore_id = rte_lcore_id(); 439d7937e2eSIntel 440d7937e2eSIntel /* accumulate total execution time in us when callback is invoked */ 441d7937e2eSIntel sleep_time_ratio = (float)(stats[lcore_id].sleep_time) / 442d7937e2eSIntel (float)SCALING_PERIOD; 443d7937e2eSIntel /** 444d7937e2eSIntel * check whether need to scale down frequency a step if it sleep a lot. 445d7937e2eSIntel */ 446aee3bc79SCunming Liang if (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) { 447d7937e2eSIntel rte_power_freq_down(lcore_id); 448aee3bc79SCunming Liang } 449d7937e2eSIntel else if ( (unsigned)(stats[lcore_id].nb_rx_processed / 450aee3bc79SCunming Liang stats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) { 451d7937e2eSIntel /** 452d7937e2eSIntel * scale down a step if average packet per iteration less 453d7937e2eSIntel * than expectation. 454d7937e2eSIntel */ 455d7937e2eSIntel rte_power_freq_down(lcore_id); 456aee3bc79SCunming Liang } 457d7937e2eSIntel 458d7937e2eSIntel /** 459d7937e2eSIntel * initialize another timer according to current frequency to ensure 460d7937e2eSIntel * timer interval is relatively fixed. 461d7937e2eSIntel */ 462d7937e2eSIntel hz = rte_get_timer_hz(); 463d7937e2eSIntel rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, 464d7937e2eSIntel SINGLE, lcore_id, power_timer_cb, NULL); 465d7937e2eSIntel 466d7937e2eSIntel stats[lcore_id].nb_rx_processed = 0; 467d7937e2eSIntel stats[lcore_id].nb_iteration_looped = 0; 468d7937e2eSIntel 469d7937e2eSIntel stats[lcore_id].sleep_time = 0; 470d7937e2eSIntel } 471d7937e2eSIntel 472d7937e2eSIntel /* Enqueue a single packet, and send burst if queue is filled */ 473d7937e2eSIntel static inline int 47447523597SZhiyong Yang send_single_packet(struct rte_mbuf *m, uint16_t port) 475d7937e2eSIntel { 476d7937e2eSIntel uint32_t lcore_id; 477d7937e2eSIntel struct lcore_conf *qconf; 478d7937e2eSIntel 479d7937e2eSIntel lcore_id = rte_lcore_id(); 480d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 481d7937e2eSIntel 482e2366e74STomasz Kulasek rte_eth_tx_buffer(port, qconf->tx_queue_id[port], 483e2366e74STomasz Kulasek qconf->tx_buffer[port], m); 484d7937e2eSIntel 485d7937e2eSIntel return 0; 486d7937e2eSIntel } 487d7937e2eSIntel 488d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 489d7937e2eSIntel static inline int 490a7c528e5SOlivier Matz is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len) 491d7937e2eSIntel { 492d7937e2eSIntel /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ 493d7937e2eSIntel /* 494d7937e2eSIntel * 1. The packet length reported by the Link Layer must be large 495d7937e2eSIntel * enough to hold the minimum length legal IP datagram (20 bytes). 496d7937e2eSIntel */ 497a7c528e5SOlivier Matz if (link_len < sizeof(struct rte_ipv4_hdr)) 498d7937e2eSIntel return -1; 499d7937e2eSIntel 500d7937e2eSIntel /* 2. The IP checksum must be correct. */ 501f0b00d98SMiao Li /* if this is not checked in H/W, check it. */ 502f0b00d98SMiao Li if ((port_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) == 0) { 503f0b00d98SMiao Li uint16_t actual_cksum, expected_cksum; 504f0b00d98SMiao Li actual_cksum = pkt->hdr_checksum; 505f0b00d98SMiao Li pkt->hdr_checksum = 0; 506f0b00d98SMiao Li expected_cksum = rte_ipv4_cksum(pkt); 507f0b00d98SMiao Li if (actual_cksum != expected_cksum) 508f0b00d98SMiao Li return -2; 509f0b00d98SMiao Li } 510d7937e2eSIntel 511d7937e2eSIntel /* 512d7937e2eSIntel * 3. The IP version number must be 4. If the version number is not 4 513d7937e2eSIntel * then the packet may be another version of IP, such as IPng or 514d7937e2eSIntel * ST-II. 515d7937e2eSIntel */ 516d7937e2eSIntel if (((pkt->version_ihl) >> 4) != 4) 517d7937e2eSIntel return -3; 518d7937e2eSIntel /* 519d7937e2eSIntel * 4. The IP header length field must be large enough to hold the 520d7937e2eSIntel * minimum length legal IP datagram (20 bytes = 5 words). 521d7937e2eSIntel */ 522d7937e2eSIntel if ((pkt->version_ihl & 0xf) < 5) 523d7937e2eSIntel return -4; 524d7937e2eSIntel 525d7937e2eSIntel /* 526d7937e2eSIntel * 5. The IP total length field must be large enough to hold the IP 527d7937e2eSIntel * datagram header, whose length is specified in the IP header length 528d7937e2eSIntel * field. 529d7937e2eSIntel */ 530a7c528e5SOlivier Matz if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) 531d7937e2eSIntel return -5; 532d7937e2eSIntel 533d7937e2eSIntel return 0; 534d7937e2eSIntel } 535d7937e2eSIntel #endif 536d7937e2eSIntel 537d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 538d7937e2eSIntel static void 539d7937e2eSIntel print_ipv4_key(struct ipv4_5tuple key) 540d7937e2eSIntel { 541d7937e2eSIntel printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, " 542d7937e2eSIntel "proto = %d\n", (unsigned)key.ip_dst, (unsigned)key.ip_src, 543d7937e2eSIntel key.port_dst, key.port_src, key.proto); 544d7937e2eSIntel } 545d7937e2eSIntel static void 546d7937e2eSIntel print_ipv6_key(struct ipv6_5tuple key) 547d7937e2eSIntel { 548d7937e2eSIntel printf( "IP dst = " IPv6_BYTES_FMT ", IP src = " IPv6_BYTES_FMT ", " 549d7937e2eSIntel "port dst = %d, port src = %d, proto = %d\n", 550d7937e2eSIntel IPv6_BYTES(key.ip_dst), IPv6_BYTES(key.ip_src), 551d7937e2eSIntel key.port_dst, key.port_src, key.proto); 552d7937e2eSIntel } 553d7937e2eSIntel 554f8244c63SZhiyong Yang static inline uint16_t 555a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, 556d7937e2eSIntel lookup_struct_t * ipv4_l3fwd_lookup_struct) 557d7937e2eSIntel { 558d7937e2eSIntel struct ipv4_5tuple key; 559f41b5156SOlivier Matz struct rte_tcp_hdr *tcp; 560e73e3547SOlivier Matz struct rte_udp_hdr *udp; 561d7937e2eSIntel int ret = 0; 562d7937e2eSIntel 563d7937e2eSIntel key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); 564d7937e2eSIntel key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr); 565d7937e2eSIntel key.proto = ipv4_hdr->next_proto_id; 566d7937e2eSIntel 567d7937e2eSIntel switch (ipv4_hdr->next_proto_id) { 568d7937e2eSIntel case IPPROTO_TCP: 569f41b5156SOlivier Matz tcp = (struct rte_tcp_hdr *)((unsigned char *)ipv4_hdr + 570a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr)); 571d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(tcp->dst_port); 572d7937e2eSIntel key.port_src = rte_be_to_cpu_16(tcp->src_port); 573d7937e2eSIntel break; 574d7937e2eSIntel 575d7937e2eSIntel case IPPROTO_UDP: 576e73e3547SOlivier Matz udp = (struct rte_udp_hdr *)((unsigned char *)ipv4_hdr + 577a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr)); 578d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(udp->dst_port); 579d7937e2eSIntel key.port_src = rte_be_to_cpu_16(udp->src_port); 580d7937e2eSIntel break; 581d7937e2eSIntel 582d7937e2eSIntel default: 583d7937e2eSIntel key.port_dst = 0; 584d7937e2eSIntel key.port_src = 0; 585d7937e2eSIntel break; 586d7937e2eSIntel } 587d7937e2eSIntel 588d7937e2eSIntel /* Find destination port */ 589d7937e2eSIntel ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key); 590f8244c63SZhiyong Yang return ((ret < 0) ? portid : ipv4_l3fwd_out_if[ret]); 591d7937e2eSIntel } 592d7937e2eSIntel 593f8244c63SZhiyong Yang static inline uint16_t 594a7c528e5SOlivier Matz get_ipv6_dst_port(struct rte_ipv6_hdr *ipv6_hdr, uint16_t portid, 595d7937e2eSIntel lookup_struct_t *ipv6_l3fwd_lookup_struct) 596d7937e2eSIntel { 597d7937e2eSIntel struct ipv6_5tuple key; 598f41b5156SOlivier Matz struct rte_tcp_hdr *tcp; 599e73e3547SOlivier Matz struct rte_udp_hdr *udp; 600d7937e2eSIntel int ret = 0; 601d7937e2eSIntel 602d7937e2eSIntel memcpy(key.ip_dst, ipv6_hdr->dst_addr, IPV6_ADDR_LEN); 603d7937e2eSIntel memcpy(key.ip_src, ipv6_hdr->src_addr, IPV6_ADDR_LEN); 604d7937e2eSIntel 605d7937e2eSIntel key.proto = ipv6_hdr->proto; 606d7937e2eSIntel 607d7937e2eSIntel switch (ipv6_hdr->proto) { 608d7937e2eSIntel case IPPROTO_TCP: 609f41b5156SOlivier Matz tcp = (struct rte_tcp_hdr *)((unsigned char *) ipv6_hdr + 610a7c528e5SOlivier Matz sizeof(struct rte_ipv6_hdr)); 611d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(tcp->dst_port); 612d7937e2eSIntel key.port_src = rte_be_to_cpu_16(tcp->src_port); 613d7937e2eSIntel break; 614d7937e2eSIntel 615d7937e2eSIntel case IPPROTO_UDP: 616e73e3547SOlivier Matz udp = (struct rte_udp_hdr *)((unsigned char *) ipv6_hdr + 617a7c528e5SOlivier Matz sizeof(struct rte_ipv6_hdr)); 618d7937e2eSIntel key.port_dst = rte_be_to_cpu_16(udp->dst_port); 619d7937e2eSIntel key.port_src = rte_be_to_cpu_16(udp->src_port); 620d7937e2eSIntel break; 621d7937e2eSIntel 622d7937e2eSIntel default: 623d7937e2eSIntel key.port_dst = 0; 624d7937e2eSIntel key.port_src = 0; 625d7937e2eSIntel break; 626d7937e2eSIntel } 627d7937e2eSIntel 628d7937e2eSIntel /* Find destination port */ 629d7937e2eSIntel ret = rte_hash_lookup(ipv6_l3fwd_lookup_struct, (const void *)&key); 630f8244c63SZhiyong Yang return ((ret < 0) ? portid : ipv6_l3fwd_out_if[ret]); 631d7937e2eSIntel } 632d7937e2eSIntel #endif 633d7937e2eSIntel 634d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 635f8244c63SZhiyong Yang static inline uint16_t 636a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, 637d7937e2eSIntel lookup_struct_t *ipv4_l3fwd_lookup_struct) 638d7937e2eSIntel { 639dc81ebbaSMichal Kobylinski uint32_t next_hop; 640d7937e2eSIntel 641f8244c63SZhiyong Yang return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, 642d7937e2eSIntel rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? 643d7937e2eSIntel next_hop : portid); 644d7937e2eSIntel } 645d7937e2eSIntel #endif 646d7937e2eSIntel 647d7937e2eSIntel static inline void 64882bea466SJianfeng Tan parse_ptype_one(struct rte_mbuf *m) 64982bea466SJianfeng Tan { 6506d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 65182bea466SJianfeng Tan uint32_t packet_type = RTE_PTYPE_UNKNOWN; 65282bea466SJianfeng Tan uint16_t ether_type; 65382bea466SJianfeng Tan 6546d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 65582bea466SJianfeng Tan ether_type = eth_hdr->ether_type; 6560c9da755SDavid Marchand if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) 65782bea466SJianfeng Tan packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN; 6580c9da755SDavid Marchand else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) 65982bea466SJianfeng Tan packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; 66082bea466SJianfeng Tan 66182bea466SJianfeng Tan m->packet_type = packet_type; 66282bea466SJianfeng Tan } 66382bea466SJianfeng Tan 66482bea466SJianfeng Tan static uint16_t 665f8244c63SZhiyong Yang cb_parse_ptype(uint16_t port __rte_unused, uint16_t queue __rte_unused, 66682bea466SJianfeng Tan struct rte_mbuf *pkts[], uint16_t nb_pkts, 66782bea466SJianfeng Tan uint16_t max_pkts __rte_unused, 66882bea466SJianfeng Tan void *user_param __rte_unused) 66982bea466SJianfeng Tan { 67082bea466SJianfeng Tan unsigned int i; 67182bea466SJianfeng Tan 67282bea466SJianfeng Tan for (i = 0; i < nb_pkts; ++i) 67382bea466SJianfeng Tan parse_ptype_one(pkts[i]); 67482bea466SJianfeng Tan 67582bea466SJianfeng Tan return nb_pkts; 67682bea466SJianfeng Tan } 67782bea466SJianfeng Tan 67882bea466SJianfeng Tan static int 679f8244c63SZhiyong Yang add_cb_parse_ptype(uint16_t portid, uint16_t queueid) 68082bea466SJianfeng Tan { 68182bea466SJianfeng Tan printf("Port %d: softly parse packet type info\n", portid); 68282bea466SJianfeng Tan if (rte_eth_add_rx_callback(portid, queueid, cb_parse_ptype, NULL)) 68382bea466SJianfeng Tan return 0; 68482bea466SJianfeng Tan 68582bea466SJianfeng Tan printf("Failed to add rx callback: port=%d\n", portid); 68682bea466SJianfeng Tan return -1; 68782bea466SJianfeng Tan } 68882bea466SJianfeng Tan 68982bea466SJianfeng Tan static inline void 69047523597SZhiyong Yang l3fwd_simple_forward(struct rte_mbuf *m, uint16_t portid, 691d7937e2eSIntel struct lcore_conf *qconf) 692d7937e2eSIntel { 6936d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 694a7c528e5SOlivier Matz struct rte_ipv4_hdr *ipv4_hdr; 695d7937e2eSIntel void *d_addr_bytes; 696f8244c63SZhiyong Yang uint16_t dst_port; 697d7937e2eSIntel 6986d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); 699d7937e2eSIntel 7003c0184ccSHelin Zhang if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { 701d7937e2eSIntel /* Handle IPv4 headers.*/ 702d7937e2eSIntel ipv4_hdr = 703a7c528e5SOlivier Matz rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, 7046d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr)); 705d7937e2eSIntel 706d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 707d7937e2eSIntel /* Check to make sure the packet is valid (RFC1812) */ 708ea672a8bSOlivier Matz if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { 709d7937e2eSIntel rte_pktmbuf_free(m); 710d7937e2eSIntel return; 711d7937e2eSIntel } 712d7937e2eSIntel #endif 713d7937e2eSIntel 714d7937e2eSIntel dst_port = get_ipv4_dst_port(ipv4_hdr, portid, 715d7937e2eSIntel qconf->ipv4_lookup_struct); 716d7937e2eSIntel if (dst_port >= RTE_MAX_ETHPORTS || 717d7937e2eSIntel (enabled_port_mask & 1 << dst_port) == 0) 718d7937e2eSIntel dst_port = portid; 719d7937e2eSIntel 720d7937e2eSIntel /* 02:00:00:00:00:xx */ 72104d43857SDmitry Kozlyuk d_addr_bytes = ð_hdr->dst_addr.addr_bytes[0]; 722d7937e2eSIntel *((uint64_t *)d_addr_bytes) = 723d7937e2eSIntel 0x000000000002 + ((uint64_t)dst_port << 40); 724d7937e2eSIntel 725d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS 726d7937e2eSIntel /* Update time to live and header checksum */ 727d7937e2eSIntel --(ipv4_hdr->time_to_live); 728d7937e2eSIntel ++(ipv4_hdr->hdr_checksum); 729d7937e2eSIntel #endif 730d7937e2eSIntel 731d7937e2eSIntel /* src addr */ 732538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port], 73304d43857SDmitry Kozlyuk ð_hdr->src_addr); 734d7937e2eSIntel 735d7937e2eSIntel send_single_packet(m, dst_port); 7363c0184ccSHelin Zhang } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { 737d7937e2eSIntel /* Handle IPv6 headers.*/ 738d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 739a7c528e5SOlivier Matz struct rte_ipv6_hdr *ipv6_hdr; 740d7937e2eSIntel 741d7937e2eSIntel ipv6_hdr = 742a7c528e5SOlivier Matz rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, 7436d13ea8eSOlivier Matz sizeof(struct rte_ether_hdr)); 744d7937e2eSIntel 745d7937e2eSIntel dst_port = get_ipv6_dst_port(ipv6_hdr, portid, 746d7937e2eSIntel qconf->ipv6_lookup_struct); 747d7937e2eSIntel 748d7937e2eSIntel if (dst_port >= RTE_MAX_ETHPORTS || 749d7937e2eSIntel (enabled_port_mask & 1 << dst_port) == 0) 750d7937e2eSIntel dst_port = portid; 751d7937e2eSIntel 752d7937e2eSIntel /* 02:00:00:00:00:xx */ 75304d43857SDmitry Kozlyuk d_addr_bytes = ð_hdr->dst_addr.addr_bytes[0]; 754d7937e2eSIntel *((uint64_t *)d_addr_bytes) = 755d7937e2eSIntel 0x000000000002 + ((uint64_t)dst_port << 40); 756d7937e2eSIntel 757d7937e2eSIntel /* src addr */ 758538da7a1SOlivier Matz rte_ether_addr_copy(&ports_eth_addr[dst_port], 75904d43857SDmitry Kozlyuk ð_hdr->src_addr); 760d7937e2eSIntel 761d7937e2eSIntel send_single_packet(m, dst_port); 762d7937e2eSIntel #else 763d7937e2eSIntel /* We don't currently handle IPv6 packets in LPM mode. */ 764d7937e2eSIntel rte_pktmbuf_free(m); 765d7937e2eSIntel #endif 766bec2f7dfSShaopeng He } else 767bec2f7dfSShaopeng He rte_pktmbuf_free(m); 768d7937e2eSIntel 769d7937e2eSIntel } 770d7937e2eSIntel 771aee3bc79SCunming Liang #define MINIMUM_SLEEP_TIME 1 772aee3bc79SCunming Liang #define SUSPEND_THRESHOLD 300 773d7937e2eSIntel 774d7937e2eSIntel static inline uint32_t 775d7937e2eSIntel power_idle_heuristic(uint32_t zero_rx_packet_count) 776d7937e2eSIntel { 777aee3bc79SCunming Liang /* If zero count is less than 100, sleep 1us */ 778aee3bc79SCunming Liang if (zero_rx_packet_count < SUSPEND_THRESHOLD) 779aee3bc79SCunming Liang return MINIMUM_SLEEP_TIME; 780aee3bc79SCunming Liang /* If zero count is less than 1000, sleep 100 us which is the 781aee3bc79SCunming Liang minimum latency switching from C3/C6 to C0 782aee3bc79SCunming Liang */ 783aee3bc79SCunming Liang else 784aee3bc79SCunming Liang return SUSPEND_THRESHOLD; 785d7937e2eSIntel } 786d7937e2eSIntel 787d7937e2eSIntel static inline enum freq_scale_hint_t 788b451aa39SIntel power_freq_scaleup_heuristic(unsigned lcore_id, 789f8244c63SZhiyong Yang uint16_t port_id, 790b451aa39SIntel uint16_t queue_id) 791d7937e2eSIntel { 79247d834baSNikhil Agarwal uint32_t rxq_count = rte_eth_rx_queue_count(port_id, queue_id); 793d7937e2eSIntel /** 794d7937e2eSIntel * HW Rx queue size is 128 by default, Rx burst read at maximum 32 entries 795d7937e2eSIntel * per iteration 796d7937e2eSIntel */ 797d7937e2eSIntel #define FREQ_GEAR1_RX_PACKET_THRESHOLD MAX_PKT_BURST 798b451aa39SIntel #define FREQ_GEAR2_RX_PACKET_THRESHOLD (MAX_PKT_BURST*2) 799b451aa39SIntel #define FREQ_GEAR3_RX_PACKET_THRESHOLD (MAX_PKT_BURST*3) 800d7937e2eSIntel #define FREQ_UP_TREND1_ACC 1 801d7937e2eSIntel #define FREQ_UP_TREND2_ACC 100 802d7937e2eSIntel #define FREQ_UP_THRESHOLD 10000 803d7937e2eSIntel 80447d834baSNikhil Agarwal if (likely(rxq_count > FREQ_GEAR3_RX_PACKET_THRESHOLD)) { 805d7937e2eSIntel stats[lcore_id].trend = 0; 806d7937e2eSIntel return FREQ_HIGHEST; 80747d834baSNikhil Agarwal } else if (likely(rxq_count > FREQ_GEAR2_RX_PACKET_THRESHOLD)) 808d7937e2eSIntel stats[lcore_id].trend += FREQ_UP_TREND2_ACC; 80947d834baSNikhil Agarwal else if (likely(rxq_count > FREQ_GEAR1_RX_PACKET_THRESHOLD)) 810d7937e2eSIntel stats[lcore_id].trend += FREQ_UP_TREND1_ACC; 811d7937e2eSIntel 812b451aa39SIntel if (likely(stats[lcore_id].trend > FREQ_UP_THRESHOLD)) { 813d7937e2eSIntel stats[lcore_id].trend = 0; 814d7937e2eSIntel return FREQ_HIGHER; 815d7937e2eSIntel } 816d7937e2eSIntel 817d7937e2eSIntel return FREQ_CURRENT; 818d7937e2eSIntel } 819d7937e2eSIntel 820aee3bc79SCunming Liang /** 821aee3bc79SCunming Liang * force polling thread sleep until one-shot rx interrupt triggers 822aee3bc79SCunming Liang * @param port_id 823aee3bc79SCunming Liang * Port id. 824aee3bc79SCunming Liang * @param queue_id 825aee3bc79SCunming Liang * Rx queue id. 826aee3bc79SCunming Liang * @return 827aee3bc79SCunming Liang * 0 on success 828aee3bc79SCunming Liang */ 829aee3bc79SCunming Liang static int 830317a1da8SAnatoly Burakov sleep_until_rx_interrupt(int num, int lcore) 831aee3bc79SCunming Liang { 832f4d1e19cSAnatoly Burakov /* 833f4d1e19cSAnatoly Burakov * we want to track when we are woken up by traffic so that we can go 834317a1da8SAnatoly Burakov * back to sleep again without log spamming. Avoid cache line sharing 835317a1da8SAnatoly Burakov * to prevent threads stepping on each others' toes. 836f4d1e19cSAnatoly Burakov */ 8377e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) struct { 838317a1da8SAnatoly Burakov bool wakeup; 8397e06c0deSTyler Retzlaff } status[RTE_MAX_LCORE]; 840aee3bc79SCunming Liang struct rte_epoll_event event[num]; 841aee3bc79SCunming Liang int n, i; 842f8244c63SZhiyong Yang uint16_t port_id; 843b23c5bd7SSivaprasad Tummala uint16_t queue_id; 844aee3bc79SCunming Liang void *data; 845aee3bc79SCunming Liang 846317a1da8SAnatoly Burakov if (status[lcore].wakeup) { 847aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, 848aee3bc79SCunming Liang "lcore %u sleeps until interrupt triggers\n", 849aee3bc79SCunming Liang rte_lcore_id()); 850f4d1e19cSAnatoly Burakov } 851aee3bc79SCunming Liang 852f4d1e19cSAnatoly Burakov n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, 10); 853aee3bc79SCunming Liang for (i = 0; i < n; i++) { 854aee3bc79SCunming Liang data = event[i].epdata.data; 855b23c5bd7SSivaprasad Tummala port_id = ((uintptr_t)data) >> (sizeof(uint16_t) * CHAR_BIT); 856aee3bc79SCunming Liang queue_id = ((uintptr_t)data) & 857b23c5bd7SSivaprasad Tummala RTE_LEN2MASK((sizeof(uint16_t) * CHAR_BIT), uint16_t); 858aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, 859aee3bc79SCunming Liang "lcore %u is waked up from rx interrupt on" 860aee3bc79SCunming Liang " port %d queue %d\n", 861aee3bc79SCunming Liang rte_lcore_id(), port_id, queue_id); 862aee3bc79SCunming Liang } 863317a1da8SAnatoly Burakov status[lcore].wakeup = n != 0; 864aee3bc79SCunming Liang 865aee3bc79SCunming Liang return 0; 866aee3bc79SCunming Liang } 867aee3bc79SCunming Liang 86849dcf7b9SXiao Wang static void turn_on_off_intr(struct lcore_conf *qconf, bool on) 869aee3bc79SCunming Liang { 870aee3bc79SCunming Liang int i; 871aee3bc79SCunming Liang struct lcore_rx_queue *rx_queue; 872b23c5bd7SSivaprasad Tummala uint16_t queue_id; 873f8244c63SZhiyong Yang uint16_t port_id; 874aee3bc79SCunming Liang 875aee3bc79SCunming Liang for (i = 0; i < qconf->n_rx_queue; ++i) { 876aee3bc79SCunming Liang rx_queue = &(qconf->rx_queue_list[i]); 877aee3bc79SCunming Liang port_id = rx_queue->port_id; 878aee3bc79SCunming Liang queue_id = rx_queue->queue_id; 879aee3bc79SCunming Liang 880aee3bc79SCunming Liang rte_spinlock_lock(&(locks[port_id])); 88149dcf7b9SXiao Wang if (on) 882aee3bc79SCunming Liang rte_eth_dev_rx_intr_enable(port_id, queue_id); 88349dcf7b9SXiao Wang else 88449dcf7b9SXiao Wang rte_eth_dev_rx_intr_disable(port_id, queue_id); 885aee3bc79SCunming Liang rte_spinlock_unlock(&(locks[port_id])); 886aee3bc79SCunming Liang } 887aee3bc79SCunming Liang } 888aee3bc79SCunming Liang 889aee3bc79SCunming Liang static int event_register(struct lcore_conf *qconf) 890aee3bc79SCunming Liang { 891aee3bc79SCunming Liang struct lcore_rx_queue *rx_queue; 892b23c5bd7SSivaprasad Tummala uint16_t queueid; 893f8244c63SZhiyong Yang uint16_t portid; 894aee3bc79SCunming Liang uint32_t data; 895aee3bc79SCunming Liang int ret; 896aee3bc79SCunming Liang int i; 897aee3bc79SCunming Liang 898aee3bc79SCunming Liang for (i = 0; i < qconf->n_rx_queue; ++i) { 899aee3bc79SCunming Liang rx_queue = &(qconf->rx_queue_list[i]); 900aee3bc79SCunming Liang portid = rx_queue->port_id; 901aee3bc79SCunming Liang queueid = rx_queue->queue_id; 902b23c5bd7SSivaprasad Tummala data = portid << (sizeof(uint16_t) * CHAR_BIT) | queueid; 903aee3bc79SCunming Liang 904aee3bc79SCunming Liang ret = rte_eth_dev_rx_intr_ctl_q(portid, queueid, 905aee3bc79SCunming Liang RTE_EPOLL_PER_THREAD, 906aee3bc79SCunming Liang RTE_INTR_EVENT_ADD, 907aee3bc79SCunming Liang (void *)((uintptr_t)data)); 908aee3bc79SCunming Liang if (ret) 909aee3bc79SCunming Liang return ret; 910aee3bc79SCunming Liang } 911aee3bc79SCunming Liang 912aee3bc79SCunming Liang return 0; 913aee3bc79SCunming Liang } 914e0194febSAnatoly Burakov 9159a212dc0SConor Fogarty /* Main processing loop. 8< */ 916e0194febSAnatoly Burakov static int main_intr_loop(__rte_unused void *dummy) 917e0194febSAnatoly Burakov { 918e0194febSAnatoly Burakov struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 919e0194febSAnatoly Burakov unsigned int lcore_id; 920e0194febSAnatoly Burakov uint64_t prev_tsc, diff_tsc, cur_tsc; 921e0194febSAnatoly Burakov int i, j, nb_rx; 922b23c5bd7SSivaprasad Tummala uint16_t portid, queueid; 923e0194febSAnatoly Burakov struct lcore_conf *qconf; 924e0194febSAnatoly Burakov struct lcore_rx_queue *rx_queue; 925e0194febSAnatoly Burakov uint32_t lcore_rx_idle_count = 0; 926e0194febSAnatoly Burakov uint32_t lcore_idle_hint = 0; 927e0194febSAnatoly Burakov int intr_en = 0; 928e0194febSAnatoly Burakov 929e0194febSAnatoly Burakov const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / 930e0194febSAnatoly Burakov US_PER_S * BURST_TX_DRAIN_US; 931e0194febSAnatoly Burakov 932e0194febSAnatoly Burakov prev_tsc = 0; 933e0194febSAnatoly Burakov 934e0194febSAnatoly Burakov lcore_id = rte_lcore_id(); 935e0194febSAnatoly Burakov qconf = &lcore_conf[lcore_id]; 936e0194febSAnatoly Burakov 937e0194febSAnatoly Burakov if (qconf->n_rx_queue == 0) { 938e0194febSAnatoly Burakov RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", 939e0194febSAnatoly Burakov lcore_id); 940e0194febSAnatoly Burakov return 0; 941e0194febSAnatoly Burakov } 942e0194febSAnatoly Burakov 943e0194febSAnatoly Burakov RTE_LOG(INFO, L3FWD_POWER, "entering main interrupt loop on lcore %u\n", 944e0194febSAnatoly Burakov lcore_id); 945e0194febSAnatoly Burakov 946e0194febSAnatoly Burakov for (i = 0; i < qconf->n_rx_queue; i++) { 947e0194febSAnatoly Burakov portid = qconf->rx_queue_list[i].port_id; 948e0194febSAnatoly Burakov queueid = qconf->rx_queue_list[i].queue_id; 949e0194febSAnatoly Burakov RTE_LOG(INFO, L3FWD_POWER, 950b23c5bd7SSivaprasad Tummala " -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n", 951e0194febSAnatoly Burakov lcore_id, portid, queueid); 952e0194febSAnatoly Burakov } 953e0194febSAnatoly Burakov 954e0194febSAnatoly Burakov /* add into event wait list */ 955e0194febSAnatoly Burakov if (event_register(qconf) == 0) 956e0194febSAnatoly Burakov intr_en = 1; 957e0194febSAnatoly Burakov else 958e0194febSAnatoly Burakov RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n"); 959e0194febSAnatoly Burakov 960e0194febSAnatoly Burakov while (!is_done()) { 961e0194febSAnatoly Burakov stats[lcore_id].nb_iteration_looped++; 962e0194febSAnatoly Burakov 963e0194febSAnatoly Burakov cur_tsc = rte_rdtsc(); 964e0194febSAnatoly Burakov 965e0194febSAnatoly Burakov /* 966e0194febSAnatoly Burakov * TX burst queue drain 967e0194febSAnatoly Burakov */ 968e0194febSAnatoly Burakov diff_tsc = cur_tsc - prev_tsc; 969e0194febSAnatoly Burakov if (unlikely(diff_tsc > drain_tsc)) { 970e0194febSAnatoly Burakov for (i = 0; i < qconf->n_tx_port; ++i) { 971e0194febSAnatoly Burakov portid = qconf->tx_port_id[i]; 972e0194febSAnatoly Burakov rte_eth_tx_buffer_flush(portid, 973e0194febSAnatoly Burakov qconf->tx_queue_id[portid], 974e0194febSAnatoly Burakov qconf->tx_buffer[portid]); 975e0194febSAnatoly Burakov } 976e0194febSAnatoly Burakov prev_tsc = cur_tsc; 977e0194febSAnatoly Burakov } 978e0194febSAnatoly Burakov 979e0194febSAnatoly Burakov start_rx: 980e0194febSAnatoly Burakov /* 981e0194febSAnatoly Burakov * Read packet from RX queues 982e0194febSAnatoly Burakov */ 983e0194febSAnatoly Burakov lcore_rx_idle_count = 0; 984e0194febSAnatoly Burakov for (i = 0; i < qconf->n_rx_queue; ++i) { 985e0194febSAnatoly Burakov rx_queue = &(qconf->rx_queue_list[i]); 986e0194febSAnatoly Burakov rx_queue->idle_hint = 0; 987e0194febSAnatoly Burakov portid = rx_queue->port_id; 988e0194febSAnatoly Burakov queueid = rx_queue->queue_id; 989e0194febSAnatoly Burakov 990e0194febSAnatoly Burakov nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 991e0194febSAnatoly Burakov MAX_PKT_BURST); 992e0194febSAnatoly Burakov 993e0194febSAnatoly Burakov stats[lcore_id].nb_rx_processed += nb_rx; 994e0194febSAnatoly Burakov if (unlikely(nb_rx == 0)) { 995e0194febSAnatoly Burakov /** 996e0194febSAnatoly Burakov * no packet received from rx queue, try to 997e0194febSAnatoly Burakov * sleep for a while forcing CPU enter deeper 998e0194febSAnatoly Burakov * C states. 999e0194febSAnatoly Burakov */ 1000e0194febSAnatoly Burakov rx_queue->zero_rx_packet_count++; 1001e0194febSAnatoly Burakov 1002e0194febSAnatoly Burakov if (rx_queue->zero_rx_packet_count <= 1003e0194febSAnatoly Burakov MIN_ZERO_POLL_COUNT) 1004e0194febSAnatoly Burakov continue; 1005e0194febSAnatoly Burakov 1006e0194febSAnatoly Burakov rx_queue->idle_hint = power_idle_heuristic( 1007e0194febSAnatoly Burakov rx_queue->zero_rx_packet_count); 1008e0194febSAnatoly Burakov lcore_rx_idle_count++; 1009e0194febSAnatoly Burakov } else { 1010e0194febSAnatoly Burakov rx_queue->zero_rx_packet_count = 0; 1011e0194febSAnatoly Burakov } 1012e0194febSAnatoly Burakov 1013e0194febSAnatoly Burakov /* Prefetch first packets */ 1014e0194febSAnatoly Burakov for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1015e0194febSAnatoly Burakov rte_prefetch0(rte_pktmbuf_mtod( 1016e0194febSAnatoly Burakov pkts_burst[j], void *)); 1017e0194febSAnatoly Burakov } 1018e0194febSAnatoly Burakov 1019e0194febSAnatoly Burakov /* Prefetch and forward already prefetched packets */ 1020e0194febSAnatoly Burakov for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1021e0194febSAnatoly Burakov rte_prefetch0(rte_pktmbuf_mtod( 1022e0194febSAnatoly Burakov pkts_burst[j + PREFETCH_OFFSET], 1023e0194febSAnatoly Burakov void *)); 1024e0194febSAnatoly Burakov l3fwd_simple_forward( 1025e0194febSAnatoly Burakov pkts_burst[j], portid, qconf); 1026e0194febSAnatoly Burakov } 1027e0194febSAnatoly Burakov 1028e0194febSAnatoly Burakov /* Forward remaining prefetched packets */ 1029e0194febSAnatoly Burakov for (; j < nb_rx; j++) { 1030e0194febSAnatoly Burakov l3fwd_simple_forward( 1031e0194febSAnatoly Burakov pkts_burst[j], portid, qconf); 1032e0194febSAnatoly Burakov } 1033e0194febSAnatoly Burakov } 1034e0194febSAnatoly Burakov 1035e0194febSAnatoly Burakov if (unlikely(lcore_rx_idle_count == qconf->n_rx_queue)) { 1036e0194febSAnatoly Burakov /** 1037e0194febSAnatoly Burakov * All Rx queues empty in recent consecutive polls, 1038e0194febSAnatoly Burakov * sleep in a conservative manner, meaning sleep as 1039e0194febSAnatoly Burakov * less as possible. 1040e0194febSAnatoly Burakov */ 1041e0194febSAnatoly Burakov for (i = 1, 1042e0194febSAnatoly Burakov lcore_idle_hint = qconf->rx_queue_list[0].idle_hint; 1043e0194febSAnatoly Burakov i < qconf->n_rx_queue; ++i) { 1044e0194febSAnatoly Burakov rx_queue = &(qconf->rx_queue_list[i]); 1045e0194febSAnatoly Burakov if (rx_queue->idle_hint < lcore_idle_hint) 1046e0194febSAnatoly Burakov lcore_idle_hint = rx_queue->idle_hint; 1047e0194febSAnatoly Burakov } 1048e0194febSAnatoly Burakov 1049e0194febSAnatoly Burakov if (lcore_idle_hint < SUSPEND_THRESHOLD) 1050e0194febSAnatoly Burakov /** 1051e0194febSAnatoly Burakov * execute "pause" instruction to avoid context 1052e0194febSAnatoly Burakov * switch which generally take hundred of 1053e0194febSAnatoly Burakov * microseconds for short sleep. 1054e0194febSAnatoly Burakov */ 1055e0194febSAnatoly Burakov rte_delay_us(lcore_idle_hint); 1056e0194febSAnatoly Burakov else { 1057e0194febSAnatoly Burakov /* suspend until rx interrupt triggers */ 1058e0194febSAnatoly Burakov if (intr_en) { 1059e0194febSAnatoly Burakov turn_on_off_intr(qconf, 1); 1060e0194febSAnatoly Burakov sleep_until_rx_interrupt( 1061317a1da8SAnatoly Burakov qconf->n_rx_queue, 1062317a1da8SAnatoly Burakov lcore_id); 1063e0194febSAnatoly Burakov turn_on_off_intr(qconf, 0); 1064e0194febSAnatoly Burakov /** 1065e0194febSAnatoly Burakov * start receiving packets immediately 1066e0194febSAnatoly Burakov */ 1067e0194febSAnatoly Burakov if (likely(!is_done())) 1068e0194febSAnatoly Burakov goto start_rx; 1069e0194febSAnatoly Burakov } 1070e0194febSAnatoly Burakov } 1071e0194febSAnatoly Burakov stats[lcore_id].sleep_time += lcore_idle_hint; 1072e0194febSAnatoly Burakov } 1073e0194febSAnatoly Burakov } 1074e0194febSAnatoly Burakov 1075e0194febSAnatoly Burakov return 0; 1076e0194febSAnatoly Burakov } 10779a212dc0SConor Fogarty /* >8 End of main processing loop. */ 1078e0194febSAnatoly Burakov 1079a137d012SLiang Ma /* main processing loop */ 1080a137d012SLiang Ma static int 1081f2fc83b4SThomas Monjalon main_telemetry_loop(__rte_unused void *dummy) 1082609e7984SReshma Pattan { 1083609e7984SReshma Pattan struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1084609e7984SReshma Pattan unsigned int lcore_id; 1085609e7984SReshma Pattan uint64_t prev_tsc, diff_tsc, cur_tsc, prev_tel_tsc; 1086609e7984SReshma Pattan int i, j, nb_rx; 1087b23c5bd7SSivaprasad Tummala uint16_t portid, queueid; 1088609e7984SReshma Pattan struct lcore_conf *qconf; 1089609e7984SReshma Pattan struct lcore_rx_queue *rx_queue; 1090609e7984SReshma Pattan uint64_t ep_nep[2] = {0}, fp_nfp[2] = {0}; 1091609e7984SReshma Pattan uint64_t poll_count; 1092609e7984SReshma Pattan enum busy_rate br; 1093609e7984SReshma Pattan 1094609e7984SReshma Pattan const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / 1095609e7984SReshma Pattan US_PER_S * BURST_TX_DRAIN_US; 1096609e7984SReshma Pattan 1097609e7984SReshma Pattan poll_count = 0; 1098609e7984SReshma Pattan prev_tsc = 0; 1099609e7984SReshma Pattan prev_tel_tsc = 0; 1100609e7984SReshma Pattan 1101609e7984SReshma Pattan lcore_id = rte_lcore_id(); 1102609e7984SReshma Pattan qconf = &lcore_conf[lcore_id]; 1103609e7984SReshma Pattan 1104609e7984SReshma Pattan if (qconf->n_rx_queue == 0) { 1105609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", 1106609e7984SReshma Pattan lcore_id); 1107609e7984SReshma Pattan return 0; 1108609e7984SReshma Pattan } 1109609e7984SReshma Pattan 1110609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, "entering main telemetry loop on lcore %u\n", 1111609e7984SReshma Pattan lcore_id); 1112609e7984SReshma Pattan 1113609e7984SReshma Pattan for (i = 0; i < qconf->n_rx_queue; i++) { 1114609e7984SReshma Pattan portid = qconf->rx_queue_list[i].port_id; 1115609e7984SReshma Pattan queueid = qconf->rx_queue_list[i].queue_id; 1116609e7984SReshma Pattan RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " 1117b23c5bd7SSivaprasad Tummala "rxqueueid=%" PRIu16 "\n", lcore_id, portid, queueid); 1118609e7984SReshma Pattan } 1119609e7984SReshma Pattan 1120609e7984SReshma Pattan while (!is_done()) { 1121609e7984SReshma Pattan 1122609e7984SReshma Pattan cur_tsc = rte_rdtsc(); 1123609e7984SReshma Pattan /* 1124609e7984SReshma Pattan * TX burst queue drain 1125609e7984SReshma Pattan */ 1126609e7984SReshma Pattan diff_tsc = cur_tsc - prev_tsc; 1127609e7984SReshma Pattan if (unlikely(diff_tsc > drain_tsc)) { 1128609e7984SReshma Pattan for (i = 0; i < qconf->n_tx_port; ++i) { 1129609e7984SReshma Pattan portid = qconf->tx_port_id[i]; 1130609e7984SReshma Pattan rte_eth_tx_buffer_flush(portid, 1131609e7984SReshma Pattan qconf->tx_queue_id[portid], 1132609e7984SReshma Pattan qconf->tx_buffer[portid]); 1133609e7984SReshma Pattan } 1134609e7984SReshma Pattan prev_tsc = cur_tsc; 1135609e7984SReshma Pattan } 1136609e7984SReshma Pattan 1137609e7984SReshma Pattan /* 1138609e7984SReshma Pattan * Read packet from RX queues 1139609e7984SReshma Pattan */ 1140609e7984SReshma Pattan for (i = 0; i < qconf->n_rx_queue; ++i) { 1141609e7984SReshma Pattan rx_queue = &(qconf->rx_queue_list[i]); 1142609e7984SReshma Pattan portid = rx_queue->port_id; 1143609e7984SReshma Pattan queueid = rx_queue->queue_id; 1144609e7984SReshma Pattan 1145609e7984SReshma Pattan nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 1146609e7984SReshma Pattan MAX_PKT_BURST); 1147609e7984SReshma Pattan ep_nep[nb_rx == 0]++; 1148609e7984SReshma Pattan fp_nfp[nb_rx == MAX_PKT_BURST]++; 1149609e7984SReshma Pattan poll_count++; 1150609e7984SReshma Pattan if (unlikely(nb_rx == 0)) 1151609e7984SReshma Pattan continue; 1152609e7984SReshma Pattan 1153609e7984SReshma Pattan /* Prefetch first packets */ 1154609e7984SReshma Pattan for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1155609e7984SReshma Pattan rte_prefetch0(rte_pktmbuf_mtod( 1156609e7984SReshma Pattan pkts_burst[j], void *)); 1157609e7984SReshma Pattan } 1158609e7984SReshma Pattan 1159609e7984SReshma Pattan /* Prefetch and forward already prefetched packets */ 1160609e7984SReshma Pattan for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1161609e7984SReshma Pattan rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1162609e7984SReshma Pattan j + PREFETCH_OFFSET], void *)); 1163609e7984SReshma Pattan l3fwd_simple_forward(pkts_burst[j], portid, 1164609e7984SReshma Pattan qconf); 1165609e7984SReshma Pattan } 1166609e7984SReshma Pattan 1167609e7984SReshma Pattan /* Forward remaining prefetched packets */ 1168609e7984SReshma Pattan for (; j < nb_rx; j++) { 1169609e7984SReshma Pattan l3fwd_simple_forward(pkts_burst[j], portid, 1170609e7984SReshma Pattan qconf); 1171609e7984SReshma Pattan } 1172609e7984SReshma Pattan } 1173609e7984SReshma Pattan if (unlikely(poll_count >= DEFAULT_COUNT)) { 1174609e7984SReshma Pattan diff_tsc = cur_tsc - prev_tel_tsc; 1175609e7984SReshma Pattan if (diff_tsc >= MAX_CYCLES) { 1176609e7984SReshma Pattan br = FULL; 1177609e7984SReshma Pattan } else if (diff_tsc > MIN_CYCLES && 1178609e7984SReshma Pattan diff_tsc < MAX_CYCLES) { 1179b55d8fecSDavid Hunt br = (diff_tsc * 100) / MAX_CYCLES; 1180609e7984SReshma Pattan } else { 1181609e7984SReshma Pattan br = ZERO; 1182609e7984SReshma Pattan } 1183609e7984SReshma Pattan poll_count = 0; 1184609e7984SReshma Pattan prev_tel_tsc = cur_tsc; 1185609e7984SReshma Pattan /* update stats for telemetry */ 1186609e7984SReshma Pattan rte_spinlock_lock(&stats[lcore_id].telemetry_lock); 1187609e7984SReshma Pattan stats[lcore_id].ep_nep[0] = ep_nep[0]; 1188609e7984SReshma Pattan stats[lcore_id].ep_nep[1] = ep_nep[1]; 1189609e7984SReshma Pattan stats[lcore_id].fp_nfp[0] = fp_nfp[0]; 1190609e7984SReshma Pattan stats[lcore_id].fp_nfp[1] = fp_nfp[1]; 1191609e7984SReshma Pattan stats[lcore_id].br = br; 1192609e7984SReshma Pattan rte_spinlock_unlock(&stats[lcore_id].telemetry_lock); 1193609e7984SReshma Pattan } 1194609e7984SReshma Pattan } 1195609e7984SReshma Pattan 1196609e7984SReshma Pattan return 0; 1197609e7984SReshma Pattan } 1198aee3bc79SCunming Liang 1199d7937e2eSIntel /* main processing loop */ 1200d7937e2eSIntel static int 12015b41ab35SAnatoly Burakov main_legacy_loop(__rte_unused void *dummy) 1202d7937e2eSIntel { 1203d7937e2eSIntel struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 1204d7937e2eSIntel unsigned lcore_id; 120563de7e6eSNikhil Agarwal uint64_t prev_tsc, diff_tsc, cur_tsc, tim_res_tsc, hz; 1206d7937e2eSIntel uint64_t prev_tsc_power = 0, cur_tsc_power, diff_tsc_power; 1207d7937e2eSIntel int i, j, nb_rx; 1208b23c5bd7SSivaprasad Tummala uint16_t portid, queueid; 1209d7937e2eSIntel struct lcore_conf *qconf; 1210d7937e2eSIntel struct lcore_rx_queue *rx_queue; 1211d7937e2eSIntel enum freq_scale_hint_t lcore_scaleup_hint; 1212d7937e2eSIntel uint32_t lcore_rx_idle_count = 0; 1213d7937e2eSIntel uint32_t lcore_idle_hint = 0; 1214aee3bc79SCunming Liang int intr_en = 0; 1215d7937e2eSIntel 1216d7937e2eSIntel const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; 1217d7937e2eSIntel 1218d7937e2eSIntel prev_tsc = 0; 121963de7e6eSNikhil Agarwal hz = rte_get_timer_hz(); 122063de7e6eSNikhil Agarwal tim_res_tsc = hz/TIMER_NUMBER_PER_SECOND; 1221d7937e2eSIntel 1222d7937e2eSIntel lcore_id = rte_lcore_id(); 1223d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 1224d7937e2eSIntel 1225d7937e2eSIntel if (qconf->n_rx_queue == 0) { 1226d7937e2eSIntel RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", lcore_id); 1227d7937e2eSIntel return 0; 1228d7937e2eSIntel } 1229d7937e2eSIntel 1230d7937e2eSIntel RTE_LOG(INFO, L3FWD_POWER, "entering main loop on lcore %u\n", lcore_id); 1231d7937e2eSIntel 1232d7937e2eSIntel for (i = 0; i < qconf->n_rx_queue; i++) { 1233d7937e2eSIntel portid = qconf->rx_queue_list[i].port_id; 1234d7937e2eSIntel queueid = qconf->rx_queue_list[i].queue_id; 1235f8244c63SZhiyong Yang RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " 1236b23c5bd7SSivaprasad Tummala "rxqueueid=%" PRIu16 "\n", lcore_id, portid, queueid); 1237d7937e2eSIntel } 1238d7937e2eSIntel 1239aee3bc79SCunming Liang /* add into event wait list */ 1240aee3bc79SCunming Liang if (event_register(qconf) == 0) 1241aee3bc79SCunming Liang intr_en = 1; 1242aee3bc79SCunming Liang else 1243aee3bc79SCunming Liang RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n"); 1244aee3bc79SCunming Liang 1245613ce669SAnatoly Burakov while (!is_done()) { 1246d7937e2eSIntel stats[lcore_id].nb_iteration_looped++; 1247d7937e2eSIntel 1248d7937e2eSIntel cur_tsc = rte_rdtsc(); 1249d7937e2eSIntel cur_tsc_power = cur_tsc; 1250d7937e2eSIntel 1251d7937e2eSIntel /* 1252d7937e2eSIntel * TX burst queue drain 1253d7937e2eSIntel */ 1254d7937e2eSIntel diff_tsc = cur_tsc - prev_tsc; 1255d7937e2eSIntel if (unlikely(diff_tsc > drain_tsc)) { 1256e2366e74STomasz Kulasek for (i = 0; i < qconf->n_tx_port; ++i) { 1257e2366e74STomasz Kulasek portid = qconf->tx_port_id[i]; 1258e2366e74STomasz Kulasek rte_eth_tx_buffer_flush(portid, 1259e2366e74STomasz Kulasek qconf->tx_queue_id[portid], 1260e2366e74STomasz Kulasek qconf->tx_buffer[portid]); 1261d7937e2eSIntel } 1262d7937e2eSIntel prev_tsc = cur_tsc; 1263d7937e2eSIntel } 1264d7937e2eSIntel 1265d7937e2eSIntel diff_tsc_power = cur_tsc_power - prev_tsc_power; 126663de7e6eSNikhil Agarwal if (diff_tsc_power > tim_res_tsc) { 1267d7937e2eSIntel rte_timer_manage(); 1268d7937e2eSIntel prev_tsc_power = cur_tsc_power; 1269d7937e2eSIntel } 1270d7937e2eSIntel 1271aee3bc79SCunming Liang start_rx: 1272d7937e2eSIntel /* 1273d7937e2eSIntel * Read packet from RX queues 1274d7937e2eSIntel */ 1275d7937e2eSIntel lcore_scaleup_hint = FREQ_CURRENT; 1276d7937e2eSIntel lcore_rx_idle_count = 0; 1277d7937e2eSIntel for (i = 0; i < qconf->n_rx_queue; ++i) { 1278d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1279d7937e2eSIntel rx_queue->idle_hint = 0; 1280d7937e2eSIntel portid = rx_queue->port_id; 1281d7937e2eSIntel queueid = rx_queue->queue_id; 1282d7937e2eSIntel 1283d7937e2eSIntel nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, 1284d7937e2eSIntel MAX_PKT_BURST); 1285aee3bc79SCunming Liang 1286d7937e2eSIntel stats[lcore_id].nb_rx_processed += nb_rx; 1287d7937e2eSIntel if (unlikely(nb_rx == 0)) { 1288d7937e2eSIntel /** 1289d7937e2eSIntel * no packet received from rx queue, try to 1290d7937e2eSIntel * sleep for a while forcing CPU enter deeper 1291d7937e2eSIntel * C states. 1292d7937e2eSIntel */ 1293d7937e2eSIntel rx_queue->zero_rx_packet_count++; 1294d7937e2eSIntel 1295d7937e2eSIntel if (rx_queue->zero_rx_packet_count <= 1296d7937e2eSIntel MIN_ZERO_POLL_COUNT) 1297d7937e2eSIntel continue; 1298d7937e2eSIntel 1299d7937e2eSIntel rx_queue->idle_hint = power_idle_heuristic(\ 1300d7937e2eSIntel rx_queue->zero_rx_packet_count); 1301d7937e2eSIntel lcore_rx_idle_count++; 1302d7937e2eSIntel } else { 1303d7937e2eSIntel rx_queue->zero_rx_packet_count = 0; 1304d7937e2eSIntel 1305d7937e2eSIntel /** 1306d7937e2eSIntel * do not scale up frequency immediately as 1307d7937e2eSIntel * user to kernel space communication is costly 1308d7937e2eSIntel * which might impact packet I/O for received 1309d7937e2eSIntel * packets. 1310d7937e2eSIntel */ 1311d7937e2eSIntel rx_queue->freq_up_hint = 1312d7937e2eSIntel power_freq_scaleup_heuristic(lcore_id, 1313b451aa39SIntel portid, queueid); 1314d7937e2eSIntel } 1315d7937e2eSIntel 1316d7937e2eSIntel /* Prefetch first packets */ 1317d7937e2eSIntel for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { 1318d7937e2eSIntel rte_prefetch0(rte_pktmbuf_mtod( 1319d7937e2eSIntel pkts_burst[j], void *)); 1320d7937e2eSIntel } 1321d7937e2eSIntel 1322d7937e2eSIntel /* Prefetch and forward already prefetched packets */ 1323d7937e2eSIntel for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { 1324d7937e2eSIntel rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ 1325d7937e2eSIntel j + PREFETCH_OFFSET], void *)); 1326d7937e2eSIntel l3fwd_simple_forward(pkts_burst[j], portid, 1327d7937e2eSIntel qconf); 1328d7937e2eSIntel } 1329d7937e2eSIntel 1330d7937e2eSIntel /* Forward remaining prefetched packets */ 1331d7937e2eSIntel for (; j < nb_rx; j++) { 1332d7937e2eSIntel l3fwd_simple_forward(pkts_burst[j], portid, 1333d7937e2eSIntel qconf); 1334d7937e2eSIntel } 1335d7937e2eSIntel } 1336d7937e2eSIntel 1337d7937e2eSIntel if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) { 1338d7937e2eSIntel for (i = 1, lcore_scaleup_hint = 1339d7937e2eSIntel qconf->rx_queue_list[0].freq_up_hint; 1340d7937e2eSIntel i < qconf->n_rx_queue; ++i) { 1341d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1342d7937e2eSIntel if (rx_queue->freq_up_hint > 1343d7937e2eSIntel lcore_scaleup_hint) 1344d7937e2eSIntel lcore_scaleup_hint = 1345d7937e2eSIntel rx_queue->freq_up_hint; 1346d7937e2eSIntel } 1347d7937e2eSIntel 1348aee3bc79SCunming Liang if (lcore_scaleup_hint == FREQ_HIGHEST) { 1349d7937e2eSIntel rte_power_freq_max(lcore_id); 1350aee3bc79SCunming Liang } else if (lcore_scaleup_hint == FREQ_HIGHER) { 1351d7937e2eSIntel rte_power_freq_up(lcore_id); 1352aee3bc79SCunming Liang } 1353d7937e2eSIntel } else { 1354d7937e2eSIntel /** 1355d7937e2eSIntel * All Rx queues empty in recent consecutive polls, 1356d7937e2eSIntel * sleep in a conservative manner, meaning sleep as 1357d7937e2eSIntel * less as possible. 1358d7937e2eSIntel */ 1359d7937e2eSIntel for (i = 1, lcore_idle_hint = 1360d7937e2eSIntel qconf->rx_queue_list[0].idle_hint; 1361d7937e2eSIntel i < qconf->n_rx_queue; ++i) { 1362d7937e2eSIntel rx_queue = &(qconf->rx_queue_list[i]); 1363d7937e2eSIntel if (rx_queue->idle_hint < lcore_idle_hint) 1364d7937e2eSIntel lcore_idle_hint = rx_queue->idle_hint; 1365d7937e2eSIntel } 1366d7937e2eSIntel 1367aee3bc79SCunming Liang if (lcore_idle_hint < SUSPEND_THRESHOLD) 1368d7937e2eSIntel /** 1369d7937e2eSIntel * execute "pause" instruction to avoid context 1370aee3bc79SCunming Liang * switch which generally take hundred of 1371aee3bc79SCunming Liang * microseconds for short sleep. 1372d7937e2eSIntel */ 1373d7937e2eSIntel rte_delay_us(lcore_idle_hint); 1374aee3bc79SCunming Liang else { 1375dd22d317SXiao Wang /* suspend until rx interrupt triggers */ 1376aee3bc79SCunming Liang if (intr_en) { 137749dcf7b9SXiao Wang turn_on_off_intr(qconf, 1); 1378aee3bc79SCunming Liang sleep_until_rx_interrupt( 1379317a1da8SAnatoly Burakov qconf->n_rx_queue, 1380317a1da8SAnatoly Burakov lcore_id); 138149dcf7b9SXiao Wang turn_on_off_intr(qconf, 0); 13824ffc0a88SNikhil Agarwal /** 13834ffc0a88SNikhil Agarwal * start receiving packets immediately 13844ffc0a88SNikhil Agarwal */ 1385f4d1e19cSAnatoly Burakov if (likely(!is_done())) 1386aee3bc79SCunming Liang goto start_rx; 1387aee3bc79SCunming Liang } 13884ffc0a88SNikhil Agarwal } 1389d7937e2eSIntel stats[lcore_id].sleep_time += lcore_idle_hint; 1390d7937e2eSIntel } 1391d7937e2eSIntel } 1392613ce669SAnatoly Burakov 1393613ce669SAnatoly Burakov return 0; 1394d7937e2eSIntel } 1395d7937e2eSIntel 1396d7937e2eSIntel static int 1397d7937e2eSIntel check_lcore_params(void) 1398d7937e2eSIntel { 1399b23c5bd7SSivaprasad Tummala uint16_t queue, i; 14004b978938SSivaprasad Tummala uint32_t lcore; 1401d7937e2eSIntel int socketid; 1402d7937e2eSIntel 1403d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1404d7937e2eSIntel queue = lcore_params[i].queue_id; 1405d7937e2eSIntel if (queue >= MAX_RX_QUEUE_PER_PORT) { 1406b23c5bd7SSivaprasad Tummala printf("invalid queue number: %" PRIu16 "\n", queue); 1407d7937e2eSIntel return -1; 1408d7937e2eSIntel } 1409d7937e2eSIntel lcore = lcore_params[i].lcore_id; 1410d7937e2eSIntel if (!rte_lcore_is_enabled(lcore)) { 14114b978938SSivaprasad Tummala printf("error: lcore %u is not enabled in lcore " 1412d7937e2eSIntel "mask\n", lcore); 1413d7937e2eSIntel return -1; 1414d7937e2eSIntel } 1415d7937e2eSIntel if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && 1416d7937e2eSIntel (numa_on == 0)) { 14174b978938SSivaprasad Tummala printf("warning: lcore %u is on socket %d with numa " 1418d7937e2eSIntel "off\n", lcore, socketid); 1419d7937e2eSIntel } 1420609e7984SReshma Pattan if (app_mode == APP_MODE_TELEMETRY && lcore == rte_lcore_id()) { 1421cb056611SStephen Hemminger printf("cannot enable main core %d in config for telemetry mode\n", 1422609e7984SReshma Pattan rte_lcore_id()); 1423609e7984SReshma Pattan return -1; 1424609e7984SReshma Pattan } 1425d7937e2eSIntel } 1426d7937e2eSIntel return 0; 1427d7937e2eSIntel } 1428d7937e2eSIntel 1429d7937e2eSIntel static int 1430a9dbe180SThomas Monjalon check_port_config(void) 1431d7937e2eSIntel { 1432d7937e2eSIntel unsigned portid; 1433d7937e2eSIntel uint16_t i; 1434d7937e2eSIntel 1435d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1436d7937e2eSIntel portid = lcore_params[i].port_id; 1437d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 1438d7937e2eSIntel printf("port %u is not enabled in port mask\n", 1439d7937e2eSIntel portid); 1440d7937e2eSIntel return -1; 1441d7937e2eSIntel } 1442a9dbe180SThomas Monjalon if (!rte_eth_dev_is_valid_port(portid)) { 1443d7937e2eSIntel printf("port %u is not present on the board\n", 1444d7937e2eSIntel portid); 1445d7937e2eSIntel return -1; 1446d7937e2eSIntel } 1447d7937e2eSIntel } 1448d7937e2eSIntel return 0; 1449d7937e2eSIntel } 1450d7937e2eSIntel 1451b23c5bd7SSivaprasad Tummala static uint16_t 145247523597SZhiyong Yang get_port_n_rx_queues(const uint16_t port) 1453d7937e2eSIntel { 1454d7937e2eSIntel int queue = -1; 1455d7937e2eSIntel uint16_t i; 1456d7937e2eSIntel 1457d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1458d7937e2eSIntel if (lcore_params[i].port_id == port && 1459d7937e2eSIntel lcore_params[i].queue_id > queue) 1460d7937e2eSIntel queue = lcore_params[i].queue_id; 1461d7937e2eSIntel } 1462b23c5bd7SSivaprasad Tummala return (uint16_t)(++queue); 1463d7937e2eSIntel } 1464d7937e2eSIntel 1465d7937e2eSIntel static int 1466d7937e2eSIntel init_lcore_rx_queues(void) 1467d7937e2eSIntel { 1468d7937e2eSIntel uint16_t i, nb_rx_queue; 14694b978938SSivaprasad Tummala uint32_t lcore; 1470d7937e2eSIntel 1471d7937e2eSIntel for (i = 0; i < nb_lcore_params; ++i) { 1472d7937e2eSIntel lcore = lcore_params[i].lcore_id; 1473d7937e2eSIntel nb_rx_queue = lcore_conf[lcore].n_rx_queue; 1474d7937e2eSIntel if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 1475d7937e2eSIntel printf("error: too many queues (%u) for lcore: %u\n", 14764b978938SSivaprasad Tummala (unsigned int)nb_rx_queue + 1, lcore); 1477d7937e2eSIntel return -1; 1478d7937e2eSIntel } else { 1479d7937e2eSIntel lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 1480d7937e2eSIntel lcore_params[i].port_id; 1481d7937e2eSIntel lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 1482d7937e2eSIntel lcore_params[i].queue_id; 1483d7937e2eSIntel lcore_conf[lcore].n_rx_queue++; 1484d7937e2eSIntel } 1485d7937e2eSIntel } 1486d7937e2eSIntel return 0; 1487d7937e2eSIntel } 1488d7937e2eSIntel 1489d7937e2eSIntel /* display usage */ 1490d7937e2eSIntel static void 1491d7937e2eSIntel print_usage(const char *prgname) 1492d7937e2eSIntel { 1493d7937e2eSIntel printf ("%s [EAL options] -- -p PORTMASK -P" 1494d7937e2eSIntel " [--config (port,queue,lcore)[,(port,queue,lcore]]" 1495f88e7c17SRadu Nicolau " [--high-perf-cores CORELIST" 1496f88e7c17SRadu Nicolau " [--perf-config (port,queue,hi_perf,lcore_index)[,(port,queue,hi_perf,lcore_index]]" 14971bb4a528SFerruh Yigit " [--max-pkt-len PKTLEN]\n" 1498d7937e2eSIntel " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 1499d7937e2eSIntel " -P: enable promiscuous mode\n" 150010db2a5bSTadhg Kearney " -u: set min/max frequency for uncore to minimum value\n" 150110db2a5bSTadhg Kearney " -U: set min/max frequency for uncore to maximum value\n" 150210db2a5bSTadhg Kearney " -i (frequency index): set min/max frequency for uncore to specified frequency index\n" 1503d7937e2eSIntel " --config (port,queue,lcore): rx queues configuration\n" 15044d23d39fSHuisong Li " --cpu-resume-latency LATENCY: set CPU resume latency to control C-state selection," 15054d23d39fSHuisong Li " 0 : just allow to enter C0-state\n" 1506f88e7c17SRadu Nicolau " --high-perf-cores CORELIST: list of high performance cores\n" 1507f88e7c17SRadu Nicolau " --perf-config: similar as config, cores specified as indices" 1508f88e7c17SRadu Nicolau " for bins containing high or regular performance cores\n" 1509d7937e2eSIntel " --no-numa: optional, disable numa awareness\n" 15101bb4a528SFerruh Yigit " --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n" 1511a137d012SLiang Ma " --parse-ptype: parse packet type by software\n" 15122a0e2e2dSAnatoly Burakov " --legacy: use legacy interrupt-based scaling\n" 1513609e7984SReshma Pattan " --telemetry: enable telemetry mode, to update" 1514e0194febSAnatoly Burakov " empty polls, full polls, and core busyness to telemetry\n" 151526fe454eSLiang Ma " --interrupt-only: enable interrupt-only mode\n" 151626fe454eSLiang Ma " --pmd-mgmt MODE: enable PMD power management mode. " 151759f2853cSKevin Laatz "Currently supported modes: baseline, monitor, pause, scale\n" 151859f2853cSKevin Laatz " --max-empty-polls MAX_EMPTY_POLLS: number of empty polls to" 151959f2853cSKevin Laatz " wait before entering sleep state\n" 152059f2853cSKevin Laatz " --pause-duration DURATION: set the duration, in microseconds," 152159f2853cSKevin Laatz " of the pause callback\n" 152259f2853cSKevin Laatz " --scale-freq-min FREQ_MIN: set minimum frequency for scaling mode for" 152359f2853cSKevin Laatz " all application lcores (FREQ_MIN must be in kHz, in increments of 100MHz)\n" 152459f2853cSKevin Laatz " --scale-freq-max FREQ_MAX: set maximum frequency for scaling mode for" 152559f2853cSKevin Laatz " all application lcores (FREQ_MAX must be in kHz, in increments of 100MHz)\n", 1526d7937e2eSIntel prgname); 1527d7937e2eSIntel } 1528d7937e2eSIntel 15290bc4795dSHuisong Li /* 15300bc4795dSHuisong Li * Caller must give the right upper limit so as to ensure receiver variable 15310bc4795dSHuisong Li * doesn't overflow. 15320bc4795dSHuisong Li */ 153359f2853cSKevin Laatz static int 15340bc4795dSHuisong Li parse_uint(const char *opt, uint32_t max, uint32_t *res) 153559f2853cSKevin Laatz { 153659f2853cSKevin Laatz char *end = NULL; 153759f2853cSKevin Laatz unsigned long val; 153859f2853cSKevin Laatz 153959f2853cSKevin Laatz /* parse integer string */ 154059f2853cSKevin Laatz val = strtoul(opt, &end, 10); 154159f2853cSKevin Laatz if ((opt[0] == '\0') || (end == NULL) || (*end != '\0')) 154259f2853cSKevin Laatz return -1; 154359f2853cSKevin Laatz 15440bc4795dSHuisong Li if (val > max) { 15450bc4795dSHuisong Li RTE_LOG(ERR, L3FWD_POWER, "%s parameter shouldn't exceed %u.\n", 15460bc4795dSHuisong Li opt, max); 15470bc4795dSHuisong Li return -1; 154859f2853cSKevin Laatz } 154959f2853cSKevin Laatz 15500bc4795dSHuisong Li *res = val; 1551d7937e2eSIntel 15520bc4795dSHuisong Li return 0; 1553d7937e2eSIntel } 1554d7937e2eSIntel 1555d7937e2eSIntel static int 155610db2a5bSTadhg Kearney parse_uncore_options(enum uncore_choice choice, const char *argument) 155710db2a5bSTadhg Kearney { 155810db2a5bSTadhg Kearney unsigned int die, pkg, max_pkg, max_die; 155910db2a5bSTadhg Kearney int ret = 0; 15603b3af56dSSivaprasad Tummala ret = rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_AUTO_DETECT); 15613b3af56dSSivaprasad Tummala if (ret < 0) { 15623b3af56dSSivaprasad Tummala RTE_LOG(INFO, L3FWD_POWER, "Failed to set uncore env\n"); 15633b3af56dSSivaprasad Tummala return ret; 15643b3af56dSSivaprasad Tummala } 15653b3af56dSSivaprasad Tummala 156610db2a5bSTadhg Kearney max_pkg = rte_power_uncore_get_num_pkgs(); 156710db2a5bSTadhg Kearney if (max_pkg == 0) 156810db2a5bSTadhg Kearney return -1; 156910db2a5bSTadhg Kearney 157010db2a5bSTadhg Kearney for (pkg = 0; pkg < max_pkg; pkg++) { 157110db2a5bSTadhg Kearney max_die = rte_power_uncore_get_num_dies(pkg); 157210db2a5bSTadhg Kearney if (max_die == 0) 157310db2a5bSTadhg Kearney return -1; 157410db2a5bSTadhg Kearney for (die = 0; die < max_die; die++) { 157510db2a5bSTadhg Kearney ret = rte_power_uncore_init(pkg, die); 157610db2a5bSTadhg Kearney if (ret == -1) { 157710db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, "Unable to initialize uncore for pkg %02u die %02u\n" 157810db2a5bSTadhg Kearney , pkg, die); 157910db2a5bSTadhg Kearney return ret; 158010db2a5bSTadhg Kearney } 158110db2a5bSTadhg Kearney if (choice == UNCORE_MIN) { 158210db2a5bSTadhg Kearney ret = rte_power_uncore_freq_min(pkg, die); 158310db2a5bSTadhg Kearney if (ret == -1) { 158410db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, 158510db2a5bSTadhg Kearney "Unable to set the uncore min/max to minimum uncore frequency value for pkg %02u die %02u\n" 158610db2a5bSTadhg Kearney , pkg, die); 158710db2a5bSTadhg Kearney return ret; 158810db2a5bSTadhg Kearney } 158910db2a5bSTadhg Kearney } else if (choice == UNCORE_MAX) { 159010db2a5bSTadhg Kearney ret = rte_power_uncore_freq_max(pkg, die); 159110db2a5bSTadhg Kearney if (ret == -1) { 159210db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, 159310db2a5bSTadhg Kearney "Unable to set uncore min/max to maximum uncore frequency value for pkg %02u die %02u\n" 159410db2a5bSTadhg Kearney , pkg, die); 159510db2a5bSTadhg Kearney return ret; 159610db2a5bSTadhg Kearney } 159710db2a5bSTadhg Kearney } else if (choice == UNCORE_IDX) { 159810db2a5bSTadhg Kearney char *ptr = NULL; 159910db2a5bSTadhg Kearney int frequency_index = strtol(argument, &ptr, 10); 160010db2a5bSTadhg Kearney if (argument == ptr) { 160110db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, "Index given is not a valid number."); 160210db2a5bSTadhg Kearney return -1; 160310db2a5bSTadhg Kearney } 160410db2a5bSTadhg Kearney int freq_array_len = rte_power_uncore_get_num_freqs(pkg, die); 160510db2a5bSTadhg Kearney if (frequency_index > freq_array_len - 1) { 160610db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, 160710db2a5bSTadhg Kearney "Frequency index given out of range, please choose a value from 0 to %d.\n", 160810db2a5bSTadhg Kearney freq_array_len); 160910db2a5bSTadhg Kearney return -1; 161010db2a5bSTadhg Kearney } 161110db2a5bSTadhg Kearney ret = rte_power_set_uncore_freq(pkg, die, frequency_index); 161210db2a5bSTadhg Kearney if (ret == -1) { 161310db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, 161410db2a5bSTadhg Kearney "Unable to set min/max uncore index value for pkg %02u die %02u\n", 161510db2a5bSTadhg Kearney pkg, die); 161610db2a5bSTadhg Kearney return ret; 161710db2a5bSTadhg Kearney } 161810db2a5bSTadhg Kearney } else { 161910db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, "Uncore choice provided invalid\n"); 162010db2a5bSTadhg Kearney return -1; 162110db2a5bSTadhg Kearney } 162210db2a5bSTadhg Kearney } 162310db2a5bSTadhg Kearney } 162410db2a5bSTadhg Kearney 162510db2a5bSTadhg Kearney RTE_LOG(INFO, L3FWD_POWER, "Successfully set max/min/index uncore frequency.\n"); 162610db2a5bSTadhg Kearney return ret; 162710db2a5bSTadhg Kearney } 162810db2a5bSTadhg Kearney 162910db2a5bSTadhg Kearney static int 1630d7937e2eSIntel parse_portmask(const char *portmask) 1631d7937e2eSIntel { 1632d7937e2eSIntel char *end = NULL; 1633d7937e2eSIntel unsigned long pm; 1634d7937e2eSIntel 1635d7937e2eSIntel /* parse hexadecimal string */ 1636d7937e2eSIntel pm = strtoul(portmask, &end, 16); 1637d7937e2eSIntel if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 1638ce6b8c31SSarosh Arif return 0; 1639d7937e2eSIntel 1640d7937e2eSIntel return pm; 1641d7937e2eSIntel } 1642d7937e2eSIntel 1643d7937e2eSIntel static int 1644d7937e2eSIntel parse_config(const char *q_arg) 1645d7937e2eSIntel { 1646d7937e2eSIntel char s[256]; 1647d7937e2eSIntel const char *p, *p0 = q_arg; 1648d7937e2eSIntel char *end; 1649d7937e2eSIntel enum fieldnames { 1650d7937e2eSIntel FLD_PORT = 0, 1651d7937e2eSIntel FLD_QUEUE, 1652d7937e2eSIntel FLD_LCORE, 1653d7937e2eSIntel _NUM_FLD 1654d7937e2eSIntel }; 1655d7937e2eSIntel unsigned long int_fld[_NUM_FLD]; 1656d7937e2eSIntel char *str_fld[_NUM_FLD]; 1657d7937e2eSIntel int i; 1658d7937e2eSIntel unsigned size; 16594b978938SSivaprasad Tummala unsigned int max_fld[_NUM_FLD] = { 1660548de909SSivaprasad Tummala RTE_MAX_ETHPORTS, 16614b978938SSivaprasad Tummala RTE_MAX_QUEUES_PER_PORT, 16624b978938SSivaprasad Tummala RTE_MAX_LCORE 16634b978938SSivaprasad Tummala }; 1664d7937e2eSIntel 1665d7937e2eSIntel nb_lcore_params = 0; 1666d7937e2eSIntel 1667d7937e2eSIntel while ((p = strchr(p0,'(')) != NULL) { 1668d7937e2eSIntel ++p; 1669d7937e2eSIntel if((p0 = strchr(p,')')) == NULL) 1670d7937e2eSIntel return -1; 1671d7937e2eSIntel 1672d7937e2eSIntel size = p0 - p; 1673d7937e2eSIntel if(size >= sizeof(s)) 1674d7937e2eSIntel return -1; 1675d7937e2eSIntel 16766f41fe75SStephen Hemminger snprintf(s, sizeof(s), "%.*s", size, p); 1677d7937e2eSIntel if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 1678d7937e2eSIntel _NUM_FLD) 1679d7937e2eSIntel return -1; 1680d7937e2eSIntel for (i = 0; i < _NUM_FLD; i++){ 1681d7937e2eSIntel errno = 0; 1682d7937e2eSIntel int_fld[i] = strtoul(str_fld[i], &end, 0); 1683b23c5bd7SSivaprasad Tummala if (errno != 0 || end == str_fld[i] || int_fld[i] > max_fld[i]) 1684d7937e2eSIntel return -1; 1685d7937e2eSIntel } 1686d7937e2eSIntel if (nb_lcore_params >= MAX_LCORE_PARAMS) { 1687d7937e2eSIntel printf("exceeded max number of lcore params: %hu\n", 1688d7937e2eSIntel nb_lcore_params); 1689d7937e2eSIntel return -1; 1690d7937e2eSIntel } 1691d7937e2eSIntel lcore_params_array[nb_lcore_params].port_id = 1692548de909SSivaprasad Tummala (uint16_t)int_fld[FLD_PORT]; 1693d7937e2eSIntel lcore_params_array[nb_lcore_params].queue_id = 1694b23c5bd7SSivaprasad Tummala (uint16_t)int_fld[FLD_QUEUE]; 1695d7937e2eSIntel lcore_params_array[nb_lcore_params].lcore_id = 16964b978938SSivaprasad Tummala (uint32_t)int_fld[FLD_LCORE]; 1697d7937e2eSIntel ++nb_lcore_params; 1698d7937e2eSIntel } 1699d7937e2eSIntel lcore_params = lcore_params_array; 1700d7937e2eSIntel 1701d7937e2eSIntel return 0; 1702d7937e2eSIntel } 170326fe454eSLiang Ma 170426fe454eSLiang Ma static int 170526fe454eSLiang Ma parse_pmd_mgmt_config(const char *name) 170626fe454eSLiang Ma { 170726fe454eSLiang Ma #define PMD_MGMT_MONITOR "monitor" 170826fe454eSLiang Ma #define PMD_MGMT_PAUSE "pause" 170926fe454eSLiang Ma #define PMD_MGMT_SCALE "scale" 1710a9ea6070SDavid Hunt #define PMD_MGMT_BASELINE "baseline" 171126fe454eSLiang Ma 171226fe454eSLiang Ma if (strncmp(PMD_MGMT_MONITOR, name, sizeof(PMD_MGMT_MONITOR)) == 0) { 171326fe454eSLiang Ma pmgmt_type = RTE_POWER_MGMT_TYPE_MONITOR; 171426fe454eSLiang Ma return 0; 171526fe454eSLiang Ma } 171626fe454eSLiang Ma 171726fe454eSLiang Ma if (strncmp(PMD_MGMT_PAUSE, name, sizeof(PMD_MGMT_PAUSE)) == 0) { 171826fe454eSLiang Ma pmgmt_type = RTE_POWER_MGMT_TYPE_PAUSE; 171926fe454eSLiang Ma return 0; 172026fe454eSLiang Ma } 172126fe454eSLiang Ma 172226fe454eSLiang Ma if (strncmp(PMD_MGMT_SCALE, name, sizeof(PMD_MGMT_SCALE)) == 0) { 172326fe454eSLiang Ma pmgmt_type = RTE_POWER_MGMT_TYPE_SCALE; 172426fe454eSLiang Ma return 0; 172526fe454eSLiang Ma } 1726a9ea6070SDavid Hunt if (strncmp(PMD_MGMT_BASELINE, name, sizeof(PMD_MGMT_BASELINE)) == 0) { 1727a9ea6070SDavid Hunt baseline_enabled = true; 1728a9ea6070SDavid Hunt return 0; 1729a9ea6070SDavid Hunt } 173026fe454eSLiang Ma /* unknown PMD power management mode */ 173126fe454eSLiang Ma return -1; 173226fe454eSLiang Ma } 173326fe454eSLiang Ma 173482bea466SJianfeng Tan #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype" 17352a0e2e2dSAnatoly Burakov #define CMD_LINE_OPT_LEGACY "legacy" 1736e0194febSAnatoly Burakov #define CMD_LINE_OPT_INTERRUPT_ONLY "interrupt-only" 1737609e7984SReshma Pattan #define CMD_LINE_OPT_TELEMETRY "telemetry" 173826fe454eSLiang Ma #define CMD_LINE_OPT_PMD_MGMT "pmd-mgmt" 17391bb4a528SFerruh Yigit #define CMD_LINE_OPT_MAX_PKT_LEN "max-pkt-len" 174059f2853cSKevin Laatz #define CMD_LINE_OPT_MAX_EMPTY_POLLS "max-empty-polls" 174159f2853cSKevin Laatz #define CMD_LINE_OPT_PAUSE_DURATION "pause-duration" 174259f2853cSKevin Laatz #define CMD_LINE_OPT_SCALE_FREQ_MIN "scale-freq-min" 174359f2853cSKevin Laatz #define CMD_LINE_OPT_SCALE_FREQ_MAX "scale-freq-max" 17444d23d39fSHuisong Li #define CMD_LINE_OPT_CPU_RESUME_LATENCY "cpu-resume-latency" 174582bea466SJianfeng Tan 1746d7937e2eSIntel /* Parse the argument given in the command line of the application */ 1747d7937e2eSIntel static int 1748d7937e2eSIntel parse_args(int argc, char **argv) 1749d7937e2eSIntel { 1750d7937e2eSIntel int opt, ret; 1751d7937e2eSIntel char **argvopt; 1752d7937e2eSIntel int option_index; 1753d7937e2eSIntel char *prgname = argv[0]; 1754d7937e2eSIntel static struct option lgopts[] = { 1755d7937e2eSIntel {"config", 1, 0, 0}, 1756f88e7c17SRadu Nicolau {"perf-config", 1, 0, 0}, 1757f88e7c17SRadu Nicolau {"high-perf-cores", 1, 0, 0}, 1758d7937e2eSIntel {"no-numa", 0, 0, 0}, 17594d23d39fSHuisong Li {CMD_LINE_OPT_CPU_RESUME_LATENCY, 1, 0, 0}, 17601bb4a528SFerruh Yigit {CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, 0}, 176182bea466SJianfeng Tan {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, 17622a0e2e2dSAnatoly Burakov {CMD_LINE_OPT_LEGACY, 0, 0, 0}, 1763609e7984SReshma Pattan {CMD_LINE_OPT_TELEMETRY, 0, 0, 0}, 1764e0194febSAnatoly Burakov {CMD_LINE_OPT_INTERRUPT_ONLY, 0, 0, 0}, 176526fe454eSLiang Ma {CMD_LINE_OPT_PMD_MGMT, 1, 0, 0}, 176659f2853cSKevin Laatz {CMD_LINE_OPT_MAX_EMPTY_POLLS, 1, 0, 0}, 176759f2853cSKevin Laatz {CMD_LINE_OPT_PAUSE_DURATION, 1, 0, 0}, 176859f2853cSKevin Laatz {CMD_LINE_OPT_SCALE_FREQ_MIN, 1, 0, 0}, 176959f2853cSKevin Laatz {CMD_LINE_OPT_SCALE_FREQ_MAX, 1, 0, 0}, 1770d7937e2eSIntel {NULL, 0, 0, 0} 1771d7937e2eSIntel }; 1772d7937e2eSIntel 1773d7937e2eSIntel argvopt = argv; 1774d7937e2eSIntel 17759c75ff42SDavid Hunt while ((opt = getopt_long(argc, argvopt, "p:PuUi:", 1776d7937e2eSIntel lgopts, &option_index)) != EOF) { 1777d7937e2eSIntel 1778d7937e2eSIntel switch (opt) { 1779d7937e2eSIntel /* portmask */ 1780d7937e2eSIntel case 'p': 1781d7937e2eSIntel enabled_port_mask = parse_portmask(optarg); 1782d7937e2eSIntel if (enabled_port_mask == 0) { 1783d7937e2eSIntel printf("invalid portmask\n"); 1784d7937e2eSIntel print_usage(prgname); 1785d7937e2eSIntel return -1; 1786d7937e2eSIntel } 1787d7937e2eSIntel break; 1788d7937e2eSIntel case 'P': 1789d7937e2eSIntel printf("Promiscuous mode selected\n"); 1790d7937e2eSIntel promiscuous_on = 1; 1791d7937e2eSIntel break; 179210db2a5bSTadhg Kearney case 'u': 179310db2a5bSTadhg Kearney enabled_uncore = parse_uncore_options(UNCORE_MIN, NULL); 179410db2a5bSTadhg Kearney if (enabled_uncore < 0) { 179510db2a5bSTadhg Kearney print_usage(prgname); 179610db2a5bSTadhg Kearney return -1; 179710db2a5bSTadhg Kearney } 179810db2a5bSTadhg Kearney break; 179910db2a5bSTadhg Kearney case 'U': 180010db2a5bSTadhg Kearney enabled_uncore = parse_uncore_options(UNCORE_MAX, NULL); 180110db2a5bSTadhg Kearney if (enabled_uncore < 0) { 180210db2a5bSTadhg Kearney print_usage(prgname); 180310db2a5bSTadhg Kearney return -1; 180410db2a5bSTadhg Kearney } 180510db2a5bSTadhg Kearney break; 180610db2a5bSTadhg Kearney case 'i': 180710db2a5bSTadhg Kearney enabled_uncore = parse_uncore_options(UNCORE_IDX, optarg); 180810db2a5bSTadhg Kearney if (enabled_uncore < 0) { 180910db2a5bSTadhg Kearney print_usage(prgname); 181010db2a5bSTadhg Kearney return -1; 181110db2a5bSTadhg Kearney } 181210db2a5bSTadhg Kearney break; 1813d7937e2eSIntel /* long options */ 1814d7937e2eSIntel case 0: 1815d7937e2eSIntel if (!strncmp(lgopts[option_index].name, "config", 6)) { 1816d7937e2eSIntel ret = parse_config(optarg); 1817d7937e2eSIntel if (ret) { 1818d7937e2eSIntel printf("invalid config\n"); 1819d7937e2eSIntel print_usage(prgname); 1820d7937e2eSIntel return -1; 1821d7937e2eSIntel } 1822d7937e2eSIntel } 1823d7937e2eSIntel 1824d7937e2eSIntel if (!strncmp(lgopts[option_index].name, 1825f88e7c17SRadu Nicolau "perf-config", 11)) { 1826f88e7c17SRadu Nicolau ret = parse_perf_config(optarg); 1827f88e7c17SRadu Nicolau if (ret) { 1828f88e7c17SRadu Nicolau printf("invalid perf-config\n"); 1829f88e7c17SRadu Nicolau print_usage(prgname); 1830f88e7c17SRadu Nicolau return -1; 1831f88e7c17SRadu Nicolau } 1832f88e7c17SRadu Nicolau } 1833f88e7c17SRadu Nicolau 1834f88e7c17SRadu Nicolau if (!strncmp(lgopts[option_index].name, 1835f88e7c17SRadu Nicolau "high-perf-cores", 15)) { 1836f88e7c17SRadu Nicolau ret = parse_perf_core_list(optarg); 1837f88e7c17SRadu Nicolau if (ret) { 1838f88e7c17SRadu Nicolau printf("invalid high-perf-cores\n"); 1839f88e7c17SRadu Nicolau print_usage(prgname); 1840f88e7c17SRadu Nicolau return -1; 1841f88e7c17SRadu Nicolau } 1842f88e7c17SRadu Nicolau } 1843f88e7c17SRadu Nicolau 1844f88e7c17SRadu Nicolau if (!strncmp(lgopts[option_index].name, 1845d7937e2eSIntel "no-numa", 7)) { 1846d7937e2eSIntel printf("numa is disabled \n"); 1847d7937e2eSIntel numa_on = 0; 1848d7937e2eSIntel } 1849d7937e2eSIntel 1850d7937e2eSIntel if (!strncmp(lgopts[option_index].name, 18512a0e2e2dSAnatoly Burakov CMD_LINE_OPT_LEGACY, 18522a0e2e2dSAnatoly Burakov sizeof(CMD_LINE_OPT_LEGACY))) { 18532a0e2e2dSAnatoly Burakov if (app_mode != APP_MODE_DEFAULT) { 18542a0e2e2dSAnatoly Burakov printf(" legacy mode is mutually exclusive with other modes\n"); 18552a0e2e2dSAnatoly Burakov return -1; 18562a0e2e2dSAnatoly Burakov } 18572a0e2e2dSAnatoly Burakov app_mode = APP_MODE_LEGACY; 18582a0e2e2dSAnatoly Burakov printf("legacy mode is enabled\n"); 18592a0e2e2dSAnatoly Burakov } 18602a0e2e2dSAnatoly Burakov 18612a0e2e2dSAnatoly Burakov if (!strncmp(lgopts[option_index].name, 1862609e7984SReshma Pattan CMD_LINE_OPT_TELEMETRY, 1863609e7984SReshma Pattan sizeof(CMD_LINE_OPT_TELEMETRY))) { 18642a0e2e2dSAnatoly Burakov if (app_mode != APP_MODE_DEFAULT) { 18652a0e2e2dSAnatoly Burakov printf(" telemetry mode is mutually exclusive with other modes\n"); 1866609e7984SReshma Pattan return -1; 1867609e7984SReshma Pattan } 1868609e7984SReshma Pattan app_mode = APP_MODE_TELEMETRY; 1869609e7984SReshma Pattan printf("telemetry mode is enabled\n"); 1870a137d012SLiang Ma } 1871a137d012SLiang Ma 1872a137d012SLiang Ma if (!strncmp(lgopts[option_index].name, 187326fe454eSLiang Ma CMD_LINE_OPT_PMD_MGMT, 187426fe454eSLiang Ma sizeof(CMD_LINE_OPT_PMD_MGMT))) { 187526fe454eSLiang Ma if (app_mode != APP_MODE_DEFAULT) { 187626fe454eSLiang Ma printf(" power mgmt mode is mutually exclusive with other modes\n"); 187726fe454eSLiang Ma return -1; 187826fe454eSLiang Ma } 187926fe454eSLiang Ma if (parse_pmd_mgmt_config(optarg) < 0) { 188026fe454eSLiang Ma printf(" Invalid PMD power management mode: %s\n", 188126fe454eSLiang Ma optarg); 188226fe454eSLiang Ma return -1; 188326fe454eSLiang Ma } 188426fe454eSLiang Ma app_mode = APP_MODE_PMD_MGMT; 188526fe454eSLiang Ma printf("PMD power mgmt mode is enabled\n"); 188626fe454eSLiang Ma } 188726fe454eSLiang Ma if (!strncmp(lgopts[option_index].name, 1888e0194febSAnatoly Burakov CMD_LINE_OPT_INTERRUPT_ONLY, 1889e0194febSAnatoly Burakov sizeof(CMD_LINE_OPT_INTERRUPT_ONLY))) { 1890e0194febSAnatoly Burakov if (app_mode != APP_MODE_DEFAULT) { 1891e0194febSAnatoly Burakov printf(" interrupt-only mode is mutually exclusive with other modes\n"); 1892e0194febSAnatoly Burakov return -1; 1893e0194febSAnatoly Burakov } 1894e0194febSAnatoly Burakov app_mode = APP_MODE_INTERRUPT; 1895e0194febSAnatoly Burakov printf("interrupt-only mode is enabled\n"); 1896e0194febSAnatoly Burakov } 1897e0194febSAnatoly Burakov 1898e0194febSAnatoly Burakov if (!strncmp(lgopts[option_index].name, 18991bb4a528SFerruh Yigit CMD_LINE_OPT_MAX_PKT_LEN, 19001bb4a528SFerruh Yigit sizeof(CMD_LINE_OPT_MAX_PKT_LEN))) { 19010bc4795dSHuisong Li if (parse_uint(optarg, UINT32_MAX, &max_pkt_len) != 0) 19020bc4795dSHuisong Li return -1; 19031bb4a528SFerruh Yigit printf("Custom frame size is configured\n"); 1904d7937e2eSIntel } 1905d7937e2eSIntel 190682bea466SJianfeng Tan if (!strncmp(lgopts[option_index].name, 190782bea466SJianfeng Tan CMD_LINE_OPT_PARSE_PTYPE, 190882bea466SJianfeng Tan sizeof(CMD_LINE_OPT_PARSE_PTYPE))) { 190982bea466SJianfeng Tan printf("soft parse-ptype is enabled\n"); 191082bea466SJianfeng Tan parse_ptype = 1; 191182bea466SJianfeng Tan } 191282bea466SJianfeng Tan 191359f2853cSKevin Laatz if (!strncmp(lgopts[option_index].name, 191459f2853cSKevin Laatz CMD_LINE_OPT_MAX_EMPTY_POLLS, 191559f2853cSKevin Laatz sizeof(CMD_LINE_OPT_MAX_EMPTY_POLLS))) { 19160bc4795dSHuisong Li if (parse_uint(optarg, UINT32_MAX, &max_empty_polls) != 0) 19170bc4795dSHuisong Li return -1; 191859f2853cSKevin Laatz printf("Maximum empty polls configured\n"); 191959f2853cSKevin Laatz } 192059f2853cSKevin Laatz 192159f2853cSKevin Laatz if (!strncmp(lgopts[option_index].name, 192259f2853cSKevin Laatz CMD_LINE_OPT_PAUSE_DURATION, 192359f2853cSKevin Laatz sizeof(CMD_LINE_OPT_PAUSE_DURATION))) { 19240bc4795dSHuisong Li if (parse_uint(optarg, UINT32_MAX, &pause_duration) != 0) 19250bc4795dSHuisong Li return -1; 192659f2853cSKevin Laatz printf("Pause duration configured\n"); 192759f2853cSKevin Laatz } 192859f2853cSKevin Laatz 192959f2853cSKevin Laatz if (!strncmp(lgopts[option_index].name, 193059f2853cSKevin Laatz CMD_LINE_OPT_SCALE_FREQ_MIN, 193159f2853cSKevin Laatz sizeof(CMD_LINE_OPT_SCALE_FREQ_MIN))) { 19320bc4795dSHuisong Li if (parse_uint(optarg, UINT32_MAX, &scale_freq_min) != 0) 19330bc4795dSHuisong Li return -1; 193459f2853cSKevin Laatz printf("Scaling frequency minimum configured\n"); 193559f2853cSKevin Laatz } 193659f2853cSKevin Laatz 193759f2853cSKevin Laatz if (!strncmp(lgopts[option_index].name, 193859f2853cSKevin Laatz CMD_LINE_OPT_SCALE_FREQ_MAX, 193959f2853cSKevin Laatz sizeof(CMD_LINE_OPT_SCALE_FREQ_MAX))) { 19400bc4795dSHuisong Li if (parse_uint(optarg, UINT32_MAX, &scale_freq_max) != 0) 19410bc4795dSHuisong Li return -1; 194259f2853cSKevin Laatz printf("Scaling frequency maximum configured\n"); 194359f2853cSKevin Laatz } 194459f2853cSKevin Laatz 19454d23d39fSHuisong Li if (!strncmp(lgopts[option_index].name, 19464d23d39fSHuisong Li CMD_LINE_OPT_CPU_RESUME_LATENCY, 19474d23d39fSHuisong Li sizeof(CMD_LINE_OPT_CPU_RESUME_LATENCY))) { 19484d23d39fSHuisong Li if (parse_uint(optarg, INT_MAX, 19494d23d39fSHuisong Li (uint32_t *)&cpu_resume_latency) != 0) 19504d23d39fSHuisong Li return -1; 19514d23d39fSHuisong Li printf("PM QoS configured\n"); 19524d23d39fSHuisong Li } 19534d23d39fSHuisong Li 1954d7937e2eSIntel break; 1955d7937e2eSIntel 1956d7937e2eSIntel default: 1957d7937e2eSIntel print_usage(prgname); 1958d7937e2eSIntel return -1; 1959d7937e2eSIntel } 1960d7937e2eSIntel } 1961d7937e2eSIntel 1962d7937e2eSIntel if (optind >= 0) 1963d7937e2eSIntel argv[optind-1] = prgname; 1964d7937e2eSIntel 1965d7937e2eSIntel ret = optind-1; 19669d5ca532SKeith Wiles optind = 1; /* reset getopt lib */ 1967d7937e2eSIntel return ret; 1968d7937e2eSIntel } 1969d7937e2eSIntel 1970d7937e2eSIntel static void 19716d13ea8eSOlivier Matz print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 1972d7937e2eSIntel { 197335b2d13fSOlivier Matz char buf[RTE_ETHER_ADDR_FMT_SIZE]; 197435b2d13fSOlivier Matz rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 1975ec3d82dbSCunming Liang printf("%s%s", name, buf); 1976d7937e2eSIntel } 1977d7937e2eSIntel 1978d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 1979d7937e2eSIntel static void 1980d7937e2eSIntel setup_hash(int socketid) 1981d7937e2eSIntel { 1982d7937e2eSIntel struct rte_hash_parameters ipv4_l3fwd_hash_params = { 1983d7937e2eSIntel .name = NULL, 1984d7937e2eSIntel .entries = L3FWD_HASH_ENTRIES, 1985d7937e2eSIntel .key_len = sizeof(struct ipv4_5tuple), 1986d7937e2eSIntel .hash_func = DEFAULT_HASH_FUNC, 1987d7937e2eSIntel .hash_func_init_val = 0, 1988d7937e2eSIntel }; 1989d7937e2eSIntel 1990d7937e2eSIntel struct rte_hash_parameters ipv6_l3fwd_hash_params = { 1991d7937e2eSIntel .name = NULL, 1992d7937e2eSIntel .entries = L3FWD_HASH_ENTRIES, 1993d7937e2eSIntel .key_len = sizeof(struct ipv6_5tuple), 1994d7937e2eSIntel .hash_func = DEFAULT_HASH_FUNC, 1995d7937e2eSIntel .hash_func_init_val = 0, 1996d7937e2eSIntel }; 1997d7937e2eSIntel 1998d7937e2eSIntel unsigned i; 1999d7937e2eSIntel int ret; 2000d7937e2eSIntel char s[64]; 2001d7937e2eSIntel 2002d7937e2eSIntel /* create ipv4 hash */ 2003a5cf3924SThomas Monjalon snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid); 2004d7937e2eSIntel ipv4_l3fwd_hash_params.name = s; 2005d7937e2eSIntel ipv4_l3fwd_hash_params.socket_id = socketid; 2006d7937e2eSIntel ipv4_l3fwd_lookup_struct[socketid] = 2007d7937e2eSIntel rte_hash_create(&ipv4_l3fwd_hash_params); 2008d7937e2eSIntel if (ipv4_l3fwd_lookup_struct[socketid] == NULL) 2009d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " 2010d7937e2eSIntel "socket %d\n", socketid); 2011d7937e2eSIntel 2012d7937e2eSIntel /* create ipv6 hash */ 2013a5cf3924SThomas Monjalon snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid); 2014d7937e2eSIntel ipv6_l3fwd_hash_params.name = s; 2015d7937e2eSIntel ipv6_l3fwd_hash_params.socket_id = socketid; 2016d7937e2eSIntel ipv6_l3fwd_lookup_struct[socketid] = 2017d7937e2eSIntel rte_hash_create(&ipv6_l3fwd_hash_params); 2018d7937e2eSIntel if (ipv6_l3fwd_lookup_struct[socketid] == NULL) 2019d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " 2020d7937e2eSIntel "socket %d\n", socketid); 2021d7937e2eSIntel 2022d7937e2eSIntel 2023d7937e2eSIntel /* populate the ipv4 hash */ 20247efe28bdSPavan Nikhilesh for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) { 2025d7937e2eSIntel ret = rte_hash_add_key (ipv4_l3fwd_lookup_struct[socketid], 2026d7937e2eSIntel (void *) &ipv4_l3fwd_route_array[i].key); 2027d7937e2eSIntel if (ret < 0) { 2028d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" 2029d7937e2eSIntel "l3fwd hash on socket %d\n", i, socketid); 2030d7937e2eSIntel } 2031d7937e2eSIntel ipv4_l3fwd_out_if[ret] = ipv4_l3fwd_route_array[i].if_out; 2032d7937e2eSIntel printf("Hash: Adding key\n"); 2033d7937e2eSIntel print_ipv4_key(ipv4_l3fwd_route_array[i].key); 2034d7937e2eSIntel } 2035d7937e2eSIntel 2036d7937e2eSIntel /* populate the ipv6 hash */ 20377efe28bdSPavan Nikhilesh for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) { 2038d7937e2eSIntel ret = rte_hash_add_key (ipv6_l3fwd_lookup_struct[socketid], 2039d7937e2eSIntel (void *) &ipv6_l3fwd_route_array[i].key); 2040d7937e2eSIntel if (ret < 0) { 2041d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" 2042d7937e2eSIntel "l3fwd hash on socket %d\n", i, socketid); 2043d7937e2eSIntel } 2044d7937e2eSIntel ipv6_l3fwd_out_if[ret] = ipv6_l3fwd_route_array[i].if_out; 2045d7937e2eSIntel printf("Hash: Adding key\n"); 2046d7937e2eSIntel print_ipv6_key(ipv6_l3fwd_route_array[i].key); 2047d7937e2eSIntel } 2048d7937e2eSIntel } 2049d7937e2eSIntel #endif 2050d7937e2eSIntel 2051d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 2052d7937e2eSIntel static void 2053d7937e2eSIntel setup_lpm(int socketid) 2054d7937e2eSIntel { 2055d7937e2eSIntel unsigned i; 2056d7937e2eSIntel int ret; 2057d7937e2eSIntel char s[64]; 2058d7937e2eSIntel 2059d7937e2eSIntel /* create the LPM table */ 2060f1f72618SMichal Kobylinski struct rte_lpm_config lpm_ipv4_config; 2061f1f72618SMichal Kobylinski 2062f1f72618SMichal Kobylinski lpm_ipv4_config.max_rules = IPV4_L3FWD_LPM_MAX_RULES; 2063f1f72618SMichal Kobylinski lpm_ipv4_config.number_tbl8s = 256; 2064f1f72618SMichal Kobylinski lpm_ipv4_config.flags = 0; 2065f1f72618SMichal Kobylinski 20666f41fe75SStephen Hemminger snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid); 2067f1f72618SMichal Kobylinski ipv4_l3fwd_lookup_struct[socketid] = 2068f1f72618SMichal Kobylinski rte_lpm_create(s, socketid, &lpm_ipv4_config); 2069d7937e2eSIntel if (ipv4_l3fwd_lookup_struct[socketid] == NULL) 2070d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" 2071d7937e2eSIntel " on socket %d\n", socketid); 2072d7937e2eSIntel 2073d7937e2eSIntel /* populate the LPM table */ 20747efe28bdSPavan Nikhilesh for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) { 2075d7937e2eSIntel ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid], 2076d7937e2eSIntel ipv4_l3fwd_route_array[i].ip, 2077d7937e2eSIntel ipv4_l3fwd_route_array[i].depth, 2078d7937e2eSIntel ipv4_l3fwd_route_array[i].if_out); 2079d7937e2eSIntel 2080d7937e2eSIntel if (ret < 0) { 2081d7937e2eSIntel rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " 2082d7937e2eSIntel "l3fwd LPM table on socket %d\n", 2083d7937e2eSIntel i, socketid); 2084d7937e2eSIntel } 2085d7937e2eSIntel 2086d7937e2eSIntel printf("LPM: Adding route 0x%08x / %d (%d)\n", 2087d7937e2eSIntel (unsigned)ipv4_l3fwd_route_array[i].ip, 2088d7937e2eSIntel ipv4_l3fwd_route_array[i].depth, 2089d7937e2eSIntel ipv4_l3fwd_route_array[i].if_out); 2090d7937e2eSIntel } 2091d7937e2eSIntel } 2092d7937e2eSIntel #endif 2093d7937e2eSIntel 2094d7937e2eSIntel static int 2095d7937e2eSIntel init_mem(unsigned nb_mbuf) 2096d7937e2eSIntel { 2097d7937e2eSIntel struct lcore_conf *qconf; 2098d7937e2eSIntel int socketid; 2099d7937e2eSIntel unsigned lcore_id; 2100d7937e2eSIntel char s[64]; 2101d7937e2eSIntel 2102d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2103d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 2104d7937e2eSIntel continue; 2105d7937e2eSIntel 2106d7937e2eSIntel if (numa_on) 2107d7937e2eSIntel socketid = rte_lcore_to_socket_id(lcore_id); 2108d7937e2eSIntel else 2109d7937e2eSIntel socketid = 0; 2110d7937e2eSIntel 2111d7937e2eSIntel if (socketid >= NB_SOCKETS) { 2112d7937e2eSIntel rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is " 2113d7937e2eSIntel "out of range %d\n", socketid, 2114d7937e2eSIntel lcore_id, NB_SOCKETS); 2115d7937e2eSIntel } 2116d7937e2eSIntel if (pktmbuf_pool[socketid] == NULL) { 21176f41fe75SStephen Hemminger snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 2118d7937e2eSIntel pktmbuf_pool[socketid] = 2119ea0c20eaSOlivier Matz rte_pktmbuf_pool_create(s, nb_mbuf, 2120824cb29cSKonstantin Ananyev MEMPOOL_CACHE_SIZE, 0, 2121824cb29cSKonstantin Ananyev RTE_MBUF_DEFAULT_BUF_SIZE, 2122ea0c20eaSOlivier Matz socketid); 2123d7937e2eSIntel if (pktmbuf_pool[socketid] == NULL) 2124d7937e2eSIntel rte_exit(EXIT_FAILURE, 2125d7937e2eSIntel "Cannot init mbuf pool on socket %d\n", 2126d7937e2eSIntel socketid); 2127d7937e2eSIntel else 2128d7937e2eSIntel printf("Allocated mbuf pool on socket %d\n", 2129d7937e2eSIntel socketid); 2130d7937e2eSIntel 2131d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 2132d7937e2eSIntel setup_lpm(socketid); 2133d7937e2eSIntel #else 2134d7937e2eSIntel setup_hash(socketid); 2135d7937e2eSIntel #endif 2136d7937e2eSIntel } 2137d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 2138d7937e2eSIntel qconf->ipv4_lookup_struct = ipv4_l3fwd_lookup_struct[socketid]; 2139d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 2140d7937e2eSIntel qconf->ipv6_lookup_struct = ipv6_l3fwd_lookup_struct[socketid]; 2141d7937e2eSIntel #endif 2142d7937e2eSIntel } 2143d7937e2eSIntel return 0; 2144d7937e2eSIntel } 2145d7937e2eSIntel 2146d7937e2eSIntel /* Check the link status of all ports in up to 9s, and print them finally */ 2147d7937e2eSIntel static void 21488728ccf3SThomas Monjalon check_all_ports_link_status(uint32_t port_mask) 2149d7937e2eSIntel { 2150d7937e2eSIntel #define CHECK_INTERVAL 100 /* 100ms */ 2151d7937e2eSIntel #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 2152f8244c63SZhiyong Yang uint8_t count, all_ports_up, print_flag = 0; 2153f8244c63SZhiyong Yang uint16_t portid; 2154d7937e2eSIntel struct rte_eth_link link; 215522e5c73bSIgor Romanov int ret; 2156db4e8135SIvan Dyukov char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 2157d7937e2eSIntel 2158d7937e2eSIntel printf("\nChecking link status"); 2159d7937e2eSIntel fflush(stdout); 2160d7937e2eSIntel for (count = 0; count <= MAX_CHECK_TIME; count++) { 2161d7937e2eSIntel all_ports_up = 1; 21628728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 2163d7937e2eSIntel if ((port_mask & (1 << portid)) == 0) 2164d7937e2eSIntel continue; 2165d7937e2eSIntel memset(&link, 0, sizeof(link)); 216622e5c73bSIgor Romanov ret = rte_eth_link_get_nowait(portid, &link); 216722e5c73bSIgor Romanov if (ret < 0) { 216822e5c73bSIgor Romanov all_ports_up = 0; 216922e5c73bSIgor Romanov if (print_flag == 1) 217022e5c73bSIgor Romanov printf("Port %u link get failed: %s\n", 217122e5c73bSIgor Romanov portid, rte_strerror(-ret)); 217222e5c73bSIgor Romanov continue; 217322e5c73bSIgor Romanov } 2174d7937e2eSIntel /* print link status if flag set */ 2175d7937e2eSIntel if (print_flag == 1) { 2176db4e8135SIvan Dyukov rte_eth_link_to_str(link_status_text, 2177db4e8135SIvan Dyukov sizeof(link_status_text), &link); 2178db4e8135SIvan Dyukov printf("Port %d %s\n", portid, 2179db4e8135SIvan Dyukov link_status_text); 2180d7937e2eSIntel continue; 2181d7937e2eSIntel } 2182d7937e2eSIntel /* clear all_ports_up flag if any link down */ 2183295968d1SFerruh Yigit if (link.link_status == RTE_ETH_LINK_DOWN) { 2184d7937e2eSIntel all_ports_up = 0; 2185d7937e2eSIntel break; 2186d7937e2eSIntel } 2187d7937e2eSIntel } 2188d7937e2eSIntel /* after finally printing all link status, get out */ 2189d7937e2eSIntel if (print_flag == 1) 2190d7937e2eSIntel break; 2191d7937e2eSIntel 2192d7937e2eSIntel if (all_ports_up == 0) { 2193d7937e2eSIntel printf("."); 2194d7937e2eSIntel fflush(stdout); 2195d7937e2eSIntel rte_delay_ms(CHECK_INTERVAL); 2196d7937e2eSIntel } 2197d7937e2eSIntel 2198d7937e2eSIntel /* set the print_flag if all ports up or timeout */ 2199d7937e2eSIntel if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 2200d7937e2eSIntel print_flag = 1; 2201d7937e2eSIntel printf("done\n"); 2202d7937e2eSIntel } 2203d7937e2eSIntel } 2204d7937e2eSIntel } 2205d7937e2eSIntel 220647523597SZhiyong Yang static int check_ptype(uint16_t portid) 220782bea466SJianfeng Tan { 220882bea466SJianfeng Tan int i, ret; 220982bea466SJianfeng Tan int ptype_l3_ipv4 = 0; 221082bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 221182bea466SJianfeng Tan int ptype_l3_ipv6 = 0; 221282bea466SJianfeng Tan #endif 221382bea466SJianfeng Tan uint32_t ptype_mask = RTE_PTYPE_L3_MASK; 221482bea466SJianfeng Tan 221582bea466SJianfeng Tan ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0); 221682bea466SJianfeng Tan if (ret <= 0) 221782bea466SJianfeng Tan return 0; 221882bea466SJianfeng Tan 221982bea466SJianfeng Tan uint32_t ptypes[ret]; 222082bea466SJianfeng Tan 222182bea466SJianfeng Tan ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, ret); 222282bea466SJianfeng Tan for (i = 0; i < ret; ++i) { 222382bea466SJianfeng Tan if (ptypes[i] & RTE_PTYPE_L3_IPV4) 222482bea466SJianfeng Tan ptype_l3_ipv4 = 1; 222582bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 222682bea466SJianfeng Tan if (ptypes[i] & RTE_PTYPE_L3_IPV6) 222782bea466SJianfeng Tan ptype_l3_ipv6 = 1; 222882bea466SJianfeng Tan #endif 222982bea466SJianfeng Tan } 223082bea466SJianfeng Tan 223182bea466SJianfeng Tan if (ptype_l3_ipv4 == 0) 223282bea466SJianfeng Tan printf("port %d cannot parse RTE_PTYPE_L3_IPV4\n", portid); 223382bea466SJianfeng Tan 223482bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) 223582bea466SJianfeng Tan if (ptype_l3_ipv6 == 0) 223682bea466SJianfeng Tan printf("port %d cannot parse RTE_PTYPE_L3_IPV6\n", portid); 223782bea466SJianfeng Tan #endif 223882bea466SJianfeng Tan 223982bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) 224082bea466SJianfeng Tan if (ptype_l3_ipv4) 224182bea466SJianfeng Tan #else /* APP_LOOKUP_EXACT_MATCH */ 224282bea466SJianfeng Tan if (ptype_l3_ipv4 && ptype_l3_ipv6) 224382bea466SJianfeng Tan #endif 224482bea466SJianfeng Tan return 1; 224582bea466SJianfeng Tan 224682bea466SJianfeng Tan return 0; 224782bea466SJianfeng Tan 224882bea466SJianfeng Tan } 224982bea466SJianfeng Tan 2250f88e7c17SRadu Nicolau static int 2251f88e7c17SRadu Nicolau init_power_library(void) 2252f88e7c17SRadu Nicolau { 22539b133b42SAnatoly Burakov enum power_management_env env; 2254a163130bSAnatoly Burakov unsigned int lcore_id; 2255a163130bSAnatoly Burakov int ret = 0; 2256a163130bSAnatoly Burakov 2257a163130bSAnatoly Burakov RTE_LCORE_FOREACH(lcore_id) { 2258f88e7c17SRadu Nicolau /* init power management library */ 2259f88e7c17SRadu Nicolau ret = rte_power_init(lcore_id); 2260a163130bSAnatoly Burakov if (ret) { 22618bae59edSStephen Hemminger RTE_LOG(ERR, L3FWD_POWER, 2262f88e7c17SRadu Nicolau "Library initialization failed on core %u\n", 2263f88e7c17SRadu Nicolau lcore_id); 2264a163130bSAnatoly Burakov return ret; 2265f88e7c17SRadu Nicolau } 22669b133b42SAnatoly Burakov /* we're not supporting the VM channel mode */ 22679b133b42SAnatoly Burakov env = rte_power_get_env(); 22689b133b42SAnatoly Burakov if (env != PM_ENV_ACPI_CPUFREQ && 2269bc6fe484SJie Hai env != PM_ENV_PSTATE_CPUFREQ && 22701ed04d33SSivaprasad Tummala env != PM_ENV_AMD_PSTATE_CPUFREQ && 2271bc6fe484SJie Hai env != PM_ENV_CPPC_CPUFREQ) { 22728bae59edSStephen Hemminger RTE_LOG(ERR, L3FWD_POWER, 22738bae59edSStephen Hemminger "Only ACPI and PSTATE mode are supported\n"); 22749b133b42SAnatoly Burakov return -1; 22759b133b42SAnatoly Burakov } 2276f88e7c17SRadu Nicolau } 22774d23d39fSHuisong Li 22784d23d39fSHuisong Li if (cpu_resume_latency != -1) { 22794d23d39fSHuisong Li RTE_LCORE_FOREACH(lcore_id) { 22804d23d39fSHuisong Li /* Back old CPU resume latency. */ 22814d23d39fSHuisong Li ret = rte_power_qos_get_cpu_resume_latency(lcore_id); 22824d23d39fSHuisong Li if (ret < 0) { 22834d23d39fSHuisong Li RTE_LOG(ERR, L3FWD_POWER, 22844d23d39fSHuisong Li "Failed to get cpu resume latency on lcore-%u, ret=%d.\n", 22854d23d39fSHuisong Li lcore_id, ret); 22864d23d39fSHuisong Li } 22874d23d39fSHuisong Li resume_latency_bk[lcore_id] = ret; 22884d23d39fSHuisong Li 22894d23d39fSHuisong Li /* 22904d23d39fSHuisong Li * Set the cpu resume latency of the worker lcore based 22914d23d39fSHuisong Li * on user's request. If set strict latency (0), just 22924d23d39fSHuisong Li * allow the CPU to enter the shallowest idle state to 22934d23d39fSHuisong Li * improve performance. 22944d23d39fSHuisong Li */ 22954d23d39fSHuisong Li ret = rte_power_qos_set_cpu_resume_latency(lcore_id, 22964d23d39fSHuisong Li cpu_resume_latency); 22974d23d39fSHuisong Li if (ret != 0) { 22984d23d39fSHuisong Li RTE_LOG(ERR, L3FWD_POWER, 22994d23d39fSHuisong Li "Failed to set cpu resume latency on lcore-%u, ret=%d.\n", 23004d23d39fSHuisong Li lcore_id, ret); 23014d23d39fSHuisong Li return ret; 23024d23d39fSHuisong Li } 23034d23d39fSHuisong Li } 23044d23d39fSHuisong Li } 23054d23d39fSHuisong Li 2306f88e7c17SRadu Nicolau return ret; 2307f88e7c17SRadu Nicolau } 2308613ce669SAnatoly Burakov 2309613ce669SAnatoly Burakov static int 2310613ce669SAnatoly Burakov deinit_power_library(void) 2311613ce669SAnatoly Burakov { 231210db2a5bSTadhg Kearney unsigned int lcore_id, max_pkg, max_die, die, pkg; 2313613ce669SAnatoly Burakov int ret = 0; 2314613ce669SAnatoly Burakov 2315613ce669SAnatoly Burakov RTE_LCORE_FOREACH(lcore_id) { 2316613ce669SAnatoly Burakov /* deinit power management library */ 2317613ce669SAnatoly Burakov ret = rte_power_exit(lcore_id); 2318613ce669SAnatoly Burakov if (ret) { 23198bae59edSStephen Hemminger RTE_LOG(ERR, L3FWD_POWER, 2320613ce669SAnatoly Burakov "Library deinitialization failed on core %u\n", 2321613ce669SAnatoly Burakov lcore_id); 2322613ce669SAnatoly Burakov return ret; 2323613ce669SAnatoly Burakov } 2324613ce669SAnatoly Burakov } 232510db2a5bSTadhg Kearney 232610db2a5bSTadhg Kearney /* if uncore option was set */ 232710db2a5bSTadhg Kearney if (enabled_uncore == 0) { 232810db2a5bSTadhg Kearney max_pkg = rte_power_uncore_get_num_pkgs(); 232910db2a5bSTadhg Kearney if (max_pkg == 0) 233010db2a5bSTadhg Kearney return -1; 233110db2a5bSTadhg Kearney for (pkg = 0; pkg < max_pkg; pkg++) { 233210db2a5bSTadhg Kearney max_die = rte_power_uncore_get_num_dies(pkg); 233310db2a5bSTadhg Kearney if (max_die == 0) 233410db2a5bSTadhg Kearney return -1; 233510db2a5bSTadhg Kearney for (die = 0; die < max_die; die++) { 233610db2a5bSTadhg Kearney ret = rte_power_uncore_exit(pkg, die); 233710db2a5bSTadhg Kearney if (ret < 0) { 233810db2a5bSTadhg Kearney RTE_LOG(ERR, L3FWD_POWER, "Failed to exit uncore deinit successfully for pkg %02u die %02u\n" 233910db2a5bSTadhg Kearney , pkg, die); 234010db2a5bSTadhg Kearney return -1; 234110db2a5bSTadhg Kearney } 234210db2a5bSTadhg Kearney } 234310db2a5bSTadhg Kearney } 234410db2a5bSTadhg Kearney } 23454d23d39fSHuisong Li 23464d23d39fSHuisong Li if (cpu_resume_latency != -1) { 23474d23d39fSHuisong Li RTE_LCORE_FOREACH(lcore_id) { 23484d23d39fSHuisong Li /* Restore the original value. */ 23494d23d39fSHuisong Li rte_power_qos_set_cpu_resume_latency(lcore_id, 23504d23d39fSHuisong Li resume_latency_bk[lcore_id]); 23514d23d39fSHuisong Li } 23524d23d39fSHuisong Li } 23534d23d39fSHuisong Li 2354613ce669SAnatoly Burakov return ret; 2355613ce669SAnatoly Burakov } 2356613ce669SAnatoly Burakov 2357a137d012SLiang Ma static void 2358a35919a1SCiara Power get_current_stat_values(uint64_t *values) 2359609e7984SReshma Pattan { 2360609e7984SReshma Pattan unsigned int lcore_id = rte_lcore_id(); 2361609e7984SReshma Pattan struct lcore_conf *qconf; 2362609e7984SReshma Pattan uint64_t app_eps = 0, app_fps = 0, app_br = 0; 2363609e7984SReshma Pattan uint64_t count = 0; 2364609e7984SReshma Pattan 2365cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 2366609e7984SReshma Pattan qconf = &lcore_conf[lcore_id]; 2367609e7984SReshma Pattan if (qconf->n_rx_queue == 0) 2368609e7984SReshma Pattan continue; 2369609e7984SReshma Pattan count++; 2370609e7984SReshma Pattan rte_spinlock_lock(&stats[lcore_id].telemetry_lock); 2371609e7984SReshma Pattan app_eps += stats[lcore_id].ep_nep[1]; 2372609e7984SReshma Pattan app_fps += stats[lcore_id].fp_nfp[1]; 2373609e7984SReshma Pattan app_br += stats[lcore_id].br; 2374609e7984SReshma Pattan rte_spinlock_unlock(&stats[lcore_id].telemetry_lock); 2375609e7984SReshma Pattan } 2376609e7984SReshma Pattan 2377018faf21SDavid Hunt if (count > 0) { 2378018faf21SDavid Hunt values[0] = app_eps/count; 2379018faf21SDavid Hunt values[1] = app_fps/count; 2380018faf21SDavid Hunt values[2] = app_br/count; 2381a35919a1SCiara Power } else 2382a35919a1SCiara Power memset(values, 0, sizeof(uint64_t) * NUM_TELSTATS); 2383a35919a1SCiara Power 2384018faf21SDavid Hunt } 2385018faf21SDavid Hunt 2386a35919a1SCiara Power static void 2387a35919a1SCiara Power update_telemetry(__rte_unused struct rte_timer *tim, 2388a35919a1SCiara Power __rte_unused void *arg) 2389a35919a1SCiara Power { 2390a35919a1SCiara Power int ret; 2391a35919a1SCiara Power uint64_t values[NUM_TELSTATS] = {0}; 2392a35919a1SCiara Power 2393a35919a1SCiara Power get_current_stat_values(values); 2394609e7984SReshma Pattan ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, telstats_index, 2395609e7984SReshma Pattan values, RTE_DIM(values)); 2396609e7984SReshma Pattan if (ret < 0) 23978bae59edSStephen Hemminger RTE_LOG(WARNING, L3FWD_POWER, "failed to update metrics\n"); 2398609e7984SReshma Pattan } 2399eeb486f3SCiara Power 2400a35919a1SCiara Power static int 2401a35919a1SCiara Power handle_app_stats(const char *cmd __rte_unused, 2402a35919a1SCiara Power const char *params __rte_unused, 2403a35919a1SCiara Power struct rte_tel_data *d) 2404a35919a1SCiara Power { 2405a35919a1SCiara Power uint64_t values[NUM_TELSTATS] = {0}; 2406a35919a1SCiara Power uint32_t i; 2407a35919a1SCiara Power 2408a35919a1SCiara Power rte_tel_data_start_dict(d); 2409a35919a1SCiara Power get_current_stat_values(values); 2410a35919a1SCiara Power for (i = 0; i < NUM_TELSTATS; i++) 2411af0785a2SBruce Richardson rte_tel_data_add_dict_uint(d, telstats_strings[i].name, 2412a35919a1SCiara Power values[i]); 2413a35919a1SCiara Power return 0; 2414a35919a1SCiara Power } 2415eeb486f3SCiara Power 2416609e7984SReshma Pattan static void 2417609e7984SReshma Pattan telemetry_setup_timer(void) 2418609e7984SReshma Pattan { 2419609e7984SReshma Pattan int lcore_id = rte_lcore_id(); 2420609e7984SReshma Pattan uint64_t hz = rte_get_timer_hz(); 2421609e7984SReshma Pattan uint64_t ticks; 2422609e7984SReshma Pattan 2423609e7984SReshma Pattan ticks = hz / TELEMETRY_INTERVALS_PER_SEC; 2424609e7984SReshma Pattan rte_timer_reset_sync(&telemetry_timer, 2425609e7984SReshma Pattan ticks, 2426609e7984SReshma Pattan PERIODICAL, 2427609e7984SReshma Pattan lcore_id, 2428609e7984SReshma Pattan update_telemetry, 2429609e7984SReshma Pattan NULL); 2430609e7984SReshma Pattan } 2431a137d012SLiang Ma 2432a137d012SLiang Ma static int 2433a137d012SLiang Ma launch_timer(unsigned int lcore_id) 2434a137d012SLiang Ma { 2435a137d012SLiang Ma int64_t prev_tsc = 0, cur_tsc, diff_tsc, cycles_10ms; 2436a137d012SLiang Ma 2437a137d012SLiang Ma RTE_SET_USED(lcore_id); 2438a137d012SLiang Ma 2439a137d012SLiang Ma 2440cb056611SStephen Hemminger if (rte_get_main_lcore() != lcore_id) { 2441cb056611SStephen Hemminger rte_panic("timer on lcore:%d which is not main core:%d\n", 2442a137d012SLiang Ma lcore_id, 2443cb056611SStephen Hemminger rte_get_main_lcore()); 2444a137d012SLiang Ma } 2445a137d012SLiang Ma 24468bae59edSStephen Hemminger RTE_LOG(INFO, L3FWD_POWER, "Bring up the Timer\n"); 2447a137d012SLiang Ma 2448609e7984SReshma Pattan telemetry_setup_timer(); 2449a137d012SLiang Ma 2450a137d012SLiang Ma cycles_10ms = rte_get_timer_hz() / 100; 2451a137d012SLiang Ma 2452a137d012SLiang Ma while (!is_done()) { 2453a137d012SLiang Ma cur_tsc = rte_rdtsc(); 2454a137d012SLiang Ma diff_tsc = cur_tsc - prev_tsc; 2455a137d012SLiang Ma if (diff_tsc > cycles_10ms) { 2456a137d012SLiang Ma rte_timer_manage(); 2457a137d012SLiang Ma prev_tsc = cur_tsc; 2458a137d012SLiang Ma cycles_10ms = rte_get_timer_hz() / 100; 2459a137d012SLiang Ma } 2460a137d012SLiang Ma } 2461a137d012SLiang Ma 24628bae59edSStephen Hemminger RTE_LOG(INFO, L3FWD_POWER, "Timer_subsystem is done\n"); 2463a137d012SLiang Ma 2464a137d012SLiang Ma return 0; 2465a137d012SLiang Ma } 2466a137d012SLiang Ma 246711159dd6SAnatoly Burakov static int 246811159dd6SAnatoly Burakov autodetect_mode(void) 246911159dd6SAnatoly Burakov { 247011159dd6SAnatoly Burakov RTE_LOG(NOTICE, L3FWD_POWER, "Operating mode not specified, probing frequency scaling support...\n"); 247111159dd6SAnatoly Burakov 247211159dd6SAnatoly Burakov /* 247311159dd6SAnatoly Burakov * Empty poll and telemetry modes have to be specifically requested to 247411159dd6SAnatoly Burakov * be enabled, but we can auto-detect between interrupt mode with or 2475bc6fe484SJie Hai * without frequency scaling. Any of ACPI, pstate and CPPC can be used. 247611159dd6SAnatoly Burakov */ 247711159dd6SAnatoly Burakov if (rte_power_check_env_supported(PM_ENV_ACPI_CPUFREQ)) 247811159dd6SAnatoly Burakov return APP_MODE_LEGACY; 247911159dd6SAnatoly Burakov if (rte_power_check_env_supported(PM_ENV_PSTATE_CPUFREQ)) 248011159dd6SAnatoly Burakov return APP_MODE_LEGACY; 24811ed04d33SSivaprasad Tummala if (rte_power_check_env_supported(PM_ENV_AMD_PSTATE_CPUFREQ)) 24821ed04d33SSivaprasad Tummala return APP_MODE_LEGACY; 2483bc6fe484SJie Hai if (rte_power_check_env_supported(PM_ENV_CPPC_CPUFREQ)) 2484bc6fe484SJie Hai return APP_MODE_LEGACY; 248511159dd6SAnatoly Burakov 248611159dd6SAnatoly Burakov RTE_LOG(NOTICE, L3FWD_POWER, "Frequency scaling not supported, selecting interrupt-only mode\n"); 248711159dd6SAnatoly Burakov 248811159dd6SAnatoly Burakov return APP_MODE_INTERRUPT; 248911159dd6SAnatoly Burakov } 249011159dd6SAnatoly Burakov 249111159dd6SAnatoly Burakov static const char * 249211159dd6SAnatoly Burakov mode_to_str(enum appmode mode) 249311159dd6SAnatoly Burakov { 249411159dd6SAnatoly Burakov switch (mode) { 249511159dd6SAnatoly Burakov case APP_MODE_LEGACY: 249611159dd6SAnatoly Burakov return "legacy"; 249711159dd6SAnatoly Burakov case APP_MODE_TELEMETRY: 249811159dd6SAnatoly Burakov return "telemetry"; 249911159dd6SAnatoly Burakov case APP_MODE_INTERRUPT: 250011159dd6SAnatoly Burakov return "interrupt-only"; 250126fe454eSLiang Ma case APP_MODE_PMD_MGMT: 250226fe454eSLiang Ma return "pmd mgmt"; 250311159dd6SAnatoly Burakov default: 250411159dd6SAnatoly Burakov return "invalid"; 250511159dd6SAnatoly Burakov } 250611159dd6SAnatoly Burakov } 2507f88e7c17SRadu Nicolau 25081bb4a528SFerruh Yigit static uint32_t 25091bb4a528SFerruh Yigit eth_dev_get_overhead_len(uint32_t max_rx_pktlen, uint16_t max_mtu) 25101bb4a528SFerruh Yigit { 25111bb4a528SFerruh Yigit uint32_t overhead_len; 25121bb4a528SFerruh Yigit 25131bb4a528SFerruh Yigit if (max_mtu != UINT16_MAX && max_rx_pktlen > max_mtu) 25141bb4a528SFerruh Yigit overhead_len = max_rx_pktlen - max_mtu; 25151bb4a528SFerruh Yigit else 25161bb4a528SFerruh Yigit overhead_len = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN; 25171bb4a528SFerruh Yigit 25181bb4a528SFerruh Yigit return overhead_len; 25191bb4a528SFerruh Yigit } 25201bb4a528SFerruh Yigit 25211bb4a528SFerruh Yigit static int 25221bb4a528SFerruh Yigit config_port_max_pkt_len(struct rte_eth_conf *conf, 25231bb4a528SFerruh Yigit struct rte_eth_dev_info *dev_info) 25241bb4a528SFerruh Yigit { 25251bb4a528SFerruh Yigit uint32_t overhead_len; 25261bb4a528SFerruh Yigit 25271bb4a528SFerruh Yigit if (max_pkt_len == 0) 25281bb4a528SFerruh Yigit return 0; 25291bb4a528SFerruh Yigit 25301bb4a528SFerruh Yigit if (max_pkt_len < RTE_ETHER_MIN_LEN || max_pkt_len > MAX_JUMBO_PKT_LEN) 25311bb4a528SFerruh Yigit return -1; 25321bb4a528SFerruh Yigit 25331bb4a528SFerruh Yigit overhead_len = eth_dev_get_overhead_len(dev_info->max_rx_pktlen, 25341bb4a528SFerruh Yigit dev_info->max_mtu); 25351bb4a528SFerruh Yigit conf->rxmode.mtu = max_pkt_len - overhead_len; 25361bb4a528SFerruh Yigit 2537b563c142SFerruh Yigit if (conf->rxmode.mtu > RTE_ETHER_MTU) 2538295968d1SFerruh Yigit conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 25391bb4a528SFerruh Yigit 25401bb4a528SFerruh Yigit return 0; 25411bb4a528SFerruh Yigit } 25421bb4a528SFerruh Yigit 25439a212dc0SConor Fogarty /* Power library initialized in the main routine. 8< */ 2544d7937e2eSIntel int 254598a16481SDavid Marchand main(int argc, char **argv) 2546d7937e2eSIntel { 2547d7937e2eSIntel struct lcore_conf *qconf; 254881f7ecd9SPablo de Lara struct rte_eth_dev_info dev_info; 254981f7ecd9SPablo de Lara struct rte_eth_txconf *txconf; 2550d7937e2eSIntel int ret; 255147523597SZhiyong Yang uint16_t nb_ports; 2552d7937e2eSIntel uint16_t queueid; 2553d7937e2eSIntel unsigned lcore_id; 2554d7937e2eSIntel uint64_t hz; 2555d7937e2eSIntel uint32_t n_tx_queue, nb_lcores; 2556aee3bc79SCunming Liang uint32_t dev_rxq_num, dev_txq_num; 2557b23c5bd7SSivaprasad Tummala uint8_t socketid; 2558b23c5bd7SSivaprasad Tummala uint16_t portid, nb_rx_queue, queue; 2559a35919a1SCiara Power const char *ptr_strings[NUM_TELSTATS]; 2560d7937e2eSIntel 2561d7937e2eSIntel /* init EAL */ 2562d7937e2eSIntel ret = rte_eal_init(argc, argv); 2563d7937e2eSIntel if (ret < 0) 2564d7937e2eSIntel rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 2565d7937e2eSIntel argc -= ret; 2566d7937e2eSIntel argv += ret; 2567d7937e2eSIntel 256819781e7aSHarneet Singh /* catch SIGINT and restore cpufreq governor to ondemand */ 256919781e7aSHarneet Singh signal(SIGINT, signal_exit_now); 257019781e7aSHarneet Singh 2571d7937e2eSIntel /* init RTE timer library to be used late */ 2572d7937e2eSIntel rte_timer_subsystem_init(); 2573d7937e2eSIntel 2574a9ea6070SDavid Hunt /* if we're running pmd-mgmt mode, don't default to baseline mode */ 2575a9ea6070SDavid Hunt baseline_enabled = false; 2576a9ea6070SDavid Hunt 2577d7937e2eSIntel /* parse application arguments (after the EAL ones) */ 2578d7937e2eSIntel ret = parse_args(argc, argv); 2579d7937e2eSIntel if (ret < 0) 2580d7937e2eSIntel rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); 2581d7937e2eSIntel 25822a0e2e2dSAnatoly Burakov if (app_mode == APP_MODE_DEFAULT) 258311159dd6SAnatoly Burakov app_mode = autodetect_mode(); 258411159dd6SAnatoly Burakov 258511159dd6SAnatoly Burakov RTE_LOG(INFO, L3FWD_POWER, "Selected operation mode: %s\n", 258611159dd6SAnatoly Burakov mode_to_str(app_mode)); 25872a0e2e2dSAnatoly Burakov 25889c75ff42SDavid Hunt /* only legacy mode relies on power library */ 25899c75ff42SDavid Hunt if ((app_mode == APP_MODE_LEGACY) && init_power_library()) 2590a163130bSAnatoly Burakov rte_exit(EXIT_FAILURE, "init_power_library failed\n"); 2591f88e7c17SRadu Nicolau 2592f88e7c17SRadu Nicolau if (update_lcore_params() < 0) 2593f88e7c17SRadu Nicolau rte_exit(EXIT_FAILURE, "update_lcore_params failed\n"); 2594f88e7c17SRadu Nicolau 2595d7937e2eSIntel if (check_lcore_params() < 0) 2596d7937e2eSIntel rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); 2597d7937e2eSIntel 2598d7937e2eSIntel ret = init_lcore_rx_queues(); 2599d7937e2eSIntel if (ret < 0) 2600d7937e2eSIntel rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); 2601d7937e2eSIntel 2602d9a42a69SThomas Monjalon nb_ports = rte_eth_dev_count_avail(); 2603d7937e2eSIntel 2604a9dbe180SThomas Monjalon if (check_port_config() < 0) 2605d7937e2eSIntel rte_exit(EXIT_FAILURE, "check_port_config failed\n"); 2606d7937e2eSIntel 2607d7937e2eSIntel nb_lcores = rte_lcore_count(); 2608d7937e2eSIntel 2609d7937e2eSIntel /* initialize all ports */ 26108728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 261140df1d7aSShahaf Shuler struct rte_eth_conf local_port_conf = port_conf; 2612f06493adSAnatoly Burakov /* not all app modes need interrupts */ 2613e0194febSAnatoly Burakov bool need_intr = app_mode == APP_MODE_LEGACY || 2614e0194febSAnatoly Burakov app_mode == APP_MODE_INTERRUPT; 261540df1d7aSShahaf Shuler 2616d7937e2eSIntel /* skip ports that are not enabled */ 2617d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 2618d7937e2eSIntel printf("\nSkipping disabled port %d\n", portid); 2619d7937e2eSIntel continue; 2620d7937e2eSIntel } 2621d7937e2eSIntel 2622d7937e2eSIntel /* init port */ 2623d7937e2eSIntel printf("Initializing port %d ... ", portid ); 2624d7937e2eSIntel fflush(stdout); 2625d7937e2eSIntel 2626089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2627089e5ed7SIvan Ilchenko if (ret != 0) 2628089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2629089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2630089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2631089e5ed7SIvan Ilchenko 2632aee3bc79SCunming Liang dev_rxq_num = dev_info.max_rx_queues; 2633aee3bc79SCunming Liang dev_txq_num = dev_info.max_tx_queues; 2634aee3bc79SCunming Liang 2635d7937e2eSIntel nb_rx_queue = get_port_n_rx_queues(portid); 2636aee3bc79SCunming Liang if (nb_rx_queue > dev_rxq_num) 2637aee3bc79SCunming Liang rte_exit(EXIT_FAILURE, 2638aee3bc79SCunming Liang "Cannot configure not existed rxq: " 2639aee3bc79SCunming Liang "port=%d\n", portid); 2640aee3bc79SCunming Liang 2641d7937e2eSIntel n_tx_queue = nb_lcores; 2642aee3bc79SCunming Liang if (n_tx_queue > dev_txq_num) 2643aee3bc79SCunming Liang n_tx_queue = dev_txq_num; 2644d7937e2eSIntel printf("Creating queues: nb_rxq=%d nb_txq=%u... ", 2645d7937e2eSIntel nb_rx_queue, (unsigned)n_tx_queue ); 2646ddc554adSJingjing Wu /* If number of Rx queue is 0, no need to enable Rx interrupt */ 2647ddc554adSJingjing Wu if (nb_rx_queue == 0) 2648f06493adSAnatoly Burakov need_intr = false; 2649f06493adSAnatoly Burakov 2650f06493adSAnatoly Burakov if (need_intr) 2651f06493adSAnatoly Burakov local_port_conf.intr_conf.rxq = 1; 2652089e5ed7SIvan Ilchenko 2653089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2654089e5ed7SIvan Ilchenko if (ret != 0) 2655089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2656089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2657089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2658089e5ed7SIvan Ilchenko 26591bb4a528SFerruh Yigit ret = config_port_max_pkt_len(&local_port_conf, &dev_info); 26601bb4a528SFerruh Yigit if (ret != 0) 26611bb4a528SFerruh Yigit rte_exit(EXIT_FAILURE, 26621bb4a528SFerruh Yigit "Invalid max packet length: %u (port %u)\n", 26631bb4a528SFerruh Yigit max_pkt_len, portid); 26641bb4a528SFerruh Yigit 2665295968d1SFerruh Yigit if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) 266640df1d7aSShahaf Shuler local_port_conf.txmode.offloads |= 2667295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 26684f5701f2SFerruh Yigit 26694f5701f2SFerruh Yigit local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 26704f5701f2SFerruh Yigit dev_info.flow_type_rss_offloads; 26714f5701f2SFerruh Yigit if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 26724f5701f2SFerruh Yigit port_conf.rx_adv_conf.rss_conf.rss_hf) { 26734f5701f2SFerruh Yigit printf("Port %u modified RSS hash function based on hardware support," 26744f5701f2SFerruh Yigit "requested:%#"PRIx64" configured:%#"PRIx64"\n", 26754f5701f2SFerruh Yigit portid, 26764f5701f2SFerruh Yigit port_conf.rx_adv_conf.rss_conf.rss_hf, 26774f5701f2SFerruh Yigit local_port_conf.rx_adv_conf.rss_conf.rss_hf); 26784f5701f2SFerruh Yigit } 26794f5701f2SFerruh Yigit 2680f0b00d98SMiao Li if (local_port_conf.rx_adv_conf.rss_conf.rss_hf == 0) 2681f0b00d98SMiao Li local_port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; 2682f0b00d98SMiao Li local_port_conf.rxmode.offloads &= dev_info.rx_offload_capa; 2683f0b00d98SMiao Li port_conf.rxmode.offloads = local_port_conf.rxmode.offloads; 2684f0b00d98SMiao Li 2685d7937e2eSIntel ret = rte_eth_dev_configure(portid, nb_rx_queue, 268640df1d7aSShahaf Shuler (uint16_t)n_tx_queue, &local_port_conf); 2687d7937e2eSIntel if (ret < 0) 2688d7937e2eSIntel rte_exit(EXIT_FAILURE, "Cannot configure device: " 2689d7937e2eSIntel "err=%d, port=%d\n", ret, portid); 2690d7937e2eSIntel 269160efb44fSRoman Zhukov ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 269260efb44fSRoman Zhukov &nb_txd); 269360efb44fSRoman Zhukov if (ret < 0) 269460efb44fSRoman Zhukov rte_exit(EXIT_FAILURE, 269560efb44fSRoman Zhukov "Cannot adjust number of descriptors: err=%d, port=%d\n", 269660efb44fSRoman Zhukov ret, portid); 269760efb44fSRoman Zhukov 269870febdcfSIgor Romanov ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 269970febdcfSIgor Romanov if (ret < 0) 270070febdcfSIgor Romanov rte_exit(EXIT_FAILURE, 270170febdcfSIgor Romanov "Cannot get MAC address: err=%d, port=%d\n", 270270febdcfSIgor Romanov ret, portid); 270370febdcfSIgor Romanov 2704d7937e2eSIntel print_ethaddr(" Address:", &ports_eth_addr[portid]); 2705d7937e2eSIntel printf(", "); 2706d7937e2eSIntel 2707d7937e2eSIntel /* init memory */ 2708d7937e2eSIntel ret = init_mem(NB_MBUF); 2709d7937e2eSIntel if (ret < 0) 2710d7937e2eSIntel rte_exit(EXIT_FAILURE, "init_mem failed\n"); 2711d7937e2eSIntel 2712e2366e74STomasz Kulasek for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2713e2366e74STomasz Kulasek if (rte_lcore_is_enabled(lcore_id) == 0) 2714e2366e74STomasz Kulasek continue; 2715e2366e74STomasz Kulasek 2716e2366e74STomasz Kulasek /* Initialize TX buffers */ 2717e2366e74STomasz Kulasek qconf = &lcore_conf[lcore_id]; 2718e2366e74STomasz Kulasek qconf->tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", 2719e2366e74STomasz Kulasek RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, 2720e2366e74STomasz Kulasek rte_eth_dev_socket_id(portid)); 2721e2366e74STomasz Kulasek if (qconf->tx_buffer[portid] == NULL) 2722e2366e74STomasz Kulasek rte_exit(EXIT_FAILURE, "Can't allocate tx buffer for port %u\n", 2723f8244c63SZhiyong Yang portid); 2724e2366e74STomasz Kulasek 2725e2366e74STomasz Kulasek rte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST); 2726e2366e74STomasz Kulasek } 2727e2366e74STomasz Kulasek 2728d7937e2eSIntel /* init one TX queue per couple (lcore,port) */ 2729d7937e2eSIntel queueid = 0; 2730d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2731d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 2732d7937e2eSIntel continue; 2733d7937e2eSIntel 2734aee3bc79SCunming Liang if (queueid >= dev_txq_num) 2735aee3bc79SCunming Liang continue; 2736aee3bc79SCunming Liang 2737d7937e2eSIntel if (numa_on) 2738d7937e2eSIntel socketid = \ 2739d7937e2eSIntel (uint8_t)rte_lcore_to_socket_id(lcore_id); 2740d7937e2eSIntel else 2741d7937e2eSIntel socketid = 0; 2742d7937e2eSIntel 2743d7937e2eSIntel printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); 2744d7937e2eSIntel fflush(stdout); 274581f7ecd9SPablo de Lara 274681f7ecd9SPablo de Lara txconf = &dev_info.default_txconf; 274740df1d7aSShahaf Shuler txconf->offloads = local_port_conf.txmode.offloads; 2748d7937e2eSIntel ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 274981f7ecd9SPablo de Lara socketid, txconf); 2750d7937e2eSIntel if (ret < 0) 2751d7937e2eSIntel rte_exit(EXIT_FAILURE, 2752d7937e2eSIntel "rte_eth_tx_queue_setup: err=%d, " 2753d7937e2eSIntel "port=%d\n", ret, portid); 2754d7937e2eSIntel 2755d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 2756d7937e2eSIntel qconf->tx_queue_id[portid] = queueid; 2757d7937e2eSIntel queueid++; 2758e2366e74STomasz Kulasek 2759e2366e74STomasz Kulasek qconf->tx_port_id[qconf->n_tx_port] = portid; 2760dd1c68faSTomasz Kulasek qconf->n_tx_port++; 2761d7937e2eSIntel } 2762d7937e2eSIntel printf("\n"); 2763d7937e2eSIntel } 2764d7937e2eSIntel 2765d7937e2eSIntel for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 2766d7937e2eSIntel if (rte_lcore_is_enabled(lcore_id) == 0) 2767d7937e2eSIntel continue; 2768d7937e2eSIntel 2769609e7984SReshma Pattan if (app_mode == APP_MODE_LEGACY) { 2770d7937e2eSIntel /* init timer structures for each enabled lcore */ 2771d7937e2eSIntel rte_timer_init(&power_timers[lcore_id]); 2772d7937e2eSIntel hz = rte_get_timer_hz(); 2773d7937e2eSIntel rte_timer_reset(&power_timers[lcore_id], 2774a137d012SLiang Ma hz/TIMER_NUMBER_PER_SECOND, 2775a137d012SLiang Ma SINGLE, lcore_id, 2776d7937e2eSIntel power_timer_cb, NULL); 2777a137d012SLiang Ma } 2778d7937e2eSIntel qconf = &lcore_conf[lcore_id]; 2779d7937e2eSIntel printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); 2780d7937e2eSIntel fflush(stdout); 278126fe454eSLiang Ma 2782d7937e2eSIntel /* init RX queues */ 2783d7937e2eSIntel for(queue = 0; queue < qconf->n_rx_queue; ++queue) { 278440df1d7aSShahaf Shuler struct rte_eth_rxconf rxq_conf; 278540df1d7aSShahaf Shuler 2786d7937e2eSIntel portid = qconf->rx_queue_list[queue].port_id; 2787d7937e2eSIntel queueid = qconf->rx_queue_list[queue].queue_id; 2788d7937e2eSIntel 2789d7937e2eSIntel if (numa_on) 2790d7937e2eSIntel socketid = \ 2791d7937e2eSIntel (uint8_t)rte_lcore_to_socket_id(lcore_id); 2792d7937e2eSIntel else 2793d7937e2eSIntel socketid = 0; 2794d7937e2eSIntel 2795d7937e2eSIntel printf("rxq=%d,%d,%d ", portid, queueid, socketid); 2796d7937e2eSIntel fflush(stdout); 2797d7937e2eSIntel 2798089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(portid, &dev_info); 2799089e5ed7SIvan Ilchenko if (ret != 0) 2800089e5ed7SIvan Ilchenko rte_exit(EXIT_FAILURE, 2801089e5ed7SIvan Ilchenko "Error during getting device (port %u) info: %s\n", 2802089e5ed7SIvan Ilchenko portid, strerror(-ret)); 2803089e5ed7SIvan Ilchenko 280440df1d7aSShahaf Shuler rxq_conf = dev_info.default_rxconf; 28055c5c1f99SMarcin Zapolski rxq_conf.offloads = port_conf.rxmode.offloads; 2806d7937e2eSIntel ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, 280740df1d7aSShahaf Shuler socketid, &rxq_conf, 280881f7ecd9SPablo de Lara pktmbuf_pool[socketid]); 2809d7937e2eSIntel if (ret < 0) 2810d7937e2eSIntel rte_exit(EXIT_FAILURE, 2811d7937e2eSIntel "rte_eth_rx_queue_setup: err=%d, " 2812d7937e2eSIntel "port=%d\n", ret, portid); 281382bea466SJianfeng Tan 281482bea466SJianfeng Tan if (parse_ptype) { 281582bea466SJianfeng Tan if (add_cb_parse_ptype(portid, queueid) < 0) 281682bea466SJianfeng Tan rte_exit(EXIT_FAILURE, 281782bea466SJianfeng Tan "Fail to add ptype cb\n"); 28186184a022SGregory Etelson } 281926fe454eSLiang Ma 2820a9ea6070SDavid Hunt if (app_mode == APP_MODE_PMD_MGMT && !baseline_enabled) { 282159f2853cSKevin Laatz /* Set power_pmd_mgmt configs passed by user */ 282259f2853cSKevin Laatz rte_power_pmd_mgmt_set_emptypoll_max(max_empty_polls); 282359f2853cSKevin Laatz ret = rte_power_pmd_mgmt_set_pause_duration(pause_duration); 282459f2853cSKevin Laatz if (ret < 0) 282559f2853cSKevin Laatz rte_exit(EXIT_FAILURE, 282659f2853cSKevin Laatz "Error setting pause_duration: err=%d, lcore=%d\n", 282759f2853cSKevin Laatz ret, lcore_id); 282859f2853cSKevin Laatz 282959f2853cSKevin Laatz ret = rte_power_pmd_mgmt_set_scaling_freq_min(lcore_id, 283059f2853cSKevin Laatz scale_freq_min); 283159f2853cSKevin Laatz if (ret < 0) 283259f2853cSKevin Laatz rte_exit(EXIT_FAILURE, 283359f2853cSKevin Laatz "Error setting scaling freq min: err=%d, lcore=%d\n", 283459f2853cSKevin Laatz ret, lcore_id); 283559f2853cSKevin Laatz 283659f2853cSKevin Laatz ret = rte_power_pmd_mgmt_set_scaling_freq_max(lcore_id, 283759f2853cSKevin Laatz scale_freq_max); 283859f2853cSKevin Laatz if (ret < 0) 283959f2853cSKevin Laatz rte_exit(EXIT_FAILURE, 284059f2853cSKevin Laatz "Error setting scaling freq max: err=%d, lcore %d\n", 284159f2853cSKevin Laatz ret, lcore_id); 284259f2853cSKevin Laatz 284326fe454eSLiang Ma ret = rte_power_ethdev_pmgmt_queue_enable( 284426fe454eSLiang Ma lcore_id, portid, queueid, 284526fe454eSLiang Ma pmgmt_type); 284626fe454eSLiang Ma if (ret < 0) 284726fe454eSLiang Ma rte_exit(EXIT_FAILURE, 284826fe454eSLiang Ma "rte_power_ethdev_pmgmt_queue_enable: err=%d, port=%d\n", 284926fe454eSLiang Ma ret, portid); 285026fe454eSLiang Ma } 2851d7937e2eSIntel } 2852d7937e2eSIntel } 28539a212dc0SConor Fogarty /* >8 End of power library initialization. */ 2854d7937e2eSIntel 2855d7937e2eSIntel printf("\n"); 2856d7937e2eSIntel 2857d7937e2eSIntel /* start ports */ 28588728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(portid) { 2859d7937e2eSIntel if ((enabled_port_mask & (1 << portid)) == 0) { 2860d7937e2eSIntel continue; 2861d7937e2eSIntel } 2862d7937e2eSIntel /* Start device */ 2863d7937e2eSIntel ret = rte_eth_dev_start(portid); 2864d7937e2eSIntel if (ret < 0) 2865d7937e2eSIntel rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, " 2866d7937e2eSIntel "port=%d\n", ret, portid); 2867d7937e2eSIntel /* 2868d7937e2eSIntel * If enabled, put device in promiscuous mode. 2869d7937e2eSIntel * This allows IO forwarding mode to forward packets 2870d7937e2eSIntel * to itself through 2 cross-connected ports of the 2871d7937e2eSIntel * target machine. 2872d7937e2eSIntel */ 2873f430bbceSIvan Ilchenko if (promiscuous_on) { 2874f430bbceSIvan Ilchenko ret = rte_eth_promiscuous_enable(portid); 2875f430bbceSIvan Ilchenko if (ret != 0) 2876f430bbceSIvan Ilchenko rte_exit(EXIT_FAILURE, 2877f430bbceSIvan Ilchenko "rte_eth_promiscuous_enable: err=%s, port=%u\n", 2878f430bbceSIvan Ilchenko rte_strerror(-ret), portid); 2879f430bbceSIvan Ilchenko } 2880aee3bc79SCunming Liang /* initialize spinlock for each port */ 2881aee3bc79SCunming Liang rte_spinlock_init(&(locks[portid])); 28826184a022SGregory Etelson 28836184a022SGregory Etelson if (!parse_ptype) 28846184a022SGregory Etelson if (!check_ptype(portid)) 28856184a022SGregory Etelson rte_exit(EXIT_FAILURE, 28866184a022SGregory Etelson "PMD can not provide needed ptypes\n"); 2887d7937e2eSIntel } 2888d7937e2eSIntel 28898728ccf3SThomas Monjalon check_all_ports_link_status(enabled_port_mask); 2890d7937e2eSIntel 2891d7937e2eSIntel /* launch per-lcore init on every lcore */ 2892609e7984SReshma Pattan if (app_mode == APP_MODE_LEGACY) { 2893cb056611SStephen Hemminger rte_eal_mp_remote_launch(main_legacy_loop, NULL, CALL_MAIN); 28945b41ab35SAnatoly Burakov } else if (app_mode == APP_MODE_TELEMETRY) { 2895292472baSThomas Monjalon unsigned int i; 2896292472baSThomas Monjalon 2897609e7984SReshma Pattan /* Init metrics library */ 2898609e7984SReshma Pattan rte_metrics_init(rte_socket_id()); 2899609e7984SReshma Pattan /** Register stats with metrics library */ 2900a35919a1SCiara Power for (i = 0; i < NUM_TELSTATS; i++) 2901609e7984SReshma Pattan ptr_strings[i] = telstats_strings[i].name; 2902609e7984SReshma Pattan 2903a35919a1SCiara Power ret = rte_metrics_reg_names(ptr_strings, NUM_TELSTATS); 2904609e7984SReshma Pattan if (ret >= 0) 2905609e7984SReshma Pattan telstats_index = ret; 2906609e7984SReshma Pattan else 2907609e7984SReshma Pattan rte_exit(EXIT_FAILURE, "failed to register metrics names"); 2908609e7984SReshma Pattan 2909cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 2910609e7984SReshma Pattan rte_spinlock_init(&stats[lcore_id].telemetry_lock); 2911609e7984SReshma Pattan } 2912609e7984SReshma Pattan rte_timer_init(&telemetry_timer); 2913a35919a1SCiara Power rte_telemetry_register_cmd("/l3fwd-power/stats", 2914a35919a1SCiara Power handle_app_stats, 2915a35919a1SCiara Power "Returns global power stats. Parameters: None"); 2916609e7984SReshma Pattan rte_eal_mp_remote_launch(main_telemetry_loop, NULL, 2917cb056611SStephen Hemminger SKIP_MAIN); 2918e0194febSAnatoly Burakov } else if (app_mode == APP_MODE_INTERRUPT) { 2919cb056611SStephen Hemminger rte_eal_mp_remote_launch(main_intr_loop, NULL, CALL_MAIN); 292026fe454eSLiang Ma } else if (app_mode == APP_MODE_PMD_MGMT) { 292126fe454eSLiang Ma /* reuse telemetry loop for PMD power management mode */ 292226fe454eSLiang Ma rte_eal_mp_remote_launch(main_telemetry_loop, NULL, CALL_MAIN); 2923a137d012SLiang Ma } 2924a137d012SLiang Ma 29259c75ff42SDavid Hunt if (app_mode == APP_MODE_TELEMETRY) 2926a137d012SLiang Ma launch_timer(rte_lcore_id()); 2927a137d012SLiang Ma 2928cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 2929d7937e2eSIntel if (rte_eal_wait_lcore(lcore_id) < 0) 2930d7937e2eSIntel return -1; 2931d7937e2eSIntel } 2932d7937e2eSIntel 293326fe454eSLiang Ma if (app_mode == APP_MODE_PMD_MGMT) { 293426fe454eSLiang Ma for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 293526fe454eSLiang Ma if (rte_lcore_is_enabled(lcore_id) == 0) 293626fe454eSLiang Ma continue; 293726fe454eSLiang Ma qconf = &lcore_conf[lcore_id]; 293826fe454eSLiang Ma for (queue = 0; queue < qconf->n_rx_queue; ++queue) { 293926fe454eSLiang Ma portid = qconf->rx_queue_list[queue].port_id; 294026fe454eSLiang Ma queueid = qconf->rx_queue_list[queue].queue_id; 294126fe454eSLiang Ma 294226fe454eSLiang Ma rte_power_ethdev_pmgmt_queue_disable(lcore_id, 294326fe454eSLiang Ma portid, queueid); 294426fe454eSLiang Ma } 294526fe454eSLiang Ma } 294626fe454eSLiang Ma } 294726fe454eSLiang Ma 2948613ce669SAnatoly Burakov RTE_ETH_FOREACH_DEV(portid) 2949613ce669SAnatoly Burakov { 2950613ce669SAnatoly Burakov if ((enabled_port_mask & (1 << portid)) == 0) 2951613ce669SAnatoly Burakov continue; 2952613ce669SAnatoly Burakov 2953b55efbabSIvan Ilchenko ret = rte_eth_dev_stop(portid); 2954b55efbabSIvan Ilchenko if (ret != 0) 2955b55efbabSIvan Ilchenko RTE_LOG(ERR, L3FWD_POWER, "rte_eth_dev_stop: err=%d, port=%u\n", 2956b55efbabSIvan Ilchenko ret, portid); 2957b55efbabSIvan Ilchenko 2958613ce669SAnatoly Burakov rte_eth_dev_close(portid); 2959613ce669SAnatoly Burakov } 2960613ce669SAnatoly Burakov 29619c75ff42SDavid Hunt if ((app_mode == APP_MODE_LEGACY) && deinit_power_library()) 2962613ce669SAnatoly Burakov rte_exit(EXIT_FAILURE, "deinit_power_library failed\n"); 2963613ce669SAnatoly Burakov 2964613ce669SAnatoly Burakov if (rte_eal_cleanup() < 0) 2965613ce669SAnatoly Burakov RTE_LOG(ERR, L3FWD_POWER, "EAL cleanup failed\n"); 2966613ce669SAnatoly Burakov 2967d7937e2eSIntel return 0; 2968d7937e2eSIntel } 2969