diff options
Diffstat (limited to 'src/main_dpdk.cpp')
-rw-r--r-- | src/main_dpdk.cpp | 293 |
1 files changed, 247 insertions, 46 deletions
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 46fa7335..fbd55173 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -77,6 +77,7 @@ extern "C" { #include "stateful_rx_core.h" #include "debug.h" #include "pkt_gen.h" +#include "trex_port_attr.h" #include "internal_api/trex_platform_api.h" #include "main_dpdk.h" #include "trex_watchdog.h" @@ -120,6 +121,15 @@ static inline int get_is_rx_thread_enabled() { struct port_cfg_t; +#define MAX_DPDK_ARGS 40 +static CPlatformYamlInfo global_platform_cfg_info; +static int global_dpdk_args_num ; +static char * global_dpdk_args[MAX_DPDK_ARGS]; +static char global_cores_str[100]; +static char global_prefix_str[100]; +static char global_loglevel_str[20]; + + class CTRexExtendedDriverBase { public: @@ -147,7 +157,6 @@ public: virtual void clear_extended_stats(CPhyEthIF * _if)=0; virtual int wait_for_stable_link(); virtual void wait_after_link_up(); - virtual bool flow_control_disable_supported(){return true;} virtual bool hw_rx_stat_supported(){return false;} virtual int get_rx_stats(CPhyEthIF * _if, uint32_t *pkts, uint32_t *prev_pkts, uint32_t *bytes, uint32_t *prev_bytes , int min, int max) {return -1;} @@ -158,6 +167,7 @@ public: virtual int verify_fw_ver(int i) {return 0;} virtual CFlowStatParser *get_flow_stat_parser(); virtual int set_rcv_all(CPhyEthIF * _if, bool set_on)=0; + virtual TRexPortAttr * create_port_attr(uint8_t port_id) = 0; }; @@ -167,6 +177,10 @@ public: CTRexExtendedDriverBase1G(){ } + TRexPortAttr * create_port_attr(uint8_t port_id) { + return new DpdkTRexPortAttr(port_id, false, true); + } + static CTRexExtendedDriverBase * create(){ return ( new CTRexExtendedDriverBase1G() ); } @@ -212,6 +226,10 @@ public: CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); } + TRexPortAttr * create_port_attr(uint8_t port_id) { + return new DpdkTRexPortAttr(port_id, true, true); + } + virtual bool has_crc_added() { return false; } @@ -257,6 +275,10 @@ public: CTRexExtendedDriverBase10G(){ } + TRexPortAttr * create_port_attr(uint8_t port_id) { + return new DpdkTRexPortAttr(port_id, false, true); + } + static CTRexExtendedDriverBase * create(){ return ( new CTRexExtendedDriverBase10G() ); } @@ -298,6 +320,11 @@ public: m_if_per_card = 4; } + TRexPortAttr * create_port_attr(uint8_t port_id) { + // disabling flow control on 40G using DPDK API causes the interface to malfunction + return new DpdkTRexPortAttr(port_id, false, false); + } + static CTRexExtendedDriverBase * create(){ return ( new CTRexExtendedDriverBase40G() ); } @@ -325,8 +352,6 @@ public: return TrexPlatformApi::IF_STAT_IPV4_ID | TrexPlatformApi::IF_STAT_PAYLOAD; } virtual int wait_for_stable_link(); - // disabling flow control on 40G using DPDK API causes the interface to malfunction - virtual bool flow_control_disable_supported(){return false;} virtual bool hw_rx_stat_supported(){return true;} virtual int verify_fw_ver(int i); virtual CFlowStatParser *get_flow_stat_parser(); @@ -347,6 +372,10 @@ public: CTRexExtendedDriverBaseVIC(){ } + TRexPortAttr * create_port_attr(uint8_t port_id) { + return new DpdkTRexPortAttr(port_id, false, false); + } + static CTRexExtendedDriverBase * create(){ return ( new CTRexExtendedDriverBaseVIC() ); } @@ -357,8 +386,6 @@ public: virtual int verify_fw_ver(int i) {return 0;} - bool flow_control_disable_supported(){return false;} - virtual void update_configuration(port_cfg_t * cfg); }; @@ -413,12 +440,12 @@ private: register_driver(std::string("rte_ixgbe_pmd"),CTRexExtendedDriverBase10G::create); register_driver(std::string("rte_igb_pmd"),CTRexExtendedDriverBase1G::create); register_driver(std::string("rte_i40e_pmd"),CTRexExtendedDriverBase40G::create); + register_driver(std::string("rte_enic_pmd"),CTRexExtendedDriverBaseVIC::create); /* virtual devices */ register_driver(std::string("rte_em_pmd"),CTRexExtendedDriverBase1GVm::create); register_driver(std::string("rte_vmxnet3_pmd"),CTRexExtendedDriverBase1GVm::create); register_driver(std::string("rte_virtio_pmd"),CTRexExtendedDriverBase1GVm::create); - register_driver(std::string("rte_enic_pmd"),CTRexExtendedDriverBaseVIC::create); @@ -488,14 +515,6 @@ static inline int get_min_sample_rate(void){ return ( get_ex_drv()->get_min_sample_rate()); } -#define MAX_DPDK_ARGS 40 -static CPlatformYamlInfo global_platform_cfg_info; -static int global_dpdk_args_num ; -static char * global_dpdk_args[MAX_DPDK_ARGS]; -static char global_cores_str[100]; -static char global_prefix_str[100]; -static char global_loglevel_str[20]; - // cores =0==1,1*2,2,3,4,5,6 // An enum for all the option types enum { OPT_HELP, @@ -589,6 +608,7 @@ static CSimpleOpt::SOption parser_options[] = { OPT_NO_FLOW_CONTROL, "--no-flow-control-change", SO_NONE }, { OPT_VLAN, "--vlan", SO_NONE }, { OPT_CLIENT_CFG_FILE, "--client_cfg", SO_REQ_SEP }, + { OPT_CLIENT_CFG_FILE, "--client-cfg", SO_REQ_SEP }, { OPT_NO_KEYBOARD_INPUT ,"--no-key", SO_NONE }, { OPT_VIRT_ONE_TX_RX_QUEUE, "--vm-sim", SO_NONE }, { OPT_PREFIX, "--prefix", SO_REQ_SEP }, @@ -1443,9 +1463,107 @@ void CPhyEthIF::disable_flow_control(){ ret, m_port_id); } +/* +Get user frienly devices description from saved env. var +Changes certain attributes based on description +*/ +void DpdkTRexPortAttr::update_description(){ + struct rte_pci_addr pci_addr; + char pci[16]; + char * envvar; + std::string pci_envvar_name; + pci_addr = rte_eth_devices[m_port_id].pci_dev->addr; + snprintf(pci, sizeof(pci), "%04x:%02x:%02x.%d", pci_addr.domain, pci_addr.bus, pci_addr.devid, pci_addr.function); + intf_info_st.pci_addr = pci; + pci_envvar_name = "pci" + intf_info_st.pci_addr; + std::replace(pci_envvar_name.begin(), pci_envvar_name.end(), ':', '_'); + std::replace(pci_envvar_name.begin(), pci_envvar_name.end(), '.', '_'); + envvar = std::getenv(pci_envvar_name.c_str()); + if (envvar) { + intf_info_st.description = envvar; + } else { + intf_info_st.description = "Unknown"; + } + if (intf_info_st.description.find("82599ES") != std::string::npos) { // works for 82599EB etc. DPDK does not distinguish them + flag_is_link_change_supported = false; + } + if (intf_info_st.description.find("82545EM") != std::string::npos) { // in virtual E1000, DPDK claims fc is supported, but it's not + flag_is_fc_change_supported = false; + flag_is_led_change_supported = false; + } + if ( CGlobalInfo::m_options.preview.getVMode() > 0){ + printf("port %d desc: %s\n", m_port_id, intf_info_st.description.c_str()); + } +} + +int DpdkTRexPortAttr::set_led(bool on){ + if (on) { + return rte_eth_led_on(m_port_id); + }else{ + return rte_eth_led_off(m_port_id); + } +} + +int DpdkTRexPortAttr::get_flow_ctrl(int &mode) { + int ret = rte_eth_dev_flow_ctrl_get(m_port_id, &fc_conf_tmp); + if (ret) { + return ret; + } + mode = (int) fc_conf_tmp.mode; + return 0; +} + +int DpdkTRexPortAttr::set_flow_ctrl(int mode) { + if (!flag_is_fc_change_supported) { + return -ENOTSUP; + } + int ret = rte_eth_dev_flow_ctrl_get(m_port_id, &fc_conf_tmp); + if (ret) { + return ret; + } + fc_conf_tmp.mode = (enum rte_eth_fc_mode) mode; + return rte_eth_dev_flow_ctrl_set(m_port_id, &fc_conf_tmp); +} + +void DpdkTRexPortAttr::reset_xstats() { + rte_eth_xstats_reset(m_port_id); +} + +int DpdkTRexPortAttr::get_xstats_values(xstats_values_t &xstats_values) { + int size = rte_eth_xstats_get(m_port_id, NULL, 0); + if (size < 0) { + return size; + } + xstats_values_tmp.resize(size); + xstats_values.resize(size); + size = rte_eth_xstats_get(m_port_id, xstats_values_tmp.data(), size); + if (size < 0) { + return size; + } + for (int i=0; i<size; i++) { + xstats_values[xstats_values_tmp[i].id] = xstats_values_tmp[i].value; + } + return 0; +} +int DpdkTRexPortAttr::get_xstats_names(xstats_names_t &xstats_names){ + int size = rte_eth_xstats_get_names(m_port_id, NULL, 0); + if (size < 0) { + return size; + } + xstats_names_tmp.resize(size); + xstats_names.resize(size); + size = rte_eth_xstats_get_names(m_port_id, xstats_names_tmp.data(), size); + if (size < 0) { + return size; + } + for (int i=0; i<size; i++) { + xstats_names[i] = xstats_names_tmp[i].name; + } + return 0; +} -void CPhyEthIF::dump_link(FILE *fd){ +void DpdkTRexPortAttr::dump_link(FILE *fd){ fprintf(fd,"port : %d \n",(int)m_port_id); fprintf(fd,"------------\n"); @@ -1461,32 +1579,66 @@ void CPhyEthIF::dump_link(FILE *fd){ fprintf(fd,"promiscuous : %d \n",get_promiscuous()); } -void CPhyEthIF::update_link_status(){ +void DpdkTRexPortAttr::update_device_info(){ + rte_eth_dev_info_get(m_port_id, &dev_info); +} + +void DpdkTRexPortAttr::get_supported_speeds(supp_speeds_t &supp_speeds){ + uint32_t speed_capa = dev_info.speed_capa; + if (speed_capa & ETH_LINK_SPEED_1G) + supp_speeds.push_back(ETH_SPEED_NUM_1G); + if (speed_capa & ETH_LINK_SPEED_10G) + supp_speeds.push_back(ETH_SPEED_NUM_10G); + if (speed_capa & ETH_LINK_SPEED_40G) + supp_speeds.push_back(ETH_SPEED_NUM_40G); + if (speed_capa & ETH_LINK_SPEED_100G) + supp_speeds.push_back(ETH_SPEED_NUM_100G); +} + +void DpdkTRexPortAttr::update_link_status(){ rte_eth_link_get(m_port_id, &m_link); } -void CPhyEthIF::update_link_status_nowait(){ - rte_eth_link_get_nowait(m_port_id, &m_link); +bool DpdkTRexPortAttr::update_link_status_nowait(){ + rte_eth_link new_link; + bool changed = false; + rte_eth_link_get_nowait(m_port_id, &new_link); + if (new_link.link_speed != m_link.link_speed || + new_link.link_duplex != m_link.link_duplex || + new_link.link_autoneg != m_link.link_autoneg || + new_link.link_status != m_link.link_status) { + changed = true; + } + m_link = new_link; + return changed; } -void CPhyEthIF::add_mac(char * mac){ +int DpdkTRexPortAttr::add_mac(char * mac){ struct ether_addr mac_addr; - int i=0; - for (i=0; i<6;i++) { + for (int i=0; i<6;i++) { mac_addr.addr_bytes[i] =mac[i]; } - rte_eth_dev_mac_addr_add(m_port_id, &mac_addr,0); + return rte_eth_dev_mac_addr_add(m_port_id, &mac_addr,0); } -void CPhyEthIF::set_promiscuous(bool enable){ +int DpdkTRexPortAttr::set_promiscuous(bool enable){ if (enable) { rte_eth_promiscuous_enable(m_port_id); }else{ rte_eth_promiscuous_disable(m_port_id); } + return 0; +} + +int DpdkTRexPortAttr::set_link_up(bool up){ + if (up) { + return rte_eth_dev_set_link_up(m_port_id); + }else{ + return rte_eth_dev_set_link_down(m_port_id); + } } -bool CPhyEthIF::get_promiscuous(){ +bool DpdkTRexPortAttr::get_promiscuous(){ int ret=rte_eth_promiscuous_get(m_port_id); if (ret<0) { rte_exit(EXIT_FAILURE, "rte_eth_promiscuous_get: " @@ -1498,7 +1650,7 @@ bool CPhyEthIF::get_promiscuous(){ } -void CPhyEthIF::macaddr_get(struct ether_addr *mac_addr){ +void DpdkTRexPortAttr::macaddr_get(struct ether_addr *mac_addr){ rte_eth_macaddr_get(m_port_id , mac_addr); } @@ -1929,12 +2081,22 @@ int CCoreEthIF::send_pkt_lat(CCorePerPort *lp_port, rte_mbuf_t *m, CVirtualIFPer int ret = lp_port->m_port->tx_burst(lp_port->m_tx_queue_id_lat, &m, 1); +#ifdef DELAY_IF_NEEDED while ( unlikely( ret != 1 ) ){ rte_delay_us(1); lp_stats->m_tx_queue_full += 1; ret = lp_port->m_port->tx_burst(lp_port->m_tx_queue_id_lat, &m, 1); } +#else + if ( unlikely( ret != 1 ) ) { + lp_stats->m_tx_drop ++; + rte_pktmbuf_free(m); + return 0; + } + +#endif + return ret; } @@ -2826,6 +2988,7 @@ public: void publish_async_data(bool sync_now, bool baseline = false); void publish_async_barrier(uint32_t key); + void publish_async_port_attr_changed(uint8_t port_id); void dump_stats(FILE *fd, CGlobalStats::DumpFormat format); @@ -2867,6 +3030,7 @@ public: CLatencyManager m_mg; // statefull RX core CRxCoreStateless m_rx_sl; // stateless RX core CTrexGlobalIoMode m_io_modes; + CTRexExtendedDriverBase * m_drv; private: CLatencyHWPort m_latency_vports[TREX_MAX_PORTS]; /* read hardware driver */ @@ -2920,7 +3084,7 @@ void CGlobalTRex::pre_test() { do { ret = pretest.resolve_all(); count++; - } while ((ret != true) && (count < 3)); + } while ((ret != true) && (count < 10)); if ( CGlobalInfo::m_options.preview.getVMode() > 0) { pretest.dump(stdout); @@ -3000,11 +3164,11 @@ bool CGlobalTRex::is_all_links_are_up(bool dump){ int i; for (i=0; i<m_max_ports; i++) { CPhyEthIF * _if=&m_ports[i]; - _if->update_link_status(); + _if->get_port_attr()->update_link_status(); if ( dump ){ _if->dump_stats(stdout); } - if ( _if->is_link_up() == false){ + if ( _if->get_port_attr()->is_link_up() == false){ all_link_are=false; break; } @@ -3234,11 +3398,11 @@ int CGlobalTRex::ixgbe_start(void){ _if->configure_rx_duplicate_rules(); if ( ! get_vm_one_queue_enable() && ! CGlobalInfo::m_options.preview.get_is_disable_flow_control_setting() - && get_ex_drv()->flow_control_disable_supported()) { + && _if->get_port_attr()->is_fc_change_supported()) { _if->disable_flow_control(); } - _if->add_mac((char *)CGlobalInfo::m_options.get_src_mac_addr(i)); + _if->get_port_attr()->add_mac((char *)CGlobalInfo::m_options.get_src_mac_addr(i)); fflush(stdout); } @@ -3247,7 +3411,7 @@ int CGlobalTRex::ixgbe_start(void){ /* wait for ports to be stable */ get_ex_drv()->wait_for_stable_link(); - if ( !is_all_links_are_up(true) ){ + if ( !is_all_links_are_up(true) /*&& !get_is_stateless()*/ ){ // disable start with link down for now dump_links_status(stdout); rte_exit(EXIT_FAILURE, " " " one of the link is down \n"); @@ -3478,10 +3642,11 @@ int CGlobalTRex::ixgbe_prob_init(void){ } CTRexExtendedDriverDb::Ins()->set_driver_name(dev_info.driver_name); + m_drv = CTRexExtendedDriverDb::Ins()->get_drv(); // check if firmware version is new enough for (i = 0; i < m_max_ports; i++) { - if (CTRexExtendedDriverDb::Ins()->get_drv()->verify_fw_ver(i) < 0) { + if (m_drv->verify_fw_ver(i) < 0) { // error message printed by verify_fw_ver exit(1); } @@ -3552,9 +3717,8 @@ void CGlobalTRex::dump_config(FILE *fd){ void CGlobalTRex::dump_links_status(FILE *fd){ for (int i=0; i<m_max_ports; i++) { - CPhyEthIF * _if=&m_ports[i]; - _if->update_link_status_nowait(); - _if->dump_link(fd); + m_ports[i].get_port_attr()->update_link_status_nowait(); + m_ports[i].get_port_attr()->dump_link(fd); } } @@ -4001,11 +4165,37 @@ CGlobalTRex::publish_async_barrier(uint32_t key) { m_zmq_publisher.publish_barrier(key); } +void +CGlobalTRex:: publish_async_port_attr_changed(uint8_t port_id) { + Json::Value data; + data["port_id"] = port_id; + TRexPortAttr * _attr = m_ports[port_id].get_port_attr(); + + /* attributes */ + data["attr"]["speed"] = _attr->get_link_speed(); + data["attr"]["promiscuous"]["enabled"] = _attr->get_promiscuous(); + data["attr"]["link"]["up"] = _attr->is_link_up(); + int mode; + int ret = _attr->get_flow_ctrl(mode); + if (ret != 0) { + mode = -1; + } + data["attr"]["fc"]["mode"] = mode; + + m_zmq_publisher.publish_event(TrexPublisher::EVENT_PORT_ATTR_CHANGED, data); +} void CGlobalTRex::handle_slow_path() { m_stats_cnt+=1; + // update speed, link up/down etc. + for (int i=0; i<m_max_ports; i++) { + bool changed = m_ports[i].get_port_attr()->update_link_status_nowait(); + if (changed) { + publish_async_port_attr_changed(i); + } + } if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ) { if ( m_io_modes.handle_io_modes() ) { @@ -4487,6 +4677,7 @@ bool CPhyEthIF::Create(uint8_t portid) { m_last_rx_rate = 0.0; m_last_tx_rate = 0.0; m_last_tx_pps = 0.0; + m_port_attr = g_trex.m_drv->create_port_attr(portid); return true; } @@ -6203,6 +6394,15 @@ static void trex_termination_handler(int signum) { * TODO: REMOVE THIS TO A SEPERATE FILE * **********************************************************/ +int TrexDpdkPlatformApi::get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const { + return g_trex.m_ports[port_id].get_port_attr()->get_xstats_values(xstats_values); +} + +int TrexDpdkPlatformApi::get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names) const { + return g_trex.m_ports[port_id].get_port_attr()->get_xstats_names(xstats_names); +} + + void TrexDpdkPlatformApi::get_port_num(uint8_t &port_num) const { port_num = g_trex.m_max_ports; } @@ -6248,19 +6448,18 @@ TrexDpdkPlatformApi::port_id_to_cores(uint8_t port_id, std::vector<std::pair<uin cores_id_list = lpt->get_core_list(); } + void TrexDpdkPlatformApi::get_interface_info(uint8_t interface_id, intf_info_st &info) const { struct ether_addr rte_mac_addr; info.driver_name = CTRexExtendedDriverDb::Ins()->get_driver_name(); - g_trex.m_ports[interface_id].update_link_status_nowait(); - g_trex.m_ports[interface_id].get_link_speed(&info.speed); info.has_crc = CTRexExtendedDriverDb::Ins()->get_drv()->has_crc_added(); /* mac INFO */ /* hardware */ - g_trex.m_ports[interface_id].macaddr_get(&rte_mac_addr); + g_trex.m_ports[interface_id].get_port_attr()->macaddr_get(&rte_mac_addr); assert(ETHER_ADDR_LEN == 6); /* software */ @@ -6268,6 +6467,7 @@ TrexDpdkPlatformApi::get_interface_info(uint8_t interface_id, intf_info_st &info memcpy(sw_macaddr, CGlobalInfo::m_options.get_dst_src_mac_addr(interface_id), 12); for (int i = 0; i < 6; i++) { + info.mac_info.hw_macaddr[i] = rte_mac_addr.addr_bytes[i]; info.mac_info.dst_macaddr[i] = sw_macaddr[i]; info.mac_info.src_macaddr[i] = sw_macaddr[6 + i]; @@ -6289,6 +6489,11 @@ TrexDpdkPlatformApi::publish_async_data_now(uint32_t key, bool baseline) const { } void +TrexDpdkPlatformApi::publish_async_port_attr_changed(uint8_t port_id) const { + g_trex.publish_async_port_attr_changed(port_id); +} + +void TrexDpdkPlatformApi::get_interface_stat_info(uint8_t interface_id, uint16_t &num_counters, uint16_t &capabilities) const { num_counters = CTRexExtendedDriverDb::Ins()->get_drv()->get_stat_counters_num(); capabilities = CTRexExtendedDriverDb::Ins()->get_drv()->get_rx_stat_capabilities(); @@ -6329,14 +6534,6 @@ int TrexDpdkPlatformApi::del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_DELETE, l3_type, l4_proto, ipv6_next_h, id); } -void TrexDpdkPlatformApi::set_promiscuous(uint8_t port_id, bool enabled) const { - g_trex.m_ports[port_id].set_promiscuous(enabled); -} - -bool TrexDpdkPlatformApi::get_promiscuous(uint8_t port_id) const { - return g_trex.m_ports[port_id].get_promiscuous(); -} - void TrexDpdkPlatformApi::flush_dp_messages() const { g_trex.check_for_dp_messages(); } @@ -6376,6 +6573,10 @@ CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const { return CTRexExtendedDriverDb::Ins()->get_drv()->get_flow_stat_parser(); } +TRexPortAttr *TrexDpdkPlatformApi::getPortAttrObj(uint8_t port_id) const { + return g_trex.m_ports[port_id].get_port_attr(); +} + /** * marks the control plane for a total server shutdown * |