From e532c2a19bd6afeaccb0b3eafebed3c5e758b339 Mon Sep 17 00:00:00 2001 From: Ido Barnea Date: Sun, 8 Jan 2017 17:14:32 +0200 Subject: Support for ixgbevf and i40evf Signed-off-by: Ido Barnea --- linux_dpdk/ws_main.py | 2 +- src/debug.cpp | 8 +- src/dpdk/drivers/net/i40e/i40e_rxtx.c | 49 ++++++--- src/main_dpdk.cpp | 126 +++++++++-------------- src/stateless/rx/trex_stateless_rx_port_mngr.cpp | 3 + 5 files changed, 94 insertions(+), 94 deletions(-) diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index f3e25605..29588622 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -432,7 +432,7 @@ dpdk_src = SrcGroup(dir='src/dpdk/', 'drivers/net/i40e/base/i40e_hmc.c', 'drivers/net/i40e/base/i40e_lan_hmc.c', 'drivers/net/i40e/base/i40e_nvm.c', -# 'drivers/net/i40e/i40e_ethdev_vf.c', + 'drivers/net/i40e/i40e_ethdev_vf.c', 'drivers/net/i40e/i40e_pf.c', 'drivers/net/i40e/i40e_rxtx.c', 'drivers/net/i40e/i40e_rxtx_vec.c', diff --git a/src/debug.cpp b/src/debug.cpp index 3e35a862..4abd05a0 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -398,7 +398,13 @@ int CTrexDebug::verify_hw_rules(bool recv_all) { memset(pkt_per_q, 0, sizeof(pkt_per_q)); // We don't know which interfaces connected where, so sum all queue 1 and all queue 0 for (int port = 0; port < m_max_ports; port++) { - for(int queue_id = 0; queue_id <= 1; queue_id++) { + int max_q; + if (CGlobalInfo::m_options.preview.get_vm_one_queue_enable()) { + max_q = 0; + } else { + max_q = 1; + } + for(int queue_id = 0; queue_id <= max_q; queue_id++) { lp = &m_ports[port]; uint16_t cnt = lp->rx_burst(queue_id, rx_pkts, 32); pkt_per_q[queue_id] += cnt; diff --git a/src/dpdk/drivers/net/i40e/i40e_rxtx.c b/src/dpdk/drivers/net/i40e/i40e_rxtx.c index 8fdf30c6..19b431c3 100644 --- a/src/dpdk/drivers/net/i40e/i40e_rxtx.c +++ b/src/dpdk/drivers/net/i40e/i40e_rxtx.c @@ -2161,10 +2161,18 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t base, bsf, tc_mapping; int use_def_burst_func = 1; +#define TREX_PATCH_LOW_LATENCY +#ifdef TREX_PATCH_LOW_LATENCY + int is_vf = 0; +#endif + if (hw->mac.type == I40E_MAC_VF || hw->mac.type == I40E_MAC_X722_VF) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); vsi = &vf->vsi; +#ifdef TREX_PATCH_LOW_LATENCY + is_vf = 1; +#endif } else { vsi = i40e_pf_get_vsi_by_qindex(pf, queue_idx); } @@ -2272,10 +2280,11 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev, ad->rx_bulk_alloc_allowed = false; } -#define TREX_PATCH_LOW_LATENCY #ifdef TREX_PATCH_LOW_LATENCY - rxq->dcb_tc =0; -#else + if (! is_vf) + rxq->dcb_tc =0; + else // The entire for below is in the else +#endif for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { if (!(vsi->enabled_tc & (1 << i))) @@ -2289,7 +2298,6 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev, if (queue_idx >= base && queue_idx < (base + BIT(bsf))) rxq->dcb_tc = i; } -#endif return 0; } @@ -2385,20 +2393,25 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_rs_thresh, tx_free_thresh; uint16_t i, base, bsf, tc_mapping; +#ifdef TREX_PATCH_LOW_LATENCY + u8 low_latency = 0; + int is_vf = 1; +#endif + if (hw->mac.type == I40E_MAC_VF || hw->mac.type == I40E_MAC_X722_VF) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); vsi = &vf->vsi; } else { vsi = i40e_pf_get_vsi_by_qindex(pf, queue_idx); - } - #ifdef TREX_PATCH_LOW_LATENCY - u8 low_latency = 0; - if (queue_idx == pf->dev_data->nb_tx_queues-1) { - low_latency = 1; - } + if (queue_idx == pf->dev_data->nb_tx_queues-1) { + low_latency = 1; + } + is_vf = 0; #endif + } + if (vsi == NULL) { PMD_DRV_LOG(ERR, "VSI is NULL, or queue index (%u) " @@ -2555,12 +2568,14 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev, i40e_set_tx_function_flag(dev, txq); #ifdef TREX_PATCH_LOW_LATENCY - if (low_latency) { - txq->dcb_tc=1; - }else{ - txq->dcb_tc=0; - } -#else + if (! is_vf) { + if (low_latency) { + txq->dcb_tc=1; + }else{ + txq->dcb_tc=0; + } + } else // The entire for below is in the else +#endif for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { if (!(vsi->enabled_tc & (1 << i))) continue; @@ -2573,7 +2588,7 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev, if (queue_idx >= base && queue_idx < (base + BIT(bsf))) txq->dcb_tc = i; } -#endif + return 0; } diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 5c78013b..3149bdb3 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -288,6 +288,27 @@ public: virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return 0;} }; +class CTRexExtendedDriverVf : public CTRexExtendedDriverBase1GVm { + +public: + CTRexExtendedDriverVf(){ + /* we are working in mode in which we have we have 1 queue for rx and one queue for tx*/ + CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true); + } + virtual void get_extended_stats(CPhyEthIF * _if, CPhyEthIFStats *stats) { + uint64_t prev_ipackets = stats->ipackets; + uint64_t prev_opackets = stats->opackets; + + CTRexExtendedDriverBase1GVm::get_extended_stats(_if, stats); + // Since this driver report byte counts without Ethernet FCS (4 bytes), we need to fix the reported numbers + stats->ibytes += (stats->ipackets - prev_ipackets) * 4; + stats->obytes += (stats->opackets - prev_opackets) * 4; + } + static CTRexExtendedDriverBase * create(){ + return ( new CTRexExtendedDriverVf() ); + } +}; + class CTRexExtendedDriverBaseE1000 : public CTRexExtendedDriverBase1GVm { CTRexExtendedDriverBaseE1000() { // E1000 driver is only relevant in VM in our case @@ -571,14 +592,12 @@ private: register_driver(std::string("rte_enic_pmd"),CTRexExtendedDriverBaseVIC::create); register_driver(std::string("net_mlx5"),CTRexExtendedDriverBaseMlnx5G::create); - /* virtual devices */ register_driver(std::string("rte_em_pmd"),CTRexExtendedDriverBaseE1000::create); register_driver(std::string("rte_vmxnet3_pmd"),CTRexExtendedDriverBase1GVm::create); register_driver(std::string("rte_virtio_pmd"),CTRexExtendedDriverBase1GVm::create); - - - + register_driver(std::string("rte_ixgbevf_pmd"),CTRexExtendedDriverVf::create); + register_driver(std::string("rte_i40evf_pmd"),CTRexExtendedDriverVf::create); m_driver_was_set=false; m_drv=0; @@ -1801,7 +1820,15 @@ int DpdkTRexPortAttr::add_mac(char * mac){ for (int i=0; i<6;i++) { mac_addr.addr_bytes[i] =mac[i]; } - return rte_eth_dev_mac_addr_add(m_port_id, &mac_addr,0); + + if ( ! get_vm_one_queue_enable() ) { + if ( rte_eth_dev_mac_addr_add(m_port_id, &mac_addr,0) != 0) { + printf("Failed setting MAC for port %d \n", m_port_id); + exit(-1); + } + } + + return 0; } int DpdkTRexPortAttr::set_promiscuous(bool enable){ @@ -2171,6 +2198,18 @@ int CCoreEthIF::send_burst(CCorePerPort * lp_port, uint16_t len, CVirtualIFPerSideStats * lp_stats){ +#ifdef DEBUG_SEND_BURST + if (CGlobalInfo::m_options.preview.getVMode() > 10) { + fprintf(stdout, "send_burst port:%d queue:%d len:%d\n", lp_port->m_port->get_rte_port_id() + , lp_port->m_tx_queue_id, len); + for (int i = 0; i < lp_port->m_len; i++) { + fprintf(stdout, "packet %d:\n", i); + rte_mbuf_t *m = lp_port->m_table[i]; + utl_DumpBuffer(stdout, rte_pktmbuf_mtod(m, uint8_t*), rte_pktmbuf_pkt_len(m), 0); + } + } +#endif + uint16_t ret = lp_port->m_port->tx_burst(lp_port->m_tx_queue_id,lp_port->m_table,len); #ifdef DELAY_IF_NEEDED while ( unlikely( ret TREX_MAX_PORTS ) { - rte_exit(EXIT_FAILURE, " Maximum ports supported are %d, use the configuration file to set the expected number of ports \n",TREX_MAX_PORTS); + rte_exit(EXIT_FAILURE, " Maximum number of ports supported is %d. You are trying to use %d. Please use --limit-ports, or change 'port_limit:' in the config file\n" + ,TREX_MAX_PORTS, CGlobalInfo::m_options.get_expected_ports()); } if ( CGlobalInfo::m_options.get_expected_ports() > m_max_ports ){ - rte_exit(EXIT_FAILURE, " There are %d ports you expected more %d,use the configuration file to set the expected number of ports \n", + rte_exit(EXIT_FAILURE, " There are %d ports available. You are trying to use %d. Please use --limit-ports, or change 'port_limit:' in the config file\n", m_max_ports, CGlobalInfo::m_options.get_expected_ports()); } @@ -5218,70 +5258,6 @@ int CPhyEthIF::get_flow_stats_payload(rx_per_flow_t *rx_stats, tx_per_flow_t *tx return 0; } -// If needed, send packets to rx core for processing. -// This is relevant only in VM case, where we receive packets to the working DP core (only 1 DP core in this case) -bool CCoreEthIF::process_rx_pkt(pkt_dir_t dir, rte_mbuf_t * m) { - CFlowStatParser parser; - uint32_t ip_id; - - if (parser.parse(rte_pktmbuf_mtod(m, uint8_t*), rte_pktmbuf_pkt_len(m)) != 0) { - return false; - } - bool send=false; - - // e1000 on ESXI hands us the packet with the ethernet FCS - if (parser.get_pkt_size() < rte_pktmbuf_pkt_len(m)) { - rte_pktmbuf_trim(m, rte_pktmbuf_pkt_len(m) - parser.get_pkt_size()); - } - - if ( get_is_stateless() ) { - // In stateless RX, we only care about flow stat packets - if ((parser.get_ip_id(ip_id) == 0) && ((ip_id & 0xff00) == IP_ID_RESERVE_BASE)) { - send = true; - } - } else { - CLatencyPktMode *c_l_pkt_mode = g_trex.m_mg.c_l_pkt_mode; - bool is_lateancy_pkt = c_l_pkt_mode->IsLatencyPkt((IPHeader *)parser.get_l4()) & - CCPortLatency::IsLatencyPkt(parser.get_l4() + c_l_pkt_mode->l4_header_len()); - - if (is_lateancy_pkt) { - send = true; - } else { - if ( get_is_rx_filter_enable() ) { - uint8_t max_ttl = 0xff - get_rx_check_hops(); - uint8_t pkt_ttl = parser.get_ttl(); - if ( (pkt_ttl==max_ttl) || (pkt_ttl==(max_ttl-1) ) ) { - send=true; - } - } - } - } - - - if (send) { - CGenNodeLatencyPktInfo * node=(CGenNodeLatencyPktInfo * )CGlobalInfo::create_node(); - if ( node ) { - node->m_msg_type = CGenNodeMsgBase::LATENCY_PKT; - node->m_dir = dir; - node->m_latency_offset = 0xdead; - node->m_pkt = m; - if ( m_ring_to_rx->Enqueue((CGenNode*)node)==0 ){ - }else{ - CGlobalInfo::free_node((CGenNode *)node); - send=false; - } - -#ifdef LATENCY_QUEUE_TRACE_ - printf("rx to cp --\n"); - rte_pktmbuf_dump(stdout,m, rte_pktmbuf_pkt_len(m)); -#endif - }else{ - send=false; - } - } - return (send); -} - TrexStateless * get_stateless_obj() { return g_trex.m_trex_stateless; } @@ -6677,8 +6653,8 @@ void CTRexExtendedDriverBase40G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFSta stats->ipackets += stats1.ipackets - prev_stats->ipackets; stats->ibytes += stats1.ibytes - prev_stats->ibytes; stats->opackets += stats1.opackets - prev_stats->opackets; - stats->obytes += stats1.obytes - prev_stats->obytes - + (stats1.opackets << 2) - (prev_stats->opackets << 2); + // Since this driver report obytes count without Ethernet FCS (4 bytes), we need to fix the reported numbers + stats->obytes += stats1.obytes - prev_stats->obytes + (stats1.opackets - prev_stats->opackets) * 4; stats->f_ipackets += 0; stats->f_ibytes += 0; stats->ierrors += stats1.imissed + stats1.ierrors + stats1.rx_nombuf diff --git a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp index e16b3d0c..caed2bee 100644 --- a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp +++ b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp @@ -461,6 +461,9 @@ public: m_icmp = NULL; m_vlan_tag = 0; + if (m_size_left < 14) + return; + /* ethernet */ m_ether = (EthernetHeader *)parse_bytes(14); -- cgit 1.2.3-korg