virtio patches
cover virtio patches
These are untested patches to merge functionality from Brocade/vyatta DPDK virtio driver back into the Intel DPDK 1.7 driver. Use them and merge them if you want. But test first, these are compile tested only.
RFC 1/10 virtio: rearrange resource initialization
For clarity make the setup of PCI resources for Linux into a function rather than block of code #ifdef'd in middle of dev_init.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 76 +++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +43 -33
@@ -706,6 +706,41 @@ virtio_has_msix(const struct rte_pci_add return (d != NULL); } + +/* Extract I/O port numbers from sysfs */ +static int virtio_resource_init (struct rte_pci_device *pci_dev) +{ +char dirname[PATH_MAX ]; +char filename[PATH_MAX ]; +unsigned long start, size; + +if (get_uio_dev (&pci_dev->addr, dirname,sizeof (dirname)) <0 ) +return -1 ; + +/* get portio size */ +snprintf (filename,sizeof (filename), +"%s/portio/port0/size" , dirname); +if (parse_sysfs_value (filename, &size) <0 ) { +PMD_INIT_LOG (ERR ,"%s(): cannot parse size" , + __func__); +return -1 ; + } + +/* get portio start */ +snprintf (filename,sizeof (filename), +"%s/portio/port0/start" , dirname); +if (parse_sysfs_value (filename, &start) <0 ) { +PMD_INIT_LOG (ERR ,"%s(): cannot parse portio start" , + __func__); +return -1 ; + } + pci_dev->mem_resource[0 ].addr = (void *)(uintptr_t )start; + pci_dev->mem_resource[0 ].len = (uint64_t )size; +PMD_INIT_LOG (DEBUG , +"PCI Port IO found start=0x%lx with size=0x%lx" , + start, size); +return 0 ; +}#else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused)
@@ -713,6 +748,12 @@ virtio_has_msix(const struct rte_pci_add/* nic_uio does not enable interrupts, return 0 (false). */ return 0 ; } + +static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) +{ +/* no setup required */ +return 0 ; +}#endif /*
@@ -749,40 +790,9 @@ eth_virtio_dev_init(__rte_unused structreturn 0 ; pci_dev = eth_dev->pci_dev; +if (virtio_resource_init (pci_dev) <0 ) +return -1 ; -#ifdef RTE_EXEC_ENV_LINUXAPP - { -char dirname[PATH_MAX ]; -char filename[PATH_MAX ]; -unsigned long start, size; - -if (get_uio_dev (&pci_dev->addr, dirname,sizeof (dirname)) <0 ) -return -1 ; - -/* get portio size */ -snprintf (filename,sizeof (filename), -"%s/portio/port0/size" , dirname); -if (parse_sysfs_value (filename, &size) <0 ) { -PMD_INIT_LOG (ERR ,"%s(): cannot parse size" , - __func__); -return -1 ; - } - -/* get portio start */ -snprintf (filename,sizeof (filename), -"%s/portio/port0/start" , dirname); -if (parse_sysfs_value (filename, &start) <0 ) { -PMD_INIT_LOG (ERR ,"%s(): cannot parse portio start" , - __func__); -return -1 ; - } - pci_dev->mem_resource[0 ].addr = (void *)(uintptr_t )start; - pci_dev->mem_resource[0 ].len = (uint64_t )size; -PMD_INIT_LOG (DEBUG , -"PCI Port IO found start=0x%lx with size=0x%lx" , - start, size); - } -#endif hw->use_msix =virtio_has_msix (&pci_dev->addr); hw->io_base = (uint32_t )(uintptr_t )pci_dev->mem_resource[0 ].addr;
A message that is not in the archive (sent off-list or not yet received): 20140826020837.898427212-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org
Ouyang, Changchun
Acked-by Changchun OuyangRe: [RFC 01/10] virtio: rearrange resource initialization
Quoted 119 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Tuesday, August 26, 2014 10:08 AM
To: Ouyang, Changchun
Cc: [email protected]
Subject: [RFC 01/10] virtio: rearrange resource initializationFor clarity make the setup of PCI resources for Linux into a function rather than block of code #ifdef'd in middle of
dev_init.--- lib/librte_pmd_virtio/virtio_ethdev.c | 76 +++++++++++++++++++---------- ----- 1 file changed, 43 insertions(+), 33 deletions(-)---
a/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:03.622515574 -0700
+++b/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:03.622515574 -0700lib/librte_pmd_virtio/virtio_ethdev.c +35
-0@@ -706,6 +706,41 @@ virtio_has_msix(const struct rte_pci_add return (d != NULL); } + +/* Extract I/O port numbers from sysfs */ static int +virtio_resource_init (struct rte_pci_device *pci_dev) { +char dirname[PATH_MAX ]; +char filename[PATH_MAX ]; +unsigned long start, size; + +if (get_uio_dev (&pci_dev->addr, dirname,sizeof (dirname)) <0 ) +return -1 ; + +/* get portio size */ +snprintf (filename,sizeof (filename), +"%s/portio/port0/size" , dirname); +if (parse_sysfs_value (filename, &size) <0 ) { +PMD_INIT_LOG (ERR ,"%s(): cannot parse size" , + __func__); +return -1 ; + } + +/* get portio start */ +snprintf (filename,sizeof (filename), +"%s/portio/port0/start" , dirname); +if (parse_sysfs_value (filename, &start) <0 ) { +PMD_INIT_LOG (ERR ,"%s(): cannot parse portio start" , + __func__); +return -1 ; + } + pci_dev->mem_resource[0 ].addr = (void *)(uintptr_t )start; + pci_dev->mem_resource[0 ].len = (uint64_t )size; +PMD_INIT_LOG (DEBUG , +"PCI Port IO found start=0x%lx with size=0x%lx" , + start, size); +return 0 ; +}#else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -713,6 +748,12 @@ virtio_has_msix(const struct rte_pci_addlib/librte_pmd_virtio/virtio_ethdev.c +8
-33/* nic_uio does not enable interrupts, return 0 (false). */ return 0 ; } + +static int virtio_resource_init(struct rte_pci_device *pci_dev +__rte_unused) { +/* no setup required */ +return 0 ; +}#endif /* @@ -749,40 +790,9 @@ eth_virtio_dev_init(__rte_unused structreturn 0 ; pci_dev = eth_dev->pci_dev; +if (virtio_resource_init (pci_dev) <0 ) +return -1 ; -#ifdef RTE_EXEC_ENV_LINUXAPP - { -char dirname[PATH_MAX ]; -char filename[PATH_MAX ]; -unsigned long start, size; - -if (get_uio_dev (&pci_dev->addr, dirname,sizeof (dirname)) < 0) -return -1 ; - -/* get portio size */ -snprintf (filename,sizeof (filename), -"%s/portio/port0/size" , dirname); -if (parse_sysfs_value (filename, &size) <0 ) { -PMD_INIT_LOG (ERR ,"%s(): cannot parse size" , - __func__); -return -1 ; - } - -/* get portio start */ -snprintf (filename,sizeof (filename), -"%s/portio/port0/start" , dirname); -if (parse_sysfs_value (filename, &start) <0 ) { -PMD_INIT_LOG (ERR ,"%s(): cannot parse portio start", - __func__); -return -1 ; - } - pci_dev->mem_resource[0 ].addr = (void *)(uintptr_t )start; - pci_dev->mem_resource[0 ].len = (uint64_t )size; -PMD_INIT_LOG (DEBUG , -"PCI Port IO found start=0x%lx with size=0x%lx" , - start, size); - } -#endif hw->use_msix =virtio_has_msix (&pci_dev->addr);
hw->io_base= (uint32_t)(uintptr_t)pci_dev-Quoted 1 line
mem_resource[0].addr;
RFC 2/10 virtio: use weak barriers
In reply to Stephen HemmingerThe DPDK driver only has to deal with the case of running on PCI and with SMP. In this case, the code can use the weaker barriers instead of using hard (fence) barriers. This will help performance. The rationale is explained in Linux kernel virtio_ring.h.
To make it clearer that this is a virtio thing and not some generic barrier, prefix the barrier calls with virtio_.
Add missing (and needed) barrier between updating ring data structure and notifying host.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 2 +- lib/librte_pmd_virtio/virtio_rxtx.c | 8 +++++--- lib/librte_pmd_virtio/virtqueue.h | 19 ++++++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-)
lib/librte_pmd_virtio/virtio_rxtx.c +5 -3
@@ -454,7 +454,7 @@ virtio_recv_pkts(void *rx_queue, struct nb_used =VIRTQUEUE_NUSED (rxvq); -rmb (); +virtio_rmb (); num = (uint16_t )(likely (nb_used <= nb_pkts) ? nb_used : nb_pkts); num = (uint16_t )(likely (num <=VIRTIO_MBUF_BURST_SZ ) ? num :VIRTIO_MBUF_BURST_SZ );
@@ -514,6 +514,7 @@ virtio_recv_pkts(void *rx_queue, struct }if (likely (nb_enqueued)) { +virtio_wmb ();if (unlikely (virtqueue_kick_prepare (rxvq))) {virtqueue_notify (rxvq);PMD_RX_LOG (DEBUG ,"Notified\n" );
@@ -545,7 +546,7 @@ virtio_recv_mergeable_pkts(void *rx_queu nb_used =VIRTQUEUE_NUSED (rxvq); -rmb (); +virtio_rmb ();if (nb_used ==0 )return 0 ;
@@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, structPMD_TX_LOG (DEBUG ,"%d packets to xmit" , nb_pkts); nb_used =VIRTQUEUE_NUSED (txvq); -rmb (); +virtio_rmb (); num = (uint16_t )(likely (nb_used <VIRTIO_MBUF_BURST_SZ ) ? nb_used :VIRTIO_MBUF_BURST_SZ );
@@ -729,6 +730,7 @@ virtio_xmit_pkts(void *tx_queue, struct } }vq_update_avail_idx (txvq); +virtio_wmb (); txvq->packets += nb_tx;
lib/librte_pmd_virtio/virtqueue.h +14 -5
@@ -46,9 +46,18 @@#include "virtio_ring.h" #include "virtio_logs.h" -#define mb () rte_mb() -#define wmb () rte_wmb() -#define rmb () rte_rmb() +/* +* Per virtio_config.h in Linux. +* For virtio_pci on SMP, we don't need to order with respect to MMIO +* accesses through relaxed memory I/O windows, so smp_mb() et al are +* sufficient. +* +* This driver is for virtio_pci on SMP and therefore can assume +* weaker (compiler barriers) +*/ +#define virtio_mb () rte_mb() +#define virtio_rmb () rte_compiler_barrier() +#define virtio_wmb () rte_compiler_barrier()#ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch (p) rte_prefetch1(p)
@@ -226,7 +235,7 @@ virtqueue_full(const struct virtqueue *vstatic inline void vq_update_avail_idx (struct virtqueue *vq) { -rte_compiler_barrier (); +virtio_rmb (); vq->vq_ring.avail->idx = vq->vq_avail_idx; }
@@ -256,7 +265,7 @@ static inline void virtqueue_notify(struct virtqueue *vq) {/* -* Ensure updated avail->idx is visible to host. mb() necessary? +* Ensure updated avail->idx is visible to host. * For virtio on IA, the notificaiton is through io port operation * which is a serialization instruction itself. */
lib/librte_pmd_virtio/virtio_ethdev.c +1 -1
@@ -171,7 +171,7 @@ virtio_send_command(struct virtqueue *vquint32_t idx, desc_idx, used_idx;struct vring_used_elem *uep; -rmb (); +virtio_rmb (); used_idx = (uint32_t )(vq->vq_used_cons_idx & (vq->vq_nentries -1 ));
RFC 3/10 virtio: allow starting with link down
In reply to Stephen HemmingerStarting driver with link down should be ok, it is with every other driver. So just allow it.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +2 -4
@@ -969,14 +969,12 @@ virtio_dev_start(struct rte_eth_dev *devvtpci_read_dev_config (hw, offsetof(struct virtio_net_config , status), &status,sizeof (status)); -if ((status &VIRTIO_NET_S_LINK_UP ) ==0 ) { +if ((status &VIRTIO_NET_S_LINK_UP ) ==0 )PMD_INIT_LOG (ERR ,"Port: %d Link is DOWN" , dev->data->port_id); -return -EIO ; - }else { +else PMD_INIT_LOG (DEBUG ,"Port: %d Link is UP" , dev->data->port_id); - } }vtpci_reinit_complete (hw);
RFC 4/10 virtio: add support for Link State interrupt
In reply to Stephen HemmingerVirtio has link state interrupt which can be used.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 78 ++++++++++++++++++++++++++-------- lib/librte_pmd_virtio/virtio_pci.c | 22 +++++++++ lib/librte_pmd_virtio/virtio_pci.h | 4 + 3 files changed, 86 insertions(+), 18 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +60 -18
@@ -757,6 +757,34 @@ static int virtio_resource_init(struct r#endif /* +* Process Virtio Config changed interrupt and call the callback +* if link state changed. +*/ +static void +virtio_interrupt_handler(__rte_unused struct rte_intr_handle *handle, +void *param) +{ +struct rte_eth_dev *dev = param; +struct virtio_hw *hw = +VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +uint8_t isr; + +/* Read interrupt status which clears interrupt */ + isr =vtpci_isr (hw); +PMD_DRV_LOG (INFO ,"interrupt status = %#x" , isr); + +if (rte_intr_enable (&dev->pci_dev->intr_handle) <0 ) +PMD_DRV_LOG (ERR ,"interrupt enable failed" ); + +if (isr &VIRTIO_PCI_ISR_CONFIG ) { +if (virtio_dev_link_update (dev,0 ) ==0 ) +_rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC ); + } + +} + +/* * This function is based on probe() function in virtio_pci.c * It returns 0 on success. */
@@ -886,6 +914,10 @@ eth_virtio_dev_init(__rte_unused structPMD_INIT_LOG (DEBUG ,"port %d vendorID=0x%x deviceID=0x%x" , eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); + +/* Setup interrupt callback */ +rte_intr_callback_register (&pci_dev->intr_handle, + virtio_interrupt_handler, eth_dev);return 0 ; }
@@ -893,7 +925,7 @@ static struct eth_driver rte_virtio_pmd { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_adapter),
@@ -933,6 +965,9 @@ static int virtio_dev_configure(struct rte_eth_dev *dev) {const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; +struct virtio_hw *hw = +VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +int ret;PMD_INIT_LOG (DEBUG ,"configure" );
@@ -941,7 +976,11 @@ virtio_dev_configure(struct rte_eth_devreturn (-EINVAL ); } -return 0 ; + ret =vtpci_irq_config (hw,0 ); +if (ret !=0 ) +PMD_DRV_LOG (ERR ,"failed to set config vector" ); + +return ret; }
@@ -949,7 +988,6 @@ static int virtio_dev_start(struct rte_eth_dev *dev) {uint16_t nb_queues, i; -uint16_t status;struct virtio_hw *hw =VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private);
@@ -964,18 +1002,22 @@ virtio_dev_start(struct rte_eth_dev *dev/* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start (dev); -/* Check VIRTIO_NET_F_STATUS for link status*/ -if (vtpci_with_feature (hw,VIRTIO_NET_F_STATUS )) { -vtpci_read_dev_config (hw, - offsetof(struct virtio_net_config , status), - &status,sizeof (status)); -if ((status &VIRTIO_NET_S_LINK_UP ) ==0 ) -PMD_INIT_LOG (ERR ,"Port: %d Link is DOWN" , - dev->data->port_id); -else -PMD_INIT_LOG (DEBUG ,"Port: %d Link is UP" , - dev->data->port_id); +/* check if lsc interrupt feature is enabled */ +if (dev->data->dev_conf.intr_conf.lsc) { +if (!vtpci_with_feature (hw,VIRTIO_NET_F_STATUS )) { +PMD_DRV_LOG (ERR ,"link status not supported by host" ); +return -ENOTSUP ; + } + +if (rte_intr_enable (&dev->pci_dev->intr_handle) <0 ) { +PMD_DRV_LOG (ERR ,"interrupt enable failed" ); +return -EIO ; + } } + +/* Initialize Link state */ +virtio_dev_link_update (dev,0 ); +vtpci_reinit_complete (hw);/*Notify the backend
@@ -1057,6 +1099,7 @@ virtio_dev_stop(struct rte_eth_dev *dev)VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private);/* reset the NIC */ +vtpci_irq_config (hw,0 );vtpci_reset (hw);virtio_dev_free_mbufs (dev); }
@@ -1073,6 +1116,7 @@ virtio_dev_link_update(struct rte_eth_de old = link; link.link_duplex =FULL_DUPLEX ; link.link_speed =SPEED_10G ; +if (vtpci_with_feature (hw,VIRTIO_NET_F_STATUS )) {PMD_INIT_LOG (DEBUG ,"Get link status from hw" ); vtpci_read_dev_config(hw,
@@ -1091,10 +1135,8 @@ virtio_dev_link_update(struct rte_eth_de link.link_status =1 ;/* Link up */ }virtio_dev_atomic_write_link_status (dev, &link); -if (old.link_status == link.link_status) -return -1 ; -/*changed*/ -return 0 ; + +return (old.link_status == link.link_status) ?-1 :0 ; } static void
lib/librte_pmd_virtio/virtio_pci.c +22 -0
@@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uVIRTIO_WRITE_REG_1 (hw,VIRTIO_PCI_STATUS , status); } + +uint8_t +vtpci_isr (struct virtio_hw *hw) +{ + +return VIRTIO_READ_REG_1 (hw,VIRTIO_PCI_ISR ); +} + + +/* Enable one vector (0) for Link State Intrerrupt */ +int +vtpci_irq_config (struct virtio_hw *hw,uint16_t vec) +{ +VIRTIO_WRITE_REG_2 (hw,VIRTIO_MSI_CONFIG_VECTOR , vec); + vec =VIRTIO_READ_REG_2 (hw,VIRTIO_MSI_CONFIG_VECTOR ); +if (vec ==VIRTIO_MSI_NO_VECTOR ) { +PMD_DRV_LOG (ERR ,"failed to set config vector" ); +return -EBUSY ; + } + +return 0 ; +}
lib/librte_pmd_virtio/virtio_pci.h +4 -0
@@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtivoid vtpci_read_dev_config (struct virtio_hw *,uint64_t ,void *,int ); +uint8_t vtpci_isr (struct virtio_hw *); + +int vtpci_irq_config (struct virtio_hw *,uint16_t ); +#endif /* _VIRTIO_PCI_H_ */
RFC 5/10 ether: add soft vlan encap/decap functions
In reply to Stephen HemmingerIt is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software.
--- lib/librte_ether/rte_ether.h | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
lib/librte_ether/rte_ether.h +69 -0
@@ -48,6 +48,8 @@ extern "C" {#include <rte_memcpy.h> #include <rte_random.h> +#include <rte_mbuf.h> +#include <rte_byteorder.h> #define ETHER_ADDR_LEN 6/**< Length of Ethernet address. */ #define ETHER_TYPE_LEN 2/**< Length of Ethernet type field. */
@@ -294,6 +296,73 @@ struct vlan_hdr {#define ETHER_TYPE_VLAN 0x8100/**< IEEE 802.1Q VLAN tagging. */ #define ETHER_TYPE_1588 0x88F7/**< IEEE 802.1AS 1588 Precise Time Protocol. */ +/** +* Extract VLAN tag information into mbuf +* +* Software version of VLAN stripping +* +* @param m +* The packet mbuf. +* @return +* - 0: Success +* - 1: not a vlan packet +*/ +static inline int rte_vlan_strip (struct rte_mbuf *m) +{ +struct ether_hdr *eh + = rte_pktmbuf_mtod(m, struct ether_hdr *); + +if (eh->ether_type !=ETHER_TYPE_VLAN ) +return -1 ; + +struct vlan_hdr *vh = (struct vlan_hdr *)(eh +1 ); + m->ol_flags |=PKT_RX_VLAN_PKT ; + m->pkt.vlan_macip.f.vlan_tci =rte_be_to_cpu_16 (vh->vlan_tci); + +/* Copy ether header over rather than moving whole packet */ +memmove (rte_pktmbuf_adj (m,sizeof (struct vlan_hdr )), + eh,2 *ETHER_ADDR_LEN ); + +return 0 ; +} + +/** +* Insert VLAN tag into mbuf. +* +* Software version of VLAN unstripping +* +* @param m +* The packet mbuf. +* @return +* - 0: On success +* -EPERM: mbuf is is shared overwriting would be unsafe +* -ENOSPC: not enough headroom in mbuf +*/ +static inline int rte_vlan_insert (struct rte_mbuf *m) +{ +struct ether_hdr *oh, *nh; +struct vlan_hdr *vh; + +#ifdef RTE_MBUF_SCATTER_GATHER +/* Can't insert header if mbuf is shared */ +if (rte_mbuf_refcnt_read (m) >1 ) +return -EINVAL ; +#endif + oh = rte_pktmbuf_mtod(m, struct ether_hdr *); + nh = (struct ether_hdr *) +rte_pktmbuf_prepend (m,sizeof (struct vlan_hdr )); +if (nh ==NULL ) +return -ENOSPC ; + +memmove (nh, oh,2 *ETHER_ADDR_LEN ); + nh->ether_type =ETHER_TYPE_VLAN ; + + vh = (struct vlan_hdr *) (nh +1 ); + vh->vlan_tci =rte_cpu_to_be_16 (m->pkt.vlan_macip.f.vlan_tci); + +return 0 ; +} + #ifdef __cplusplus }#endif
RFC 6/10 virtio: use software vlan stripping
In reply to Stephen HemmingerImplement VLAN stripping in software. This allows application to be device independent.
--- 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(-)
lib/librte_pmd_virtio/virtio_ethdev.c +2 -0
@@ -976,6 +976,8 @@ virtio_dev_configure(struct rte_eth_devreturn (-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" );
lib/librte_pmd_virtio/virtio_pci.h +1 -0
@@ -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 ]; };
lib/librte_pmd_virtio/virtio_rxtx.c +18 -2
@@ -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_ethPMD_INIT_FUNC_TRACE (); -if ((tx_conf->txq_flags Ð_TXQ_FLAGS_NOOFFLOADS ) - !=ETH_TXQ_FLAGS_NOOFFLOADS ) { +if ((tx_conf->txq_flags Ð_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, structif (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)) {
A message that is not in the archive (sent off-list or not yet received): 20140826020848.386074683-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org
Re: [RFC 06/10] virtio: use software vlan stripping
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
Quoted 102 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Tuesday, August 26, 2014 10:08 AM
To: Ouyang, Changchun
Cc: [email protected]; Stephen Hemminger
Subject: [RFC 06/10] virtio: use software vlan strippingImplement VLAN stripping in software. This allows application to be device independent.
Signed-off-by Stephen Hemminger <[email protected]>--- 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.c2014-08-25
19:00:07.574537243 -0700
+++b/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:07.574537243 -0700lib/librte_pmd_virtio/virtio_ethdev.c +2
-0@@ -976,6 +976,8 @@ virtio_dev_configure(struct rte_eth_devreturn (-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" );lib/librte_pmd_virtio/virtio_pci.h +0
-019:00:07.574537243 -0700
lib/librte_pmd_virtio/virtio_pci.h +1
-0@@ -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 ]; };lib/librte_pmd_virtio/virtio_rxtx.c +0
-019:00:07.574537243 -0700
lib/librte_pmd_virtio/virtio_rxtx.c +3
-2@@ -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_ethPMD_INIT_FUNC_TRACE (); -if ((tx_conf->txq_flags Ð_TXQ_FLAGS_NOOFFLOADS ) - !=ETH_TXQ_FLAGS_NOOFFLOADS ) { +if ((tx_conf->txq_flags Ð_TXQ_FLAGS_NOXSUMS ) + !=ETH_TXQ_FLAGS_NOXSUMS ) {PMD_INIT_LOG (ERR ,"TX checksum offload not supported\n");return -EINVAL ;lib/librte_pmd_virtio/virtio_rxtx.c +15
-0}@@ -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, structif (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)) {
A message that is not in the archive (sent off-list or not yet received): F52918179C57134FAEC9EA62FA2F96251183B285-E2R4CRU6q/[email protected]
Re: [RFC 06/10] virtio: use software vlan stripping
Quoted 7 lines · Changchun
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.
Re: [RFC 06/10] virtio: use software vlan stripping
Quoted 18 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Wednesday, August 27, 2014 12:24 AM
To: Ouyang, Changchun
Cc: [email protected]
Subject: Re: [RFC 06/10] virtio: use software vlan strippingQuoted 3 lines · Changchun
Hi Stephen,
Would you please describe the use scenario for the front end rx vlan strip
and tx vlan insertion?
Quoted 1 line
In our current implementation, backend will strip vlan tag for RX, and insert
vlan tag for TX.
Quoted 1 line
Quoted 8 lines
Quoted 2 lines
Thanks
ChangchunFirst, 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
A message that is not in the archive (sent off-list or not yet received): F52918179C57134FAEC9EA62FA2F96251183B79C-E2R4CRU6q/[email protected]
Re: [RFC 06/10] virtio: use software vlan stripping
Quoted 27 lines · Changchun
Quoted 18 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Wednesday, August 27, 2014 12:24 AM
To: Ouyang, Changchun
Cc: [email protected]
Subject: Re: [RFC 06/10] virtio: use software vlan strippingQuoted 3 lines · Changchun
Hi Stephen,
Would you please describe the use scenario for the front end rx vlan strip
and tx vlan insertion?
Quoted 1 line
In our current implementation, backend will strip vlan tag for RX, and insert
vlan tag for TX.
Quoted 1 line
Quoted 8 lines
Quoted 2 lines
Thanks
ChangchunFirst, 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.
Quoted 6 lines
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.
RFC 7/10 virtio: remove unnecessary adapter structure
In reply to Stephen HemmingerCleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure. Also allows removing unneeded macro, making code clearer.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++-------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 --------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 12 insertions(+), 31 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +11 -20
@@ -203,8 +203,7 @@ virtio_send_command(struct virtqueue *vqstatic int virtio_set_multiple_queues (struct rte_eth_dev *dev,uint16_t nb_queues) { -struct virtio_hw *hw - =VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;struct virtio_pmd_ctrl ctrl;int dlen[1 ];int ret;
@@ -238,8 +237,7 @@ int virtio_dev_queue_setup(struct rte_etconst struct rte_memzone *mz;uint16_t vq_size;int size; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;struct virtqueue *vq =NULL ;/* Write the virtqueue index to the Queue Select Field */
@@ -379,8 +377,7 @@ virtio_dev_cq_queue_setup(struct rte_ethstruct virtqueue *vq;uint16_t nb_desc =0 ;int ret; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;PMD_INIT_FUNC_TRACE (); ret = virtio_dev_queue_setup(dev, VTNET_CQ, VTNET_SQ_CQ_QUEUE_IDX,
@@ -765,8 +762,7 @@ virtio_interrupt_handler(__rte_unused st void *param) {struct rte_eth_dev *dev = param; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;uint8_t isr;/* Read interrupt status which clears interrupt */
@@ -792,12 +788,11 @@ static int eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, struct rte_eth_dev *eth_dev) { + struct virtio_hw *hw = eth_dev->data->dev_private;struct virtio_net_config *config;struct virtio_net_config local_config;uint32_t offset_conf =sizeof (config->mac);struct rte_pci_device *pci_dev; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (eth_dev->data->dev_private);if (RTE_PKTMBUF_HEADROOM <sizeof (struct virtio_net_hdr )) { PMD_INIT_LOG(ERR,
@@ -928,7 +923,7 @@ static struct eth_driver rte_virtio_pmd .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_virtio_dev_init, - .dev_private_size = sizeof(struct virtio_adapter), + .dev_private_size = sizeof(struct virtio_hw), };/*
@@ -965,8 +960,7 @@ static int virtio_dev_configure(struct rte_eth_dev *dev) {const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;int ret;PMD_INIT_LOG (DEBUG ,"configure" );
@@ -990,8 +984,7 @@ static int virtio_dev_start(struct rte_eth_dev *dev) {uint16_t nb_queues, i; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;/* Tell the host we've noticed this device. */ vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_ACK );
@@ -1097,8 +1090,7 @@ static void virtio_dev_free_mbufs(structstatic void virtio_dev_stop (struct rte_eth_dev *dev) { -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;/* reset the NIC */ vtpci_irq_config (hw,0 );
@@ -1111,8 +1103,7 @@ virtio_dev_link_update(struct rte_eth_de {struct rte_eth_link link, old;uint16_t status; -struct virtio_hw *hw = -VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;memset (&link,0 ,sizeof (link));virtio_dev_atomic_read_link_status (dev, &link); old = link;
@@ -1144,7 +1135,7 @@ virtio_dev_link_update(struct rte_eth_destatic void virtio_dev_info_get (struct rte_eth_dev *dev,struct rte_eth_dev_info *dev_info) { -struct virtio_hw *hw =VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private; dev_info->driver_name = dev->driver->pci_drv.name; dev_info->max_rx_queues = (uint16_t )hw->max_rx_queues;
lib/librte_pmd_virtio/virtio_ethdev.h +0 -9
@@ -110,15 +110,6 @@ uint16_t virtio_recv_mergeable_pkts(voiduint16_t virtio_xmit_pkts (void *tx_queue,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); -/* -* Structure to store private data for each driver instance (for each port). -*/ -struct virtio_adapter { -struct virtio_hw hw; -}; - -#define VIRTIO_DEV_PRIVATE_TO_HW (adapter)\ - (&((struct virtio_adapter *)adapter)->hw)/* * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us
lib/librte_pmd_virtio/virtio_rxtx.c +1 -2
@@ -326,8 +326,7 @@ virtio_dev_vring_start(struct virtqueuevoid virtio_dev_cq_start (struct rte_eth_dev *dev) { -struct virtio_hw *hw - =VIRTIO_DEV_PRIVATE_TO_HW (dev->data->dev_private); +struct virtio_hw *hw = dev->data->dev_private;virtio_dev_vring_start (hw->cvq,VTNET_CQ );VIRTQUEUE_DUMP ((struct virtqueue *)hw->cvq);
A message that is not in the archive (sent off-list or not yet received): 20140826020851.474452281-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org
Ouyang, Changchun
Acked-by Changchun OuyangRe: [RFC 07/10] virtio: remove unnecessary adapter structure
Quoted 17 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Tuesday, August 26, 2014 10:08 AM
To: Ouyang, Changchun
Cc: [email protected]
Subject: [RFC 07/10] virtio: remove unnecessary adapter structureCleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure.
Also allows removing unneeded macro, making code clearer.--- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++-------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 --------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 12 insertions(+), 31 deletions(-)
RFC 8/10 virtio: remove redundant vq_alignment
In reply to Stephen HemmingerSince vq_alignment is constant (always 4K), it does not need to be part of the vring struct.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 1 - lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- lib/librte_pmd_virtio/virtqueue.h | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +0 -1
@@ -290,7 +290,6 @@ int virtio_dev_queue_setup(struct rte_et vq->port_id = dev->data->port_id; vq->queue_id = queue_idx; vq->vq_queue_index = vtpci_queue_idx; - vq->vq_alignment =VIRTIO_PCI_VRING_ALIGN ; vq->vq_nentries = vq_size; vq->vq_free_cnt = vq_size;
lib/librte_pmd_virtio/virtio_rxtx.c +1 -1
@@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue* Reinitialise since virtio port might have been stopped and restarted */ memset (vq->vq_ring_virt_mem,0 , vq->vq_ring_size); -vring_init (vr, size, ring_mem, vq->vq_alignment); +vring_init (vr, size, ring_mem,VIRTIO_PCI_VRING_ALIGN ); vq->vq_used_cons_idx =0 ; vq->vq_desc_head_idx =0 ; vq->vq_avail_idx =0 ;
lib/librte_pmd_virtio/virtqueue.h +1 -2
@@ -139,8 +139,7 @@ struct virtqueue {uint8_t port_id;/**< Device port identifier. */ void *vq_ring_virt_mem;/**< linear address of vring*/ -int vq_alignment; -int vq_ring_size; +unsigned int vq_ring_size;phys_addr_t vq_ring_mem;/**< physical address of vring */ struct vring vq_ring;/**< vring keeping desc, used and avail */
A message that is not in the archive (sent off-list or not yet received): 20140826020853.851222673-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org
Re: [RFC 08/10] virtio: remove redundant vq_alignment
Acked by: Changchun Ouyang <[email protected]>
Quoted 55 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Tuesday, August 26, 2014 10:08 AM
To: Ouyang, Changchun
Cc: [email protected]; Stephen Hemminger
Subject: [RFC 08/10] virtio: remove redundantvq_alignmentSince
vq_alignmentis constant (always 4K), it does not need to be part of the vring struct.Signed-off-by Stephen Hemminger <[email protected]>--- lib/librte_pmd_virtio/virtio_ethdev.c | 1 - lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- lib/librte_pmd_virtio/virtqueue.h | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-)---
a/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:09.918550097 -0700
+++b/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:09.918550097 -0700lib/librte_pmd_virtio/virtio_ethdev.c +0
-1@@ -290,7 +290,6 @@ int virtio_dev_queue_setup(struct rte_et vq->port_id = dev->data->port_id; vq->queue_id = queue_idx; vq->vq_queue_index = vtpci_queue_idx; - vq->vq_alignment =VIRTIO_PCI_VRING_ALIGN ; vq->vq_nentries = vq_size; vq->vq_free_cnt = vq_size;lib/librte_pmd_virtio/virtio_rxtx.c +0
-019:00:09.918550097 -0700
lib/librte_pmd_virtio/virtio_rxtx.c +1
-1@@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue* Reinitialise since virtio port might have been stopped and restarted */ memset (vq->vq_ring_virt_mem,0 , vq->vq_ring_size); -vring_init (vr, size, ring_mem, vq->vq_alignment); +vring_init (vr, size, ring_mem,VIRTIO_PCI_VRING_ALIGN ); vq->vq_used_cons_idx =0 ; vq->vq_desc_head_idx =0 ; vq->vq_avail_idx =0 ;lib/librte_pmd_virtio/virtqueue.h +0
-019:00:09.918550097 -0700
lib/librte_pmd_virtio/virtqueue.h +1
-2@@ -139,8 +139,7 @@ struct virtqueue {uint8_t port_id;/**< Device port identifier. */ void *vq_ring_virt_mem;/**< linear address of vring*/ -int vq_alignment; -int vq_ring_size; +unsigned int vq_ring_size;phys_addr_t vq_ring_mem;/**< physical address of vring */ struct vring vq_ring;/**< vring keeping desc, used and avail */
RFC 9/10 virtio: fix how states are handled during initialization
In reply to Stephen HemmingerChange order of initialiazation to match Linux kernel. Don't blow away control queue by doing reset when stopped.
--- lib/librte_pmd_virtio/virtio_ethdev.c | 50 ++++++++++------------------------ lib/librte_pmd_virtio/virtio_rxtx.c | 2 + 2 files changed, 18 insertions(+), 34 deletions(-)
lib/librte_pmd_virtio/virtio_ethdev.c +16 -34
@@ -394,9 +394,11 @@ virtio_dev_cq_queue_setup(struct rte_ethstatic void virtio_dev_close (struct rte_eth_dev *dev) { -PMD_INIT_LOG (DEBUG ,"virtio_dev_close" ); +struct virtio_hw *hw = dev->data->dev_private; -virtio_dev_stop (dev); +vtpci_irq_config (hw,VIRTIO_MSI_NO_VECTOR ); +vtpci_reset (hw); +virtio_dev_free_mbufs (dev); }/*
@@ -811,6 +813,9 @@ eth_virtio_dev_init(__rte_unused structif (rte_eal_process_type () ==RTE_PROC_SECONDARY )return 0 ; +/* Tell the host we've noticed this device. */ +vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_ACK ); + pci_dev = eth_dev->pci_dev;if (virtio_resource_init (pci_dev) <0 )return -1 ;
@@ -821,9 +826,6 @@ eth_virtio_dev_init(__rte_unused struct/* Reset the device although not necessary at startup */ vtpci_reset (hw); -/* Tell the host we've noticed this device. */ -vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_ACK ); -/* Tell the host we've known how to drive the device. */ vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_DRIVER );virtio_negotiate_features (hw);
@@ -912,6 +914,9 @@ eth_virtio_dev_init(__rte_unused struct/* Setup interrupt callback */ rte_intr_callback_register (&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); + +virtio_dev_cq_start (eth_dev); +return 0 ; }
@@ -982,19 +987,8 @@ virtio_dev_configure(struct rte_eth_devstatic int virtio_dev_start (struct rte_eth_dev *dev) { -uint16_t nb_queues, i;struct virtio_hw *hw = dev->data->dev_private; - -/* Tell the host we've noticed this device. */ -vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_ACK ); - -/* Tell the host we've known how to drive the device. */ -vtpci_set_status (hw,VIRTIO_CONFIG_STATUS_DRIVER ); - -virtio_dev_cq_start (dev); - -/* Do final configuration before rx/tx engine starts */ -virtio_dev_rxtx_start (dev); +uint16_t nb_queues;/* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) {
@@ -1024,18 +1018,8 @@ virtio_dev_start(struct rte_eth_dev *devreturn -EINVAL ; } -PMD_INIT_LOG (DEBUG ,"nb_queues=%d" , nb_queues); - -for (i =0 ; i < nb_queues; i++) -virtqueue_notify (dev->data->rx_queues[i]); - -PMD_INIT_LOG (DEBUG ,"Notified backend at initialization" ); - -for (i =0 ; i < dev->data->nb_rx_queues; i++) -VIRTQUEUE_DUMP ((struct virtqueue *)dev->data->rx_queues[i]); - -for (i =0 ; i < dev->data->nb_tx_queues; i++) -VIRTQUEUE_DUMP ((struct virtqueue *)dev->data->tx_queues[i]); +/* Do final configuration before rx/tx engine starts */ +virtio_dev_rxtx_start (dev);return 0 ; }
@@ -1089,12 +1073,10 @@ static void virtio_dev_free_mbufs(structstatic void virtio_dev_stop (struct rte_eth_dev *dev) { -struct virtio_hw *hw = dev->data->dev_private; +if (dev->data->dev_conf.intr_conf.lsc) +rte_intr_disable (&dev->pci_dev->intr_handle); -/* reset the NIC */ -vtpci_irq_config (hw,0 ); -vtpci_reset (hw); -virtio_dev_free_mbufs (dev); +memset (&dev->data->dev_link,0 ,sizeof (struct rte_eth_link )); } static int
lib/librte_pmd_virtio/virtio_rxtx.c +2 -0
@@ -350,6 +350,8 @@ virtio_dev_rxtx_start(struct rte_eth_devfor (i =0 ; i < dev->data->nb_rx_queues; i++) {virtio_dev_vring_start (dev->data->rx_queues[i],VTNET_RQ );VIRTQUEUE_DUMP ((struct virtqueue *)dev->data->rx_queues[i]); + +virtqueue_notify (dev->data->rx_queues[i]); }/* Start tx vring. */
RFC 10/10 virtio: add support for promiscious and multicast
In reply to Stephen HemmingerImplement standard virtio controls for enabling and disabling promiscious and multicast.
lib/librte_pmd_virtio/virtio_ethdev.c +82 -16
@@ -77,6 +77,11 @@ static void virtio_get_hwaddr(struct vir static void virtio_dev_rx_queue_release(__rte_unused void *rxq); static void virtio_dev_tx_queue_release(__rte_unused void *txq); +static void virtio_promiscuous_enable (struct rte_eth_dev *dev); +static void virtio_promiscuous_disable (struct rte_eth_dev *dev); +static void virtio_allmulticast_enable (struct rte_eth_dev *dev); +static void virtio_allmulticast_disable (struct rte_eth_dev *dev); +static void virtio_dev_stats_get (struct rte_eth_dev *dev,struct rte_eth_stats *stats);static void virtio_dev_stats_reset (struct rte_eth_dev *dev);static void virtio_dev_free_mbufs (struct rte_eth_dev *dev);
@@ -405,23 +410,27 @@ virtio_dev_close(struct rte_eth_dev *dev* dev_ops for virtio, bare necessities for basic operation */ static struct eth_dev_ops virtio_eth_dev_ops = { - .dev_configure = virtio_dev_configure, - .dev_start = virtio_dev_start, - .dev_stop = virtio_dev_stop, - .dev_close = virtio_dev_close, - - .dev_infos_get = virtio_dev_info_get, - .stats_get = virtio_dev_stats_get, - .stats_reset = virtio_dev_stats_reset, - .link_update = virtio_dev_link_update, - .mac_addr_add =NULL , - .mac_addr_remove =NULL , - .rx_queue_setup = virtio_dev_rx_queue_setup, + .dev_configure = virtio_dev_configure, + .dev_start = virtio_dev_start, + .dev_stop = virtio_dev_stop, + .dev_close = virtio_dev_close, + + .dev_infos_get = virtio_dev_info_get, + .stats_get = virtio_dev_stats_get, + .stats_reset = virtio_dev_stats_reset, + .link_update = virtio_dev_link_update, + .promiscuous_enable = virtio_promiscuous_enable, + .promiscuous_disable = virtio_promiscuous_disable, + .allmulticast_enable = virtio_allmulticast_enable, + .allmulticast_disable = virtio_allmulticast_disable, + .mac_addr_add =NULL , + .mac_addr_remove =NULL , + .rx_queue_setup = virtio_dev_rx_queue_setup,/* meaningfull only to multiple queue */ - .rx_queue_release = virtio_dev_rx_queue_release, - .tx_queue_setup = virtio_dev_tx_queue_setup, + .rx_queue_release = virtio_dev_rx_queue_release, + .tx_queue_setup = virtio_dev_tx_queue_setup,/* meaningfull only to multiple queue */ - .tx_queue_release = virtio_dev_tx_queue_release, + .tx_queue_release = virtio_dev_tx_queue_release,/* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, };
@@ -466,6 +475,63 @@ virtio_dev_atomic_write_link_status(strureturn 0 ; } +/* Control receive processing (ie multicast, promiscious, mac address). */ +static int virtio_ctrl_rx (struct virtio_hw *hw,uint8_t cmd,uint8_t onoff) +{ +struct virtio_pmd_ctrl ctrl; +int len, ret; + +if (!vtpci_with_feature (hw,VIRTIO_NET_F_CTRL_RX )) +return -ENOTSUP ; + + ctrl.hdr.class =VIRTIO_NET_CTRL_RX ; + ctrl.hdr.cmd = cmd; +memcpy (ctrl.data, &onoff,sizeof (uint8_t )); + + len =sizeof (uint8_t ); + ret =virtio_send_command (hw->cvq, &ctrl, &len,1 ); +if (ret !=0 ) +PMD_DRV_LOG (NOTICE ,"ctrl_rx %u failed: %d\n" , cmd, ret); + +return ret; +} + +static void +virtio_promiscuous_enable (struct rte_eth_dev *dev) +{ +struct virtio_hw *hw = dev->data->dev_private; + +PMD_INIT_LOG (DEBUG ,"promiscious enable" ); +virtio_ctrl_rx (hw,VIRTIO_NET_CTRL_RX_PROMISC ,1 ); +} + +static void +virtio_promiscuous_disable (struct rte_eth_dev *dev) +{ +struct virtio_hw *hw = dev->data->dev_private; + +PMD_INIT_LOG (DEBUG ,"promiscious disable" ); +virtio_ctrl_rx (hw,VIRTIO_NET_CTRL_RX_PROMISC ,0 ); +} + +static void +virtio_allmulticast_enable (struct rte_eth_dev *dev) +{ +struct virtio_hw *hw = dev->data->dev_private; + +PMD_INIT_LOG (DEBUG ,"allmulticast enable" ); +virtio_ctrl_rx (hw,VIRTIO_NET_CTRL_RX_ALLMULTI ,1 ); +} + +static void +virtio_allmulticast_disable (struct rte_eth_dev *dev) +{ +struct virtio_hw *hw = dev->data->dev_private; + +PMD_INIT_LOG (DEBUG ,"allmulticast disable" ); +virtio_ctrl_rx (hw,VIRTIO_NET_CTRL_RX_ALLMULTI ,0 ); +} +static void virtio_dev_stats_get (struct rte_eth_dev *dev,struct rte_eth_stats *stats) {
@@ -559,7 +625,7 @@ virtio_negotiate_features(struct virtio_ {uint32_t host_features, mask; - mask =VIRTIO_NET_F_CTRL_RX |VIRTIO_NET_F_CTRL_VLAN ; + mask =VIRTIO_NET_F_CTRL_VLAN ; mask |=VIRTIO_NET_F_CSUM |VIRTIO_NET_F_GUEST_CSUM ;/* TSO and LRO are only available when their corresponding
A message that is not in the archive (sent off-list or not yet received): 20140826020858.448904783-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org
Re: [RFC 10/10] virtio: add support for promiscious and multicast
This patch is very similar with my previous patch:
[PATCH 4/5] virtio: New API to enable/disable multicast and promisc mode
So suggest applying only one of both.
Thanks
Changchun
Quoted 16 lines
-----Original Message-----
From: Stephen Hemminger [mailto:[email protected]]
Sent: Tuesday, August 26, 2014 10:08 AM
To: Ouyang, Changchun
Cc: [email protected]; Stephen Hemminger
Subject: [RFC 10/10] virtio: add support for promiscious and multicastImplement standard virtio controls for enabling and disabling promiscious and multicast.
Signed-off-by Stephen Hemminger <[email protected]>---
a/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:00:16.754586819 -0700
+++b/lib/librte_pmd_virtio/virtio_ethdev.c2014-08-25
19:02:48.019397658 -0700