summaryrefslogtreecommitdiffstats
path: root/src/main_dpdk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main_dpdk.cpp')
-rw-r--r--src/main_dpdk.cpp293
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
*