[dpdk-dev,RFC,06/10] virtio: use software vlan stripping
Commit Message
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
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)) {
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.
> -----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
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.
@@ -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");
@@ -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];
};
@@ -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)) {