[dpdk-dev,RFC,06/10] virtio: use software vlan stripping

Message ID 20140826020848.386074683@networkplumber.org (mailing list archive)
State RFC, archived
Headers

Commit Message

Stephen Hemminger Aug. 26, 2014, 2:07 a.m. UTC
  Implement VLAN stripping in software. This allows application
to be device independent.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>


---
 lib/librte_pmd_virtio/virtio_ethdev.c |    2 ++
 lib/librte_pmd_virtio/virtio_pci.h    |    1 +
 lib/librte_pmd_virtio/virtio_rxtx.c   |   20 ++++++++++++++++++--
 3 files changed, 21 insertions(+), 2 deletions(-)
  

Comments

Ouyang Changchun Aug. 26, 2014, 8:37 a.m. UTC | #1
Hi Stephen,

Would you please describe the use scenario for the front end rx vlan strip and tx vlan insertion?
In our current implementation, backend will strip vlan tag for RX, and insert vlan tag for TX.
  
Thanks
Changchun

> -----Original Message-----

> From: Stephen Hemminger [mailto:stephen@networkplumber.org]

> Sent: Tuesday, August 26, 2014 10:08 AM

> To: Ouyang, Changchun

> Cc: dev@dpdk.org; Stephen Hemminger

> Subject: [RFC 06/10] virtio: use software vlan stripping

> 

> Implement VLAN stripping in software. This allows application to be device

> independent.

> 

> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

> 

> 

> ---

>  lib/librte_pmd_virtio/virtio_ethdev.c |    2 ++

>  lib/librte_pmd_virtio/virtio_pci.h    |    1 +

>  lib/librte_pmd_virtio/virtio_rxtx.c   |   20 ++++++++++++++++++--

>  3 files changed, 21 insertions(+), 2 deletions(-)

> 

> --- a/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25

> 19:00:07.574537243 -0700

> +++ b/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25

> 19:00:07.574537243 -0700

> @@ -976,6 +976,8 @@ virtio_dev_configure(struct rte_eth_dev

>  		return (-EINVAL);

>  	}

> 

> +	hw->vlan_strip = rxmode->hw_vlan_strip;

> +

>  	ret = vtpci_irq_config(hw, 0);

>  	if (ret != 0)

>  		PMD_DRV_LOG(ERR, "failed to set config vector");

> --- a/lib/librte_pmd_virtio/virtio_pci.h	2014-08-25 19:00:07.574537243 -0700

> +++ b/lib/librte_pmd_virtio/virtio_pci.h	2014-08-25

> 19:00:07.574537243 -0700

> @@ -168,6 +168,7 @@ struct virtio_hw {

>  	uint32_t    max_tx_queues;

>  	uint32_t    max_rx_queues;

>  	uint16_t    vtnet_hdr_size;

> +	uint8_t	    vlan_strip;

>  	uint8_t	    use_msix;

>  	uint8_t     mac_addr[ETHER_ADDR_LEN];

>  };

> --- a/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25 19:00:07.574537243 -0700

> +++ b/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25

> 19:00:07.574537243 -0700

> @@ -49,6 +49,7 @@

>  #include <rte_prefetch.h>

>  #include <rte_string_fns.h>

>  #include <rte_errno.h>

> +#include <rte_byteorder.h>

> 

>  #include "virtio_logs.h"

>  #include "virtio_ethdev.h"

> @@ -406,8 +407,8 @@ virtio_dev_tx_queue_setup(struct rte_eth

> 

>  	PMD_INIT_FUNC_TRACE();

> 

> -	if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)

> -	    != ETH_TXQ_FLAGS_NOOFFLOADS) {

> +	if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOXSUMS)

> +	    != ETH_TXQ_FLAGS_NOXSUMS) {

>  		PMD_INIT_LOG(ERR, "TX checksum offload not

> supported\n");

>  		return -EINVAL;

>  	}

> @@ -444,6 +445,7 @@ uint16_t

>  virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t

> nb_pkts)  {

>  	struct virtqueue *rxvq = rx_queue;

> +	struct virtio_hw *hw = rxvq->hw;

>  	struct rte_mbuf *rxm, *new_mbuf;

>  	uint16_t nb_used, num, nb_rx = 0;

>  	uint32_t len[VIRTIO_MBUF_BURST_SZ];

> @@ -487,6 +489,9 @@ virtio_recv_pkts(void *rx_queue, struct

>  		rxm->pkt.pkt_len = (uint32_t)(len[i] - hdr_size);

>  		rxm->pkt.data_len = (uint16_t)(len[i] - hdr_size);

> 

> +		if (hw->vlan_strip)

> +			rte_vlan_strip(rxm);

> +

>  		VIRTIO_DUMP_PACKET(rxm, rxm->pkt.data_len);

> 

>  		rx_pkts[nb_rx++] = rxm;

> @@ -711,6 +716,17 @@ virtio_xmit_pkts(void *tx_queue, struct

> 

>  		if (tx_pkts[nb_tx]->pkt.nb_segs <= txvq->vq_free_cnt) {

>  			txm = tx_pkts[nb_tx];

> +

> +			/* Do VLAN tag insertion */

> +			if (txm->ol_flags & PKT_TX_VLAN_PKT) {

> +				error = rte_vlan_insert(txm);

> +				if (unlikely(error)) {

> +					rte_pktmbuf_free(txm);

> +					++nb_tx;

> +					continue;

> +				}

> +			}

> +

>  			/* Enqueue Packet buffers */

>  			error = virtqueue_enqueue_xmit(txvq, txm);

>  			if (unlikely(error)) {
  
Stephen Hemminger Aug. 26, 2014, 4:24 p.m. UTC | #2
On Tue, 26 Aug 2014 08:37:11 +0000
"Ouyang, Changchun" <changchun.ouyang@intel.com> wrote:

> Hi Stephen,
> 
> Would you please describe the use scenario for the front end rx vlan strip and tx vlan insertion?
> In our current implementation, backend will strip vlan tag for RX, and insert vlan tag for TX.
>   
> Thanks
> Changchun

First, we don't have to do software VLAN strip on our backend if we do this.
And this way we can always use VLAN insert on transmit. Otherwise you have to
introduce special case because there is no DPDK API to determine if device does or does not
do VLAN handling.
  
Ouyang Changchun Aug. 27, 2014, 5:42 a.m. UTC | #3
> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Wednesday, August 27, 2014 12:24 AM
> To: Ouyang, Changchun
> Cc: dev@dpdk.org
> Subject: Re: [RFC 06/10] virtio: use software vlan stripping
> 
> On Tue, 26 Aug 2014 08:37:11 +0000
> "Ouyang, Changchun" <changchun.ouyang@intel.com> wrote:
> 
> > Hi Stephen,
> >
> > Would you please describe the use scenario for the front end rx vlan strip
> and tx vlan insertion?
> > In our current implementation, backend will strip vlan tag for RX, and insert
> vlan tag for TX.
> >
> > Thanks
> > Changchun
> 
> First, we don't have to do software VLAN strip on our backend if we do this.
> And this way we can always use VLAN insert on transmit. Otherwise you
> have to introduce special case because there is no DPDK API to determine if
> device does or does not do VLAN handling.
> 

How the virtio frontend tell backend whether it has software VLAN strip feature or not?
It seems no feature bit to negotiate it.

Thanks
Changchun
  
Stephen Hemminger Aug. 27, 2014, 6:04 p.m. UTC | #4
On Wed, 27 Aug 2014 05:42:09 +0000
"Ouyang, Changchun" <changchun.ouyang@intel.com> wrote:

> 
> > -----Original Message-----
> > From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > Sent: Wednesday, August 27, 2014 12:24 AM
> > To: Ouyang, Changchun
> > Cc: dev@dpdk.org
> > Subject: Re: [RFC 06/10] virtio: use software vlan stripping
> > 
> > On Tue, 26 Aug 2014 08:37:11 +0000
> > "Ouyang, Changchun" <changchun.ouyang@intel.com> wrote:
> > 
> > > Hi Stephen,
> > >
> > > Would you please describe the use scenario for the front end rx vlan strip
> > and tx vlan insertion?
> > > In our current implementation, backend will strip vlan tag for RX, and insert
> > vlan tag for TX.
> > >
> > > Thanks
> > > Changchun
> > 
> > First, we don't have to do software VLAN strip on our backend if we do this.
> > And this way we can always use VLAN insert on transmit. Otherwise you
> > have to introduce special case because there is no DPDK API to determine if
> > device does or does not do VLAN handling.
> > 
> 
> How the virtio frontend tell backend whether it has software VLAN strip feature or not?
> It seems no feature bit to negotiate it.
> 
> Thanks
> Changchun
> 

All other drivers have VLAN stripping as option under rte_eth_rxmode / hw_vlan_strip.
There is negotiation in DPDK, it is strictly ask for feature and either get it or an error.
Therefore we went ahead and emulated the feature in software.
  

Patch

--- a/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25 19:00:07.574537243 -0700
+++ b/lib/librte_pmd_virtio/virtio_ethdev.c	2014-08-25 19:00:07.574537243 -0700
@@ -976,6 +976,8 @@  virtio_dev_configure(struct rte_eth_dev
 		return (-EINVAL);
 	}
 
+	hw->vlan_strip = rxmode->hw_vlan_strip;
+
 	ret = vtpci_irq_config(hw, 0);
 	if (ret != 0)
 		PMD_DRV_LOG(ERR, "failed to set config vector");
--- a/lib/librte_pmd_virtio/virtio_pci.h	2014-08-25 19:00:07.574537243 -0700
+++ b/lib/librte_pmd_virtio/virtio_pci.h	2014-08-25 19:00:07.574537243 -0700
@@ -168,6 +168,7 @@  struct virtio_hw {
 	uint32_t    max_tx_queues;
 	uint32_t    max_rx_queues;
 	uint16_t    vtnet_hdr_size;
+	uint8_t	    vlan_strip;
 	uint8_t	    use_msix;
 	uint8_t     mac_addr[ETHER_ADDR_LEN];
 };
--- a/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25 19:00:07.574537243 -0700
+++ b/lib/librte_pmd_virtio/virtio_rxtx.c	2014-08-25 19:00:07.574537243 -0700
@@ -49,6 +49,7 @@ 
 #include <rte_prefetch.h>
 #include <rte_string_fns.h>
 #include <rte_errno.h>
+#include <rte_byteorder.h>
 
 #include "virtio_logs.h"
 #include "virtio_ethdev.h"
@@ -406,8 +407,8 @@  virtio_dev_tx_queue_setup(struct rte_eth
 
 	PMD_INIT_FUNC_TRACE();
 
-	if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)
-	    != ETH_TXQ_FLAGS_NOOFFLOADS) {
+	if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOXSUMS)
+	    != ETH_TXQ_FLAGS_NOXSUMS) {
 		PMD_INIT_LOG(ERR, "TX checksum offload not supported\n");
 		return -EINVAL;
 	}
@@ -444,6 +445,7 @@  uint16_t
 virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 {
 	struct virtqueue *rxvq = rx_queue;
+	struct virtio_hw *hw = rxvq->hw;
 	struct rte_mbuf *rxm, *new_mbuf;
 	uint16_t nb_used, num, nb_rx = 0;
 	uint32_t len[VIRTIO_MBUF_BURST_SZ];
@@ -487,6 +489,9 @@  virtio_recv_pkts(void *rx_queue, struct
 		rxm->pkt.pkt_len = (uint32_t)(len[i] - hdr_size);
 		rxm->pkt.data_len = (uint16_t)(len[i] - hdr_size);
 
+		if (hw->vlan_strip)
+			rte_vlan_strip(rxm);
+
 		VIRTIO_DUMP_PACKET(rxm, rxm->pkt.data_len);
 
 		rx_pkts[nb_rx++] = rxm;
@@ -711,6 +716,17 @@  virtio_xmit_pkts(void *tx_queue, struct
 
 		if (tx_pkts[nb_tx]->pkt.nb_segs <= txvq->vq_free_cnt) {
 			txm = tx_pkts[nb_tx];
+
+			/* Do VLAN tag insertion */
+			if (txm->ol_flags & PKT_TX_VLAN_PKT) {
+				error = rte_vlan_insert(txm);
+				if (unlikely(error)) {
+					rte_pktmbuf_free(txm);
+					++nb_tx;
+					continue;
+				}
+			}
+
 			/* Enqueue Packet buffers */
 			error = virtqueue_enqueue_xmit(txvq, txm);
 			if (unlikely(error)) {