Support for ixgbevf and i40evf 36/5236/1
authorIdo Barnea <[email protected]>
Sun, 8 Jan 2017 15:14:32 +0000 (17:14 +0200)
committerIdo Barnea <[email protected]>
Mon, 9 Jan 2017 13:19:00 +0000 (15:19 +0200)
Signed-off-by: Ido Barnea <[email protected]>
linux_dpdk/ws_main.py
src/debug.cpp
src/dpdk/drivers/net/i40e/i40e_rxtx.c
src/main_dpdk.cpp
src/stateless/rx/trex_stateless_rx_port_mngr.cpp

index f3e2560..2958862 100755 (executable)
@@ -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',
index 3e35a86..4abd05a 100644 (file)
@@ -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;
index 8fdf30c..19b431c 100644 (file)
@@ -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;
 }
 
index 5c78013..3149bdb 100644 (file)
@@ -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<len ) ){
@@ -3928,21 +3967,22 @@ int  CGlobalTRex::ixgbe_prob_init(void){
 
     m_max_ports  = rte_eth_dev_count();
     if (m_max_ports == 0)
-        rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
+        rte_exit(EXIT_FAILURE, "Error: Could not find supported ethernet ports. You are probably trying to use unsupported NIC \n");
 
     printf(" Number of ports found: %d \n",m_max_ports);
 
     if ( m_max_ports %2 !=0 ) {
-        rte_exit(EXIT_FAILURE, " Number of ports %d should be even, mask the one port in the configuration file  \n, ",
+        rte_exit(EXIT_FAILURE, " Number of ports in config file is %d. It should be even. Please use --limit-ports, or change 'port_limit:' in the config file\n",
                  m_max_ports);
     }
 
     if ( CGlobalInfo::m_options.get_expected_ports() > 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
index e16b3d0..caed2be 100644 (file)
@@ -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);