* [dpdk-dev] [PATCH 00/22] Single virtio implementation @ 2015-01-15 5:15 Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 01/22] virtio: Rearrange resource initialization Ouyang Changchun ` (22 more replies) 0 siblings, 23 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev This is the patch set for single virtio implementation. Why we need single virtio? ============================ As we know currently there are at least 3 virtio PMD driver implementations: A) lib/librte_pmd_virtio(refer as virtio A); B) virtio_net_pmd by 6wind(refer as virtio B); C) virtio by Brocade/vyatta(refer as virtio C); Integrating 3 implementations into one could reduce the maintaining cost and time, in other hand, user don't need practice their application on 3 variant one by one to see which one is the best for them; What's the status? ==================== Currently virtio A has covered most features of virtio B except for using port io to get pci resource, so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some issues in original codes. What this patch set contains: =============================== 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; 2) virtio: Use weaker barriers, as 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 may help performance a bit; 3) virtio: Allow starting with link down, other driver has similar behavior; 4) virtio: Add support for Link State interrupt; 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; 6) virtio: Use software vlan stripping; 7) virtio: Remove unnecessary adapter structure; 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; 10) virtio: Make vtpci_get_status a local function as it is used in one file; 11) virtio: Check for packet headroom at compile time; 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; 13) virtio: Add support for vlan filtering; 14) virtio: Add support for multiple mac addresses; 15) virtio: Add ability to set MAC address; 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; 18) virtio: Fix descriptor index issue; 19) ether: Fix vlan strip/insert issue; 20) example/vhost: Avoid inserting vlan twice and guest and host; 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic with the normal Rx path. Changchun Ouyang (6): virtio: Use port IO to get PCI resource. virtio: Fix descriptor index issue ether: Fix vlan strip/insert issue example/vhost: Avoid inserting vlan twice example/vhost: Add vlan-strip cmd line option virtio: Use soft vlan strip in mergeable Rx path Stephen Hemminger (16): virtio: Rearrange resource initialization virtio: Use weaker barriers virtio: Allow starting with link down virtio: Add support for Link State interrupt ether: Add soft vlan encap/decap functions virtio: Use software vlan stripping virtio: Remove unnecessary adapter structure virtio: Remove redundant vq_alignment virtio: Fix how states are handled during initialization virtio: Make vtpci_get_status local virtio: Check for packet headroom at compile time virtio: Move allocation before initialization virtio: Add support for vlan filtering virtio: Add suport for multiple mac addresses virtio: Add ability to set MAC address virtio: Free mbuf's with threshold config/common_linuxapp | 2 + examples/vhost/main.c | 43 ++- lib/librte_eal/common/include/rte_pci.h | 4 + lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_ether/rte_ethdev.h | 8 + lib/librte_ether/rte_ether.h | 76 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 497 +++++++++++++++++++++++++------- lib/librte_pmd_virtio/virtio_ethdev.h | 12 +- lib/librte_pmd_virtio/virtio_pci.c | 20 +- lib/librte_pmd_virtio/virtio_pci.h | 8 +- lib/librte_pmd_virtio/virtio_rxtx.c | 110 +++++-- lib/librte_pmd_virtio/virtqueue.h | 59 +++- 12 files changed, 676 insertions(+), 168 deletions(-) -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 01/22] virtio: Rearrange resource initialization 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 02/22] virtio: Use weaker barriers Ouyang Changchun ` (21 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 76 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index c009f2a..6c31598 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -794,6 +794,41 @@ virtio_has_msix(const struct rte_pci_addr *loc) 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) @@ -801,6 +836,12 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) /* 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 /* @@ -831,40 +872,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 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; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 02/22] virtio: Use weaker barriers 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 01/22] virtio: Rearrange resource initialization Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 03/22] virtio: Allow starting with link down Ouyang Changchun ` (20 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev The 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 6c31598..78018f9 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -175,7 +175,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, uint32_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)); diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 3f6bad2..f878c62 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -456,7 +456,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) 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); @@ -516,6 +516,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } if (likely(nb_enqueued)) { + virtio_wmb(); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); @@ -547,7 +548,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, nb_used = VIRTQUEUE_NUSED(rxvq); - rmb(); + virtio_rmb(); if (nb_used == 0) return 0; @@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) PMD_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); @@ -735,6 +736,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) } } vq_update_avail_idx(txvq); + virtio_wmb(); txvq->packets += nb_tx; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index fdee054..f6ad98d 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -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) @@ -225,7 +234,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - rte_compiler_barrier(); + virtio_rmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } @@ -255,7 +264,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. */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 03/22] virtio: Allow starting with link down 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 01/22] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 02/22] virtio: Use weaker barriers Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 04/22] virtio: Add support for Link State interrupt Ouyang Changchun ` (19 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Starting driver with link down should be ok, it is with every other driver. So just allow it. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 78018f9..4bff0fe 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1057,14 +1057,12 @@ virtio_dev_start(struct rte_eth_dev *dev) vtpci_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); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 04/22] virtio: Add support for Link State interrupt 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (2 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 03/22] virtio: Allow starting with link down Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 05/22] ether: Add soft vlan encap/decap functions Ouyang Changchun ` (18 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Virtio has link state interrupt which can be used. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 4bff0fe..d37f2e9 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) #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. */ @@ -968,6 +996,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, PMD_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; } @@ -975,7 +1007,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), @@ -1021,6 +1053,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"); @@ -1029,7 +1064,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return (-EINVAL); } - return 0; + ret = vtpci_irq_config(hw, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, "failed to set config vector"); + + return ret; } @@ -1037,7 +1076,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); @@ -1052,18 +1090,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 @@ -1145,6 +1187,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); } @@ -1161,6 +1204,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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, @@ -1179,10 +1223,8 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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 diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index ca9c748..6d51032 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uint8_t status) VIRTIO_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; +} diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 373f9dc..6998737 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void 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_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 05/22] ether: Add soft vlan encap/decap functions 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (3 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 04/22] virtio: Add support for Link State interrupt Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 06/22] virtio: Use software vlan stripping Ouyang Changchun ` (17 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev It is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software. This allows application to be device independent. Avoid discarding shared mbufs. Make a copy in rte_vlan_insert() of any packet to be tagged that has a reference count > 1. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 187608d..3b6ab4b 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -49,6 +49,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. */ @@ -332,6 +334,80 @@ struct vxlan_hdr { #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) /**< VXLAN tunnel header length. */ +/** + * 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->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_REFCNT + /* Can't insert header if mbuf is shared */ + if (rte_mbuf_refcnt_read(*m) > 1) { + struct rte_mbuf *copy; + + copy = rte_pktmbuf_clone(*m, (*m)->pool); + if (unlikely(copy == NULL)) + return -ENOMEM; + rte_pktmbuf_free(*m); + *m = copy; + } +#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)->vlan_tci); + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 06/22] virtio: Use software vlan stripping 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (4 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 05/22] ether: Add soft vlan encap/decap functions Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 07/22] virtio: Remove unnecessary adapter structure Ouyang Changchun ` (16 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Implement VLAN stripping in software. This allows application to be device independent. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 3 +++ lib/librte_pmd_virtio/virtio_ethdev.c | 2 ++ lib/librte_pmd_virtio/virtio_pci.h | 1 + lib/librte_pmd_virtio/virtio_rxtx.c | 20 ++++++++++++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index f66805d..07d55b8 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -643,6 +643,9 @@ struct rte_eth_rxconf { #define ETH_TXQ_FLAGS_NOOFFLOADS \ (ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | \ ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) +#define ETH_TXQ_FLAGS_NOXSUMS \ + (ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ + ETH_TXQ_FLAGS_NOXSUMTCP) /** * A structure used to configure a TX ring of an Ethernet port. */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index d37f2e9..829838c 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1064,6 +1064,8 @@ virtio_dev_configure(struct rte_eth_dev *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"); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6998737..6d93fac 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -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]; }; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index f878c62..a5756e1 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -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" @@ -408,8 +409,8 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, 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; } @@ -446,6 +447,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]; @@ -489,6 +491,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->pkt_len = (uint32_t)(len[i] - hdr_size); rxm->data_len = (uint16_t)(len[i] - hdr_size); + if (hw->vlan_strip) + rte_vlan_strip(rxm); + VIRTIO_DUMP_PACKET(rxm, rxm->data_len); rx_pkts[nb_rx++] = rxm; @@ -717,6 +722,17 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) */ if (likely(need <= 0)) { 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)) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 07/22] virtio: Remove unnecessary adapter structure 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (5 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 06/22] virtio: Use software vlan stripping Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 08/22] virtio: Remove redundant vq_alignment Ouyang Changchun ` (15 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Cleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure. Also allows removing unneeded macro, making code clearer. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 43 ++++++++++++----------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 -------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 829838c..c89614d 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -207,8 +207,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, static 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; @@ -242,8 +241,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, const 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 */ @@ -383,8 +381,7 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, struct 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, @@ -410,8 +407,7 @@ virtio_dev_close(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -430,8 +426,7 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -450,8 +445,7 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -470,8 +464,7 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -853,8 +846,7 @@ 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); + struct virtio_hw *hw = dev->data->dev_private; uint8_t isr; /* Read interrupt status which clears interrupt */ @@ -880,12 +872,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, @@ -1010,7 +1001,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), }; /* @@ -1053,8 +1044,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"); @@ -1078,8 +1068,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); @@ -1185,8 +1174,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) static 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); @@ -1199,8 +1187,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet { 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; @@ -1232,7 +1219,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet static 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; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 1da3c62..55c9749 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -110,15 +110,6 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_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 diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a5756e1..73ad3ac 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -326,8 +326,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) void 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; if (hw->cvq) { virtio_dev_vring_start(hw->cvq, VTNET_CQ); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 08/22] virtio: Remove redundant vq_alignment 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (6 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 07/22] virtio: Remove unnecessary adapter structure Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 09/22] virtio: Fix how states are handled during initialization Ouyang Changchun ` (14 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Since vq_alignment is constant (always 4K), it does not need to be part of the vring struct. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index c89614d..b7f65b9 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -294,7 +294,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, 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; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 73ad3ac..b44f091 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) * 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; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index f6ad98d..5b8a255 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -138,8 +138,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 */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 09/22] virtio: Fix how states are handled during initialization 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (7 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 08/22] virtio: Remove redundant vq_alignment Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 10/22] virtio: Make vtpci_get_status local Ouyang Changchun ` (13 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Change order of initialiazation to match Linux kernel. Don't blow away control queue by doing reset when stopped. Calling dev_stop then dev_start would not work. Dev_stop was calling virtio reset and that would clear all queues and clear all feature negotiation. Resolved by only doing reset on device removal. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 58 ++++++++++++++++++++--------------- lib/librte_pmd_virtio/virtio_pci.c | 10 ++---- lib/librte_pmd_virtio/virtio_pci.h | 3 +- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b7f65b9..a07f4ca 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -398,9 +398,14 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, static void virtio_dev_close(struct rte_eth_dev *dev) { + struct virtio_hw *hw = dev->data->dev_private; + PMD_INIT_LOG(DEBUG, "virtio_dev_close"); - virtio_dev_stop(dev); + /* reset the NIC */ + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + vtpci_reset(hw); + virtio_dev_free_mbufs(dev); } static void @@ -889,6 +894,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (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; @@ -899,9 +907,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -990,6 +995,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* Setup interrupt callback */ rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); + + virtio_dev_cq_start(eth_dev); + return 0; } @@ -1044,7 +1052,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; - int ret; PMD_INIT_LOG(DEBUG, "configure"); @@ -1055,11 +1062,12 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; - ret = vtpci_irq_config(hw, 0); - if (ret != 0) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } - return ret; + return 0; } @@ -1069,17 +1077,6 @@ 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); - /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { @@ -1096,8 +1093,16 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Initialize Link state */ virtio_dev_link_update(dev, 0); + /* On restart after stop do not touch queues */ + if (hw->started) + return 0; + vtpci_reinit_complete(hw); + /* Do final configuration before rx/tx engine starts */ + virtio_dev_rxtx_start(dev); + hw->started = 1; + /*Notify the backend *Otherwise the tap backend might already stop its queue due to fullness. *vhost backend will have no chance to be waked up @@ -1168,17 +1173,20 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) } /* - * Stop device: disable rx and tx functions to allow for reconfiguring. + * Stop device: disable interrupt and mark link down */ static void virtio_dev_stop(struct rte_eth_dev *dev) { - struct virtio_hw *hw = dev->data->dev_private; + struct rte_eth_link link; - /* reset the NIC */ - vtpci_irq_config(hw, 0); - vtpci_reset(hw); - virtio_dev_free_mbufs(dev); + PMD_INIT_LOG(DEBUG, "stop"); + + if (dev->data->dev_conf.intr_conf.lsc) + rte_intr_disable(&dev->pci_dev->intr_handle); + + memset(&link, 0, sizeof(link)); + virtio_dev_atomic_write_link_status(dev, &link); } static int diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index 6d51032..b099e4f 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -137,15 +137,9 @@ vtpci_isr(struct virtio_hw *hw) /* Enable one vector (0) for Link State Intrerrupt */ -int +uint16_t 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; + return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); } diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6d93fac..0a4b578 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -170,6 +170,7 @@ struct virtio_hw { uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; + uint8_t started; uint8_t mac_addr[ETHER_ADDR_LEN]; }; @@ -266,6 +267,6 @@ void 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); +uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); #endif /* _VIRTIO_PCI_H_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 10/22] virtio: Make vtpci_get_status local 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (8 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 09/22] virtio: Fix how states are handled during initialization Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 11/22] virtio: Check for packet headroom at compile time Ouyang Changchun ` (12 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Make vtpci_get_status a local function as it is used in one file. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_pci.c | 4 +++- lib/librte_pmd_virtio/virtio_pci.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index b099e4f..2245bec 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -35,6 +35,8 @@ #include "virtio_pci.h" #include "virtio_logs.h" +static uint8_t vtpci_get_status(struct virtio_hw *); + void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -113,7 +115,7 @@ vtpci_reinit_complete(struct virtio_hw *hw) vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); } -uint8_t +static uint8_t vtpci_get_status(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 0a4b578..64d9c34 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -255,8 +255,6 @@ void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); -uint8_t vtpci_get_status(struct virtio_hw *); - void vtpci_set_status(struct virtio_hw *, uint8_t); uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 11/22] virtio: Check for packet headroom at compile time 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (9 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 10/22] virtio: Make vtpci_get_status local Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 12/22] virtio: Move allocation before initialization Ouyang Changchun ` (11 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Better to check at compile time than fail at runtime. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index a07f4ca..c17cac8 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -882,11 +882,7 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; - if (RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)) { - PMD_INIT_LOG(ERR, - "MBUF HEADROOM should be enough to hold virtio net hdr\n"); - return -1; - } + RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); eth_dev->dev_ops = &virtio_eth_dev_ops; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 12/22] virtio: Move allocation before initialization 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (10 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 11/22] virtio: Check for packet headroom at compile time Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 13/22] virtio: Add support for vlan filtering Ouyang Changchun ` (10 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev If allocation fails, don't want to leave virtio device stuck in middle of initialization sequence. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index c17cac8..13feda5 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -890,6 +890,15 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %d bytes needed to store MAC addresses", + ETHER_ADDR_LEN); + return -ENOMEM; + } + /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); @@ -916,15 +925,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr); } - /* Allocate memory for storing MAC addresses */ - eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); - if (eth_dev->data->mac_addrs == NULL) { - PMD_INIT_LOG(ERR, - "Failed to allocate %d bytes needed to store MAC addresses", - ETHER_ADDR_LEN); - return -ENOMEM; - } - /* Copy the permanent MAC address to: virtio_hw */ virtio_get_hwaddr(hw); ether_addr_copy((struct ether_addr *) hw->mac_addr, -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 13/22] virtio: Add support for vlan filtering 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (11 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 12/22] virtio: Move allocation before initialization Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 14/22] virtio: Add suport for multiple mac addresses Ouyang Changchun ` (9 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Virtio supports vlan filtering. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 13feda5..ec5a51e 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -84,6 +84,8 @@ static void virtio_dev_tx_queue_release(__rte_unused void *txq); 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); +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, + uint16_t vlan_id, int on); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -511,6 +513,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, + .vlan_filter_set = virtio_vlan_filter_set, }; static inline int @@ -640,14 +643,31 @@ virtio_get_hwaddr(struct virtio_hw *hw) } } +static int +virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtio_pmd_ctrl ctrl; + int len; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) + return -ENOTSUP; + + ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN; + ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; + memcpy(ctrl.data, &vlan_id, sizeof(vlan_id)); + len = sizeof(vlan_id); + + return virtio_send_command(hw->cvq, &ctrl, &len, 1); +} static void virtio_negotiate_features(struct virtio_hw *hw) { uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_VLAN; - mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; + /* checksum offload not implemented */ + mask = VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding * checksum offload feature is also negotiated. @@ -1058,6 +1078,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; + if (rxmode->hw_vlan_filter + && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { + PMD_DRV_LOG(NOTICE, + "vlan filtering not available on this host"); + return -ENOTSUP; + } + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); return -EBUSY; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 14/22] virtio: Add suport for multiple mac addresses 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (12 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 13/22] virtio: Add support for vlan filtering Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 15/22] virtio: Add ability to set MAC address Ouyang Changchun ` (8 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Virtio support multiple MAC addresses. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 94 ++++++++++++++++++++++++++++++++++- lib/librte_pmd_virtio/virtio_ethdev.h | 3 +- lib/librte_pmd_virtio/virtqueue.h | 34 ++++++++++++- 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index ec5a51e..e469ac2 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -86,6 +86,10 @@ static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); +static void virtio_mac_addr_add(struct rte_eth_dev *dev, + struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused); +static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -503,8 +507,6 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .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, /* meaningfull only to multiple queue */ .rx_queue_release = virtio_dev_rx_queue_release, @@ -514,6 +516,8 @@ static struct eth_dev_ops virtio_eth_dev_ops = { /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, .vlan_filter_set = virtio_vlan_filter_set, + .mac_addr_add = virtio_mac_addr_add, + .mac_addr_remove = virtio_mac_addr_remove, }; static inline int @@ -644,6 +648,92 @@ virtio_get_hwaddr(struct virtio_hw *hw) } static int +virtio_mac_table_set(struct virtio_hw *hw, + const struct virtio_net_ctrl_mac *uc, + const struct virtio_net_ctrl_mac *mc) +{ + struct virtio_pmd_ctrl ctrl; + int err, len[2]; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET; + + len[0] = uc->entries * ETHER_ADDR_LEN + sizeof(uc->entries); + memcpy(ctrl.data, uc, len[0]); + + len[1] = mc->entries * ETHER_ADDR_LEN + sizeof(mc->entries); + memcpy(ctrl.data + len[0], mc, len[1]); + + err = virtio_send_command(hw->cvq, &ctrl, len, 2); + if (err != 0) + PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err); + + return err; +} + +static void +virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused) +{ + struct virtio_hw *hw = dev->data->dev_private; + const struct ether_addr *addrs = dev->data->mac_addrs; + unsigned int i; + struct virtio_net_ctrl_mac *uc, *mc; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + const struct ether_addr *addr + = (i == index) ? mac_addr : addrs + i; + struct virtio_net_ctrl_mac *tbl + = is_multicast_ether_addr(addr) ? mc : uc; + + memcpy(&tbl->macs[tbl->entries++], addr, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static void +virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct ether_addr *addrs = dev->data->mac_addrs; + struct virtio_net_ctrl_mac *uc, *mc; + unsigned int i; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + struct virtio_net_ctrl_mac *tbl; + + if (i == index || is_zero_ether_addr(addrs + i)) + continue; + + tbl = is_multicast_ether_addr(addrs + i) ? mc : uc; + memcpy(&tbl->macs[tbl->entries++], addrs + i, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct virtio_hw *hw = dev->data->dev_private; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 55c9749..74ac7e0 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -51,7 +51,7 @@ #define VIRTIO_MAX_RX_QUEUES 128 #define VIRTIO_MAX_TX_QUEUES 128 -#define VIRTIO_MAX_MAC_ADDRS 1 +#define VIRTIO_MAX_MAC_ADDRS 64 #define VIRTIO_MIN_RX_BUFSIZE 64 #define VIRTIO_MAX_RX_PKTLEN 9728 @@ -60,6 +60,7 @@ (VIRTIO_NET_F_MAC | \ VIRTIO_NET_F_STATUS | \ VIRTIO_NET_F_MQ | \ + VIRTIO_NET_F_CTRL_MAC_ADDR | \ VIRTIO_NET_F_CTRL_VQ | \ VIRTIO_NET_F_CTRL_RX | \ VIRTIO_NET_F_CTRL_VLAN | \ diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 5b8a255..d210f4f 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -99,6 +99,34 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; #define VIRTIO_NET_CTRL_RX_NOBCAST 5 /** + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + uint32_t entries; + uint8_t macs[][ETHER_ADDR_LEN]; +} __attribute__((__packed__)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/** * Control VLAN filtering * * The VLAN filter table is controlled via a simple ADD/DEL interface. @@ -121,7 +149,7 @@ typedef uint8_t virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_MAX_CTRL_DATA 128 +#define VIRTIO_MAX_CTRL_DATA 2048 struct virtio_pmd_ctrl { struct virtio_net_ctrl_hdr hdr; @@ -180,6 +208,10 @@ struct virtqueue { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 #endif +#ifndef VIRTIO_NET_F_CTRL_MAC_ADDR +#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 +#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 +#endif /** * This is the first element of the scatter-gather list. If you don't -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 15/22] virtio: Add ability to set MAC address 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (13 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 14/22] virtio: Add suport for multiple mac addresses Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 16/22] virtio: Free mbuf's with threshold Ouyang Changchun ` (7 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Need to have do special things to set default mac address. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 5 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 07d55b8..cbe3fdf 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1249,6 +1249,10 @@ typedef void (*eth_mac_addr_add_t)(struct rte_eth_dev *dev, uint32_t vmdq); /**< @internal Set a MAC address into Receive Address Address Register */ +typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); +/**< @internal Set a MAC address into Receive Address Address Register */ + typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint8_t on); @@ -1482,6 +1486,7 @@ struct eth_dev_ops { priority_flow_ctrl_set_t priority_flow_ctrl_set; /**< Setup priority flow control.*/ eth_mac_addr_remove_t mac_addr_remove; /**< Remove MAC address */ eth_mac_addr_add_t mac_addr_add; /**< Add a MAC address */ + eth_mac_addr_set_t mac_addr_set; /**< Set a MAC address */ eth_uc_hash_table_set_t uc_hash_table_set; /**< Set Unicast Table Array */ eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */ eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index e469ac2..c5f21c1 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -90,6 +90,8 @@ static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused); static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); +static void virtio_mac_addr_set(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -518,6 +520,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .vlan_filter_set = virtio_vlan_filter_set, .mac_addr_add = virtio_mac_addr_add, .mac_addr_remove = virtio_mac_addr_remove, + .mac_addr_set = virtio_mac_addr_set, }; static inline int @@ -733,6 +736,27 @@ virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) virtio_mac_table_set(hw, uc, mc); } +static void +virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) +{ + struct virtio_hw *hw = dev->data->dev_private; + + memcpy(hw->mac_addr, mac_addr, ETHER_ADDR_LEN); + + /* Use atomic update if available */ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { + struct virtio_pmd_ctrl ctrl; + int len = ETHER_ADDR_LEN; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; + + memcpy(ctrl.data, mac_addr, ETHER_ADDR_LEN); + virtio_send_command(hw->cvq, &ctrl, &len, 1); + } else if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) + virtio_set_hwaddr(hw); +} + static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 16/22] virtio: Free mbuf's with threshold 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (14 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 15/22] virtio: Add ability to set MAC address Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 17/22] virtio: Use port IO to get PCI resource Ouyang Changchun ` (6 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev This makes virtio driver work like ixgbe. Transmit buffers are held until a transmit threshold is reached. The previous behavior was to hold mbuf's until the ring entry was reused which caused more memory usage than needed. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 7 ++-- lib/librte_pmd_virtio/virtio_rxtx.c | 75 +++++++++++++++++++++++++---------- lib/librte_pmd_virtio/virtqueue.h | 3 +- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index c5f21c1..1ec29e1 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -176,15 +176,16 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, virtqueue_notify(vq); - while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) + rte_rmb(); + while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { + rte_rmb(); usleep(100); + } while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; - virtio_rmb(); - used_idx = (uint32_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index b44f091..12c2310 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -129,17 +129,32 @@ virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, return i; } +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif + +/* Cleanup from completed transmits. */ static void -virtqueue_dequeue_pkt_tx(struct virtqueue *vq) +virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) { - struct vring_used_elem *uep; - uint16_t used_idx, desc_idx; + uint16_t i, used_idx, desc_idx; + for (i = 0; i < num; i++) { + struct vring_used_elem *uep; + struct vq_desc_extra *dxp; + + used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); + uep = &vq->vq_ring.used->ring[used_idx]; + dxp = &vq->vq_descx[used_idx]; + + desc_idx = (uint16_t) uep->id; + vq->vq_used_cons_idx++; + vq_ring_free_chain(vq, desc_idx); - used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); - uep = &vq->vq_ring.used->ring[used_idx]; - desc_idx = (uint16_t) uep->id; - vq->vq_used_cons_idx++; - vq_ring_free_chain(vq, desc_idx); + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } } @@ -203,8 +218,6 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) idx = head_idx; dxp = &txvq->vq_descx[idx]; - if (dxp->cookie != NULL) - rte_pktmbuf_free(dxp->cookie); dxp->cookie = (void *)cookie; dxp->ndescs = needed; @@ -404,6 +417,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; struct virtqueue *vq; + uint16_t tx_free_thresh; int ret; PMD_INIT_FUNC_TRACE(); @@ -421,6 +435,22 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, return ret; } + tx_free_thresh = tx_conf->tx_free_thresh; + if (tx_free_thresh == 0) + tx_free_thresh = + RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH); + + if (tx_free_thresh >= (vq->vq_nentries - 3)) { + RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the " + "number of TX entries minus 3 (%u)." + " (tx_free_thresh=%u port=%u queue=%u)\n", + vq->vq_nentries - 3, + tx_free_thresh, dev->data->port_id, queue_idx); + return -EINVAL; + } + + vq->vq_free_thresh = tx_free_thresh; + dev->data->tx_queues[queue_idx] = vq; return 0; } @@ -688,11 +718,9 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; - uint16_t nb_used, nb_tx, num; + uint16_t nb_used, nb_tx; int error; - nb_tx = 0; - if (unlikely(nb_pkts < 1)) return nb_pkts; @@ -700,21 +728,26 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); + if (likely(nb_used > txvq->vq_free_thresh)) + virtio_xmit_cleanup(txvq, nb_used); - num = (uint16_t)(likely(nb_used < VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ); + nb_tx = 0; while (nb_tx < nb_pkts) { /* Need one more descriptor for virtio header. */ int need = tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; - int deq_cnt = RTE_MIN(need, (int)num); - num -= (deq_cnt > 0) ? deq_cnt : 0; - while (deq_cnt > 0) { - virtqueue_dequeue_pkt_tx(txvq); - deq_cnt--; + /*Positive value indicates it need free vring descriptors */ + if (unlikely(need > 0)) { + nb_used = VIRTQUEUE_NUSED(txvq); + virtio_rmb(); + need = RTE_MIN(need, (int)nb_used); + + virtio_xmit_cleanup(txvq, need); + need = (int)tx_pkts[nb_tx]->nb_segs - + txvq->vq_free_cnt + 1; } - need = (int)tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; /* * Zero or negative value indicates it has enough free * descriptors to use for transmitting. @@ -723,7 +756,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) txm = tx_pkts[nb_tx]; /* Do VLAN tag insertion */ - if (txm->ol_flags & PKT_TX_VLAN_PKT) { + if (unlikely(txm->ol_flags & PKT_TX_VLAN_PKT)) { error = rte_vlan_insert(&txm); if (unlikely(error)) { rte_pktmbuf_free(txm); diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index d210f4f..6c45c27 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -164,6 +164,7 @@ struct virtqueue { struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint8_t port_id; /**< Device port identifier. */ + uint16_t vq_queue_index; /**< PCI queue index */ void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; @@ -172,7 +173,7 @@ struct virtqueue { struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_nentries; /**< vring desc numbers */ - uint16_t vq_queue_index; /**< PCI queue index */ + uint16_t vq_free_thresh; /**< free threshold */ /** * Head of the free chain in the descriptor table. If * there are no free descriptors, this will be set to -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 17/22] virtio: Use port IO to get PCI resource. 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (15 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 16/22] virtio: Free mbuf's with threshold Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue Ouyang Changchun ` (5 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- config/common_linuxapp | 2 + lib/librte_eal/common/include/rte_pci.h | 4 ++ lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_pmd_virtio/virtio_ethdev.c | 91 ++++++++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/config/common_linuxapp b/config/common_linuxapp index 6243d4b..a3227a2 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -125,6 +125,8 @@ CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n CONFIG_RTE_EAL_IGB_UIO=y CONFIG_RTE_EAL_VFIO=y +# Only for VIRTIO PMD currently +CONFIG_RTE_EAL_PORT_IO=n # # Special configurations in PCI Config Space for high performance diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..19abc1f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -193,6 +193,10 @@ struct rte_pci_driver { /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */ #define RTE_PCI_DRV_NEED_MAPPING 0x0001 +/** Device needs port IO(done with /proc/ioports) */ +#ifdef RTE_EAL_PORT_IO +#define RTE_PCI_DRV_PORT_IO 0x0002 +#endif /** Device driver must be registered several times until failure - deprecated */ #pragma GCC poison RTE_PCI_DRV_MULTIPLE /** Device needs to be unbound even if no module is provided */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..5db0059 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -574,7 +574,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d /* map resources for devices that use igb_uio */ ret = pci_map_device(dev); if (ret != 0) - return ret; +#ifdef RTE_EAL_PORT_IO + if ((dr->drv_flags & RTE_PCI_DRV_PORT_IO) == 0) +#endif + return ret; } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && rte_eal_process_type() == RTE_PROC_PRIMARY) { /* unbind current driver */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 1ec29e1..15324c9 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -961,6 +961,71 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) start, size); return 0; } + +#ifdef RTE_EAL_PORT_IO +/* Extract port I/O numbers from proc/ioports */ +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_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; +} +#endif + #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -974,6 +1039,14 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) /* no setup required */ return 0; } + +#ifdef RTE_EAL_PORT_IO +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + /* no setup required */ + return 0; +} +#endif #endif /* @@ -1039,7 +1112,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev = eth_dev->pci_dev; if (virtio_resource_init(pci_dev) < 0) - return -1; +#ifdef RTE_EAL_PORT_IO + if (virtio_resource_init_by_portio(pci_dev) < 0) +#endif + return -1; hw->use_msix = virtio_has_msix(&pci_dev->addr); hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; @@ -1132,6 +1208,18 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 0; } +#ifdef RTE_EAL_PORT_IO +static struct eth_driver rte_virtio_pmd = { + { + .name = "rte_virtio_pmd", + .id_table = pci_id_virtio_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_PORT_IO | + RTE_PCI_DRV_INTR_LSC, + }, + .eth_dev_init = eth_virtio_dev_init, + .dev_private_size = sizeof(struct virtio_hw), +}; +#else static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", @@ -1141,6 +1229,7 @@ static struct eth_driver rte_virtio_pmd = { .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_hw), }; +#endif /* * Driver initialization routine. -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (16 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 17/22] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 16:54 ` Stephen Hemminger 2015-01-15 5:15 ` [dpdk-dev] [PATCH 19/22] ether: Fix vlan strip/insert issue Ouyang Changchun ` (4 subsequent siblings) 22 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev It should use vring descriptor index instead of used_ring index to index vq_descx. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 12c2310..2529dc4 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; - dxp = &vq->vq_descx[used_idx]; desc_idx = (uint16_t) uep->id; + dxp = &vq->vq_descx[desc_idx]; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue 2015-01-15 5:15 ` [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue Ouyang Changchun @ 2015-01-15 16:54 ` Stephen Hemminger 2015-01-16 0:55 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-01-15 16:54 UTC (permalink / raw) To: Ouyang Changchun; +Cc: dev On Thu, 15 Jan 2015 13:15:26 +0800 Ouyang Changchun <changchun.ouyang@intel.com> wrote: > It should use vring descriptor index instead of used_ring index to index vq_descx. > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > --- > lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c > index 12c2310..2529dc4 100644 > --- a/lib/librte_pmd_virtio/virtio_rxtx.c > +++ b/lib/librte_pmd_virtio/virtio_rxtx.c > @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) > > used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); > uep = &vq->vq_ring.used->ring[used_idx]; > - dxp = &vq->vq_descx[used_idx]; > > desc_idx = (uint16_t) uep->id; > + dxp = &vq->vq_descx[desc_idx]; > vq->vq_used_cons_idx++; > vq_ring_free_chain(vq, desc_idx); > Rather than patching a code added by earlier patch in series, why not just fix/merge the two patches? ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue 2015-01-15 16:54 ` Stephen Hemminger @ 2015-01-16 0:55 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-01-16 0:55 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Friday, January 16, 2015 12:54 AM > To: Ouyang, Changchun > Cc: dev@dpdk.org; Doherty, Declan; Cao, Waterman > Subject: Re: [PATCH 18/22] virtio: Fix descriptor index issue > > On Thu, 15 Jan 2015 13:15:26 +0800 > Ouyang Changchun <changchun.ouyang@intel.com> wrote: > > > It should use vring descriptor index instead of used_ring index to index > vq_descx. > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > --- > > lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c > > b/lib/librte_pmd_virtio/virtio_rxtx.c > > index 12c2310..2529dc4 100644 > > --- a/lib/librte_pmd_virtio/virtio_rxtx.c > > +++ b/lib/librte_pmd_virtio/virtio_rxtx.c > > @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t > > num) > > > > used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq- > >vq_nentries - 1)); > > uep = &vq->vq_ring.used->ring[used_idx]; > > - dxp = &vq->vq_descx[used_idx]; > > > > desc_idx = (uint16_t) uep->id; > > + dxp = &vq->vq_descx[desc_idx]; > > vq->vq_used_cons_idx++; > > vq_ring_free_chain(vq, desc_idx); > > > > Rather than patching a code added by earlier patch in series, why not just > fix/merge the two patches? I think it could be more clear what's the original patch looks like and what I need to fix. And I also resolve the patch author issue, which I am not care for, but someone may care for. :-) Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 19/22] ether: Fix vlan strip/insert issue 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (17 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 20/22] example/vhost: Avoid inserting vlan twice Ouyang Changchun ` (3 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Need swap the data from cpu to BE(big endian) for vlan-type. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 3b6ab4b..90fb3c9 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -350,7 +350,7 @@ 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) + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) return -1; struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); @@ -400,7 +400,7 @@ static inline int rte_vlan_insert(struct rte_mbuf **m) return -ENOSPC; memmove(nh, oh, 2 * ETHER_ADDR_LEN); - nh->ether_type = ETHER_TYPE_VLAN; + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vh = (struct vlan_hdr *) (nh + 1); vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 20/22] example/vhost: Avoid inserting vlan twice 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (18 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 19/22] ether: Fix vlan strip/insert issue Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 21/22] example/vhost: Add vlan-strip cmd line option Ouyang Changchun ` (2 subsequent siblings) 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Check if it has already been vlan-tagged packet, if true, avoid inserting a duplicated vlan tag into it. This is a possible case when guest has the capability of inserting vlan tag. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 1f1edbe..a7e623e 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -1120,6 +1120,7 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) unsigned len, ret, offset = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; + struct ether_hdr *nh; /*check if destination is local VM*/ if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) { @@ -1141,12 +1142,21 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; - m->ol_flags = PKT_TX_VLAN_PKT; + nh = rte_pktmbuf_mtod(m, struct ether_hdr *); + if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) { + /* Guest has inserted the vlan tag. */ + struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1); + uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag); + if (vh->vlan_tci != vlan_tag_be) + vh->vlan_tci = vlan_tag_be; + } else { + m->ol_flags = PKT_TX_VLAN_PKT; - m->data_len += offset; - m->pkt_len += offset; + m->data_len += offset; + m->pkt_len += offset; - m->vlan_tci = vlan_tag; + m->vlan_tci = vlan_tag; + } tx_q->m_table[len] = m; len++; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 21/22] example/vhost: Add vlan-strip cmd line option 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (19 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 20/22] example/vhost: Avoid inserting vlan twice Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun 22 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev Support turn on/off RX VLAN strip on host, this let guest get the chance of using its software VALN strip functionality. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index a7e623e..4df4977 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -178,6 +178,9 @@ static uint32_t num_devices; static uint32_t zero_copy; static int mergeable; +/* Do vlan strip on host, enabled on default */ +static uint32_t vlan_strip = 1; + /* number of descriptors to apply*/ static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP; static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP; @@ -570,6 +573,7 @@ us_vhost_usage(const char *prgname) " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n" " --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n" + " --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n" " --zero-copy [0|1]: disable(default)/enable rx/tx " @@ -597,6 +601,7 @@ us_vhost_parse_args(int argc, char **argv) {"rx-retry-delay", required_argument, NULL, 0}, {"rx-retry-num", required_argument, NULL, 0}, {"mergeable", required_argument, NULL, 0}, + {"vlan-strip", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {"dev-basename", required_argument, NULL, 0}, {"zero-copy", required_argument, NULL, 0}, @@ -697,6 +702,22 @@ us_vhost_parse_args(int argc, char **argv) } } + /* Enable/disable RX VLAN strip on host. */ + if (!strncmp(long_option[option_index].name, + "vlan-strip", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, + "Invalid argument for VLAN strip [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else { + vlan_strip = !!ret; + vmdq_conf_default.rxmode.hw_vlan_strip = + vlan_strip; + } + } + /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); @@ -955,7 +976,9 @@ link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m) dev->device_fh); /* Enable stripping of the vlan tag as we handle routing. */ - rte_eth_dev_set_vlan_strip_on_queue(ports[0], (uint16_t)vdev->vmdq_rx_q, 1); + if (vlan_strip) + rte_eth_dev_set_vlan_strip_on_queue(ports[0], + (uint16_t)vdev->vmdq_rx_q, 1); /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (20 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 21/22] example/vhost: Add vlan-strip cmd line option Ouyang Changchun @ 2015-01-15 5:15 ` Ouyang Changchun 2015-01-15 16:55 ` Stephen Hemminger 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun 22 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-01-15 5:15 UTC (permalink / raw) To: dev To keep the consistent logic with normal Rx path, the mergeable Rx path also needs software vlan strip/decap if it is enabled. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 2529dc4..9090613 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, 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]; @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, seg_res -= rcv_cnt; } + if (hw->vlan_strip) + rte_vlan_strip(rx_pkts[nb_rx]); + VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], rx_pkts[nb_rx]->data_len); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path 2015-01-15 5:15 ` [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun @ 2015-01-15 16:55 ` Stephen Hemminger 2015-01-16 0:56 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-01-15 16:55 UTC (permalink / raw) To: Ouyang Changchun; +Cc: dev On Thu, 15 Jan 2015 13:15:30 +0800 Ouyang Changchun <changchun.ouyang@intel.com> wrote: > To keep the consistent logic with normal Rx path, the mergeable > Rx path also needs software vlan strip/decap if it is enabled. > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > --- > lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c > index 2529dc4..9090613 100644 > --- a/lib/librte_pmd_virtio/virtio_rxtx.c > +++ b/lib/librte_pmd_virtio/virtio_rxtx.c > @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, > 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]; > @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, > seg_res -= rcv_cnt; > } > > + if (hw->vlan_strip) > + rte_vlan_strip(rx_pkts[nb_rx]); > + > VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], > rx_pkts[nb_rx]->data_len); > If you resubmit, just combine this with earlier patch that does vlan strip ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path 2015-01-15 16:55 ` Stephen Hemminger @ 2015-01-16 0:56 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-01-16 0:56 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Friday, January 16, 2015 12:56 AM > To: Ouyang, Changchun > Cc: dev@dpdk.org; Doherty, Declan; Cao, Waterman > Subject: Re: [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path > > On Thu, 15 Jan 2015 13:15:30 +0800 > Ouyang Changchun <changchun.ouyang@intel.com> wrote: > > > To keep the consistent logic with normal Rx path, the mergeable Rx > > path also needs software vlan strip/decap if it is enabled. > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > --- > > lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ > > 1 file changed, 4 insertions(+) > > > > diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c > > b/lib/librte_pmd_virtio/virtio_rxtx.c > > index 2529dc4..9090613 100644 > > --- a/lib/librte_pmd_virtio/virtio_rxtx.c > > +++ b/lib/librte_pmd_virtio/virtio_rxtx.c > > @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, > > 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]; > > @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, > > seg_res -= rcv_cnt; > > } > > > > + if (hw->vlan_strip) > > + rte_vlan_strip(rx_pkts[nb_rx]); > > + > > VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], > > rx_pkts[nb_rx]->data_len); > > > > If you resubmit, just combine this with earlier patch that does vlan strip I think just keeping it as a separate a patch may be a good way. Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun ` (21 preceding siblings ...) 2015-01-15 5:15 ` [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 01/24] virtio: Rearrange resource initialization Ouyang Changchun ` (25 more replies) 22 siblings, 26 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev This is the patch set for single virtio implementation. Why we need single virtio? ============================ As we know currently there are at least 3 virtio PMD driver implementations: A) lib/librte_pmd_virtio(refer as virtio A); B) virtio_net_pmd by 6wind(refer as virtio B); C) virtio by Brocade/vyatta(refer as virtio C); Integrating 3 implementations into one could reduce the maintaining cost and time, in other hand, user don't need practice their application on 3 variant one by one to see which one is the best for them; What's the status? ==================== Currently virtio A has covered most features of virtio B except for using port io to get pci resource, so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some issues in original codes. What this patch set contains: =============================== 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; 2) virtio: Use weaker barriers, as 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 may help performance a bit; 3) virtio: Allow starting with link down, other driver has similar behavior; 4) virtio: Add support for Link State interrupt; 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; 6) virtio: Use software vlan stripping; 7) virtio: Remove unnecessary adapter structure; 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; 10) virtio: Make vtpci_get_status a local function as it is used in one file; 11) virtio: Check for packet headroom at compile time; 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; 13) virtio: Add support for vlan filtering; 14) virtio: Add support for multiple mac addresses; 15) virtio: Add ability to set MAC address; 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; 18) virtio: Fix descriptor index issue; 19) ether: Fix vlan strip/insert issue; 20) example/vhost: Avoid inserting vlan twice and guest and host; 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic with the normal Rx path. Changes in v2: 23) virtio: Fix zero copy break issue, the vring should be ready before virtio PMD set the status of DRIVER_OK; 24) virtio: Remove unnecessary hotspots in data path. Changchun Ouyang (8): virtio: Use port IO to get PCI resource. virtio: Fix descriptor index issue ether: Fix vlan strip/insert issue example/vhost: Avoid inserting vlan twice example/vhost: Add vlan-strip cmd line option virtio: Use soft vlan strip in mergeable Rx path virtio: Fix zero copy break issue virtio: Remove hotspots Stephen Hemminger (16): virtio: Rearrange resource initialization virtio: Use weaker barriers virtio: Allow starting with link down virtio: Add support for Link State interrupt ether: Add soft vlan encap/decap functions virtio: Use software vlan stripping virtio: Remove unnecessary adapter structure virtio: Remove redundant vq_alignment virtio: Fix how states are handled during initialization virtio: Make vtpci_get_status local virtio: Check for packet headroom at compile time virtio: Move allocation before initialization virtio: Add support for vlan filtering virtio: Add suport for multiple mac addresses virtio: Add ability to set MAC address virtio: Free mbuf's with threshold config/common_linuxapp | 2 + examples/vhost/main.c | 39 ++- lib/librte_eal/common/include/rte_pci.h | 4 + lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_ether/rte_ethdev.h | 8 + lib/librte_ether/rte_ether.h | 76 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 492 +++++++++++++++++++++++++------- lib/librte_pmd_virtio/virtio_ethdev.h | 12 +- lib/librte_pmd_virtio/virtio_pci.c | 20 +- lib/librte_pmd_virtio/virtio_pci.h | 8 +- lib/librte_pmd_virtio/virtio_rxtx.c | 139 ++++++--- lib/librte_pmd_virtio/virtqueue.h | 59 +++- 12 files changed, 693 insertions(+), 171 deletions(-) -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 01/24] virtio: Rearrange resource initialization 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers Ouyang Changchun ` (24 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 76 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b3b5bb6..662a49c 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -794,6 +794,41 @@ virtio_has_msix(const struct rte_pci_addr *loc) 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) @@ -801,6 +836,12 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) /* 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 /* @@ -831,40 +872,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 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; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 01/24] virtio: Rearrange resource initialization Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 7:03 ` Xie, Huawei 2015-01-27 7:56 ` Xie, Huawei 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 03/24] virtio: Allow starting with link down Ouyang Changchun ` (23 subsequent siblings) 25 siblings, 2 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev The 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 662a49c..dc47e72 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -175,7 +175,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, uint32_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)); diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c013f97..78af334 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -456,7 +456,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) 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); @@ -516,6 +516,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } if (likely(nb_enqueued)) { + virtio_wmb(); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); @@ -547,7 +548,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, nb_used = VIRTQUEUE_NUSED(rxvq); - rmb(); + virtio_rmb(); if (nb_used == 0) return 0; @@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) PMD_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); @@ -735,6 +736,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) } } vq_update_avail_idx(txvq); + virtio_wmb(); txvq->packets += nb_tx; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index fdee054..f6ad98d 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -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) @@ -225,7 +234,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - rte_compiler_barrier(); + virtio_rmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } @@ -255,7 +264,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. */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers Ouyang Changchun @ 2015-01-27 7:03 ` Xie, Huawei 2015-01-27 9:58 ` Stephen Hemminger 2015-01-27 7:56 ` Xie, Huawei 1 sibling, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-01-27 7:03 UTC (permalink / raw) To: Ouyang, Changchun, dev > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ouyang Changchun > Sent: Tuesday, January 27, 2015 10:36 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers > > The 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. > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > --- > 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(-) > > diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c > b/lib/librte_pmd_virtio/virtio_ethdev.c > index 662a49c..dc47e72 100644 > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > @@ -175,7 +175,7 @@ virtio_send_command(struct virtqueue *vq, struct > virtio_pmd_ctrl *ctrl, > uint32_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)); > diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c > b/lib/librte_pmd_virtio/virtio_rxtx.c > index c013f97..78af334 100644 > --- a/lib/librte_pmd_virtio/virtio_rxtx.c > +++ b/lib/librte_pmd_virtio/virtio_rxtx.c > @@ -456,7 +456,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf > **rx_pkts, uint16_t nb_pkts) > > 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); > @@ -516,6 +516,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf > **rx_pkts, uint16_t nb_pkts) > } > > if (likely(nb_enqueued)) { > + virtio_wmb(); > if (unlikely(virtqueue_kick_prepare(rxvq))) { > virtqueue_notify(rxvq); > PMD_RX_LOG(DEBUG, "Notified\n"); > @@ -547,7 +548,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, > > nb_used = VIRTQUEUE_NUSED(rxvq); > > - rmb(); > + virtio_rmb(); > > if (nb_used == 0) > return 0; > @@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf > **tx_pkts, uint16_t nb_pkts) > PMD_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); > > @@ -735,6 +736,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf > **tx_pkts, uint16_t nb_pkts) > } > } > vq_update_avail_idx(txvq); > + virtio_wmb(); > > txvq->packets += nb_tx; > > diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h > index fdee054..f6ad98d 100644 > --- a/lib/librte_pmd_virtio/virtqueue.h > +++ b/lib/librte_pmd_virtio/virtqueue.h > @@ -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) > @@ -225,7 +234,7 @@ virtqueue_full(const struct virtqueue *vq) > static inline void > vq_update_avail_idx(struct virtqueue *vq) > { > - rte_compiler_barrier(); > + virtio_rmb(); I recall our original code is virtio_wmb(). Use store fence to ensure all updates to entries before updating the index. Why do we need virtio_rmb() here and add virtio_wmb after vq_update_avail_idx()? > vq->vq_ring.avail->idx = vq->vq_avail_idx; > } > > @@ -255,7 +264,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. > */ > -- > 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 7:03 ` Xie, Huawei @ 2015-01-27 9:58 ` Stephen Hemminger 2015-01-27 16:16 ` Xie, Huawei 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-01-27 9:58 UTC (permalink / raw) To: Xie, Huawei; +Cc: dev > I recall our original code is virtio_wmb(). > Use store fence to ensure all updates to entries before updating the index. > Why do we need virtio_rmb() here and add virtio_wmb after vq_update_avail_idx()? Store fence is unnecessary, Intel CPU's are cache coherent, please read the virtio Linux ring header file for explanation. A full fence WMB is more expensive and causes CPU stall > > vq->vq_ring.avail->idx = vq->vq_avail_idx; > > } > > > > @@ -255,7 +264,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. > > */ > > -- > > 1.8.4.2 > ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 9:58 ` Stephen Hemminger @ 2015-01-27 16:16 ` Xie, Huawei 2015-01-28 6:12 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-01-27 16:16 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Tuesday, January 27, 2015 5:59 PM > To: Xie, Huawei > Cc: Ouyang, Changchun; dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers > > > > I recall our original code is virtio_wmb(). > > Use store fence to ensure all updates to entries before updating the index. > > Why do we need virtio_rmb() here and add virtio_wmb after > vq_update_avail_idx()? > > Store fence is unnecessary, Intel CPU's are cache coherent, please read > the virtio Linux ring header file for explanation. A full fence WMB > is more expensive and causes CPU stall > I mean virtio_wmb rather than virtio_rmb should be used here, and both of them are defined as compiler barrier. The following code is linux virtio driver for adding buffer to vring. /* Put entry in available array (but don't update avail->idx until they * do sync). */ avail = (vq->vring.avail->idx & (vq->vring.num-1)); vq->vring.avail->ring[avail] = head; /* Descriptors and available array need to be set before we expose the * new available array entries. */ virtio_wmb(vq->weak_barriers); vq->vring.avail->idx++; > > > vq->vq_ring.avail->idx = vq->vq_avail_idx; > > > } > > > > > > @@ -255,7 +264,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. > > > */ > > > -- > > > 1.8.4.2 > > ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 16:16 ` Xie, Huawei @ 2015-01-28 6:12 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-01-28 6:12 UTC (permalink / raw) To: Xie, Huawei, Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Xie, Huawei > Sent: Wednesday, January 28, 2015 12:16 AM > To: Stephen Hemminger > Cc: Ouyang, Changchun; dev@dpdk.org > Subject: RE: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers > > > > > -----Original Message----- > > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > > Sent: Tuesday, January 27, 2015 5:59 PM > > To: Xie, Huawei > > Cc: Ouyang, Changchun; dev@dpdk.org > > Subject: Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers > > > > > > > I recall our original code is virtio_wmb(). > > > Use store fence to ensure all updates to entries before updating the > index. > > > Why do we need virtio_rmb() here and add virtio_wmb after > > vq_update_avail_idx()? > > > > Store fence is unnecessary, Intel CPU's are cache coherent, please > > read the virtio Linux ring header file for explanation. A full fence > > WMB is more expensive and causes CPU stall > > > > > I mean virtio_wmb rather than virtio_rmb should be used here, and both of > them are defined as compiler barrier. > > The following code is linux virtio driver for adding buffer to vring. > /* Put entry in available array (but don't update avail->idx until they > * do sync). */ > avail = (vq->vring.avail->idx & (vq->vring.num-1)); > vq->vring.avail->ring[avail] = head; > > /* Descriptors and available array need to be set before we expose > the > * new available array entries. */ > virtio_wmb(vq->weak_barriers); > vq->vring.avail->idx++; > Yes, use virtio_wmb is better here, will change it in next version. Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers Ouyang Changchun 2015-01-27 7:03 ` Xie, Huawei @ 2015-01-27 7:56 ` Xie, Huawei 2015-01-27 8:04 ` Ouyang, Changchun 1 sibling, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-01-27 7:56 UTC (permalink / raw) To: Ouyang, Changchun, dev >-------if (likely(nb_enqueued)) { >------->-------virtio_wmb(); >------->-------if (unlikely(virtqueue_kick_prepare(rxvq))) { >------->------->-------virtqueue_notify(rxvq); >------->------->-------PMD_RX_LOG(DEBUG, "Notified\n"); >------->-------} >-------} >-------vq_update_avail_idx(rxvq); Two confuses for the modification here: 1. why notify host without updating avail idx? Will this cause potential deadlock? 2. Why update avail index even no packets are enqueued? ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers 2015-01-27 7:56 ` Xie, Huawei @ 2015-01-27 8:04 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-01-27 8:04 UTC (permalink / raw) To: Stephen Hemminger (stephen@networkplumber.org), Xie, Huawei, dev Hi Stephen, Although it is original code logic, But we can move vq_update_avail_idx(rxvq) into if block to resolve it. What do you think of it? Thanks Changchun -----Original Message----- From: Xie, Huawei Sent: Tuesday, January 27, 2015 3:57 PM To: Ouyang, Changchun; dev@dpdk.org Cc: Stephen Hemminger (stephen@networkplumber.org) Subject: RE: [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers >-------if (likely(nb_enqueued)) { >------->-------virtio_wmb(); >------->-------if (unlikely(virtqueue_kick_prepare(rxvq))) { >------->------->-------virtqueue_notify(rxvq); >------->------->-------PMD_RX_LOG(DEBUG, "Notified\n"); >------->-------} >-------} >-------vq_update_avail_idx(rxvq); Two confuses for the modification here: 1. why notify host without updating avail idx? Will this cause potential deadlock? 2. Why update avail index even no packets are enqueued? ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 03/24] virtio: Allow starting with link down 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 01/24] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt Ouyang Changchun ` (22 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Starting driver with link down should be ok, it is with every other driver. So just allow it. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index dc47e72..5df3b54 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1057,14 +1057,12 @@ virtio_dev_start(struct rte_eth_dev *dev) vtpci_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); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (2 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 03/24] virtio: Allow starting with link down Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 9:04 ` Xie, Huawei 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 05/24] ether: Add soft vlan encap/decap functions Ouyang Changchun ` (21 subsequent siblings) 25 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Virtio has link state interrupt which can be used. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 5df3b54..ef87ff8 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) #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. */ @@ -968,6 +996,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, PMD_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; } @@ -975,7 +1007,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), @@ -1021,6 +1053,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"); @@ -1029,7 +1064,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return (-EINVAL); } - return 0; + ret = vtpci_irq_config(hw, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, "failed to set config vector"); + + return ret; } @@ -1037,7 +1076,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); @@ -1052,18 +1090,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 @@ -1145,6 +1187,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); } @@ -1161,6 +1204,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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, @@ -1179,10 +1223,8 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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 diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index ca9c748..6d51032 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uint8_t status) VIRTIO_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; +} diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 373f9dc..6998737 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void 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_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt Ouyang Changchun @ 2015-01-27 9:04 ` Xie, Huawei 2015-01-27 10:00 ` Stephen Hemminger 0 siblings, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-01-27 9:04 UTC (permalink / raw) To: Ouyang, Changchun, dev > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ouyang Changchun > Sent: Tuesday, January 27, 2015 10:36 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt > > Virtio has link state interrupt which can be used. > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > --- > 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(-) > > diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c > b/lib/librte_pmd_virtio/virtio_ethdev.c > index 5df3b54..ef87ff8 100644 > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device > *pci_dev __rte_unused) > #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"); > + Is it better to put rte_intr_enable after we have handled the interrupt. Is there the possibility of interrupt reentrant in uio intr framework? > + 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); > + } > + > +} > + > ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt 2015-01-27 9:04 ` Xie, Huawei @ 2015-01-27 10:00 ` Stephen Hemminger 2015-01-28 3:03 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-01-27 10:00 UTC (permalink / raw) To: Xie, Huawei; +Cc: dev On Tue, 27 Jan 2015 09:04:07 +0000 "Xie, Huawei" <huawei.xie@intel.com> wrote: > > -----Original Message----- > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ouyang Changchun > > Sent: Tuesday, January 27, 2015 10:36 AM > > To: dev@dpdk.org > > Subject: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt > > > > Virtio has link state interrupt which can be used. > > > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > --- > > 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(-) > > > > diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c > > b/lib/librte_pmd_virtio/virtio_ethdev.c > > index 5df3b54..ef87ff8 100644 > > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > > @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device > > *pci_dev __rte_unused) > > #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"); > > + > > Is it better to put rte_intr_enable after we have handled the interrupt. > Is there the possibility of interrupt reentrant in uio intr framework? The UIO framework handles IRQ's via posix thread that is reading fd, then calling this code. Therefore it is always single threaded. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt 2015-01-27 10:00 ` Stephen Hemminger @ 2015-01-28 3:03 ` Ouyang, Changchun 2015-01-28 15:11 ` Stephen Hemminger 0 siblings, 1 reply; 132+ messages in thread From: Ouyang, Changchun @ 2015-01-28 3:03 UTC (permalink / raw) To: Stephen Hemminger, Xie, Huawei; +Cc: dev Hi Stephen, > -----Original Message----- > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Tuesday, January 27, 2015 6:00 PM > To: Xie, Huawei > Cc: Ouyang, Changchun; dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State > interrupt > > On Tue, 27 Jan 2015 09:04:07 +0000 > "Xie, Huawei" <huawei.xie@intel.com> wrote: > > > > -----Original Message----- > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ouyang > > > Changchun > > > Sent: Tuesday, January 27, 2015 10:36 AM > > > To: dev@dpdk.org > > > Subject: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link > > > State interrupt > > > > > > Virtio has link state interrupt which can be used. > > > > > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > > --- > > > 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(-) > > > > > > diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c > > > b/lib/librte_pmd_virtio/virtio_ethdev.c > > > index 5df3b54..ef87ff8 100644 > > > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > > > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > > > @@ -845,6 +845,34 @@ static int virtio_resource_init(struct > > > rte_pci_device *pci_dev __rte_unused) #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"); > > > + > > > > Is it better to put rte_intr_enable after we have handled the interrupt. > > Is there the possibility of interrupt reentrant in uio intr framework? > > The UIO framework handles IRQ's via posix thread that is reading fd, then > calling this code. Therefore it is always single threaded. Even if it is under UIO framework, and always single threaded, How about move rte_intr_enable after the virtio_dev_link_update() and _rte_eth_dev_callback_process is called. This make it more like interrupt handler in linux kernel. What do you think of it? Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt 2015-01-28 3:03 ` Ouyang, Changchun @ 2015-01-28 15:11 ` Stephen Hemminger 0 siblings, 0 replies; 132+ messages in thread From: Stephen Hemminger @ 2015-01-28 15:11 UTC (permalink / raw) To: Ouyang, Changchun; +Cc: dev On Wed, 28 Jan 2015 03:03:32 +0000 "Ouyang, Changchun" <changchun.ouyang@intel.com> wrote: > Hi Stephen, > > > -----Original Message----- > > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > > Sent: Tuesday, January 27, 2015 6:00 PM > > To: Xie, Huawei > > Cc: Ouyang, Changchun; dev@dpdk.org > > Subject: Re: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State > > interrupt > > > > On Tue, 27 Jan 2015 09:04:07 +0000 > > "Xie, Huawei" <huawei.xie@intel.com> wrote: > > > > > > -----Original Message----- > > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ouyang > > > > Changchun > > > > Sent: Tuesday, January 27, 2015 10:36 AM > > > > To: dev@dpdk.org > > > > Subject: [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link > > > > State interrupt > > > > > > > > Virtio has link state interrupt which can be used. > > > > > > > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > > > --- > > > > 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(-) > > > > > > > > diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c > > > > b/lib/librte_pmd_virtio/virtio_ethdev.c > > > > index 5df3b54..ef87ff8 100644 > > > > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > > > > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > > > > @@ -845,6 +845,34 @@ static int virtio_resource_init(struct > > > > rte_pci_device *pci_dev __rte_unused) #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"); > > > > + > > > > > > Is it better to put rte_intr_enable after we have handled the interrupt. > > > Is there the possibility of interrupt reentrant in uio intr framework? > > > > The UIO framework handles IRQ's via posix thread that is reading fd, then > > calling this code. Therefore it is always single threaded. > > Even if it is under UIO framework, and always single threaded, > How about move rte_intr_enable after the virtio_dev_link_update() and _rte_eth_dev_callback_process is called. > This make it more like interrupt handler in linux kernel. > What do you think of it? I ordered the interrupt handling to match what happens in e1000/igb handler. My concern is that interrupt was level (not edge triggered) and another link transisition could occur and be missed. ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 05/24] ether: Add soft vlan encap/decap functions 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (3 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 06/24] virtio: Use software vlan stripping Ouyang Changchun ` (20 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev It is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software. This allows application to be device independent. Avoid discarding shared mbufs. Make a copy in rte_vlan_insert() of any packet to be tagged that has a reference count > 1. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 7e7d22c..74f71c2 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -49,6 +49,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. */ @@ -333,6 +335,80 @@ struct vxlan_hdr { #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) /**< VXLAN tunnel header length. */ +/** + * 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->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_REFCNT + /* Can't insert header if mbuf is shared */ + if (rte_mbuf_refcnt_read(*m) > 1) { + struct rte_mbuf *copy; + + copy = rte_pktmbuf_clone(*m, (*m)->pool); + if (unlikely(copy == NULL)) + return -ENOMEM; + rte_pktmbuf_free(*m); + *m = copy; + } +#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)->vlan_tci); + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 06/24] virtio: Use software vlan stripping 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (4 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 05/24] ether: Add soft vlan encap/decap functions Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 07/24] virtio: Remove unnecessary adapter structure Ouyang Changchun ` (19 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Implement VLAN stripping in software. This allows application to be device independent. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 3 +++ lib/librte_pmd_virtio/virtio_ethdev.c | 2 ++ lib/librte_pmd_virtio/virtio_pci.h | 1 + lib/librte_pmd_virtio/virtio_rxtx.c | 20 ++++++++++++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 1200c1c..94d6b2b 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -643,6 +643,9 @@ struct rte_eth_rxconf { #define ETH_TXQ_FLAGS_NOOFFLOADS \ (ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | \ ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) +#define ETH_TXQ_FLAGS_NOXSUMS \ + (ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ + ETH_TXQ_FLAGS_NOXSUMTCP) /** * A structure used to configure a TX ring of an Ethernet port. */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index ef87ff8..da74659 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1064,6 +1064,8 @@ virtio_dev_configure(struct rte_eth_dev *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"); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6998737..6d93fac 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -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]; }; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 78af334..e0216ec 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -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" @@ -408,8 +409,8 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, 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; } @@ -446,6 +447,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]; @@ -489,6 +491,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->pkt_len = (uint32_t)(len[i] - hdr_size); rxm->data_len = (uint16_t)(len[i] - hdr_size); + if (hw->vlan_strip) + rte_vlan_strip(rxm); + VIRTIO_DUMP_PACKET(rxm, rxm->data_len); rx_pkts[nb_rx++] = rxm; @@ -717,6 +722,17 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) */ if (likely(need <= 0)) { 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)) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 07/24] virtio: Remove unnecessary adapter structure 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (5 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 06/24] virtio: Use software vlan stripping Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 08/24] virtio: Remove redundant vq_alignment Ouyang Changchun ` (18 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Cleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure. Also allows removing unneeded macro, making code clearer. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 43 ++++++++++++----------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 -------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index da74659..59b74b7 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -207,8 +207,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, static 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; @@ -242,8 +241,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, const 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 */ @@ -383,8 +381,7 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, struct 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, @@ -410,8 +407,7 @@ virtio_dev_close(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -430,8 +426,7 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -450,8 +445,7 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -470,8 +464,7 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -853,8 +846,7 @@ 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); + struct virtio_hw *hw = dev->data->dev_private; uint8_t isr; /* Read interrupt status which clears interrupt */ @@ -880,12 +872,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, @@ -1010,7 +1001,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), }; /* @@ -1053,8 +1044,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"); @@ -1078,8 +1068,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); @@ -1185,8 +1174,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) static 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); @@ -1199,8 +1187,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet { 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; @@ -1232,7 +1219,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet static 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; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 1da3c62..55c9749 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -110,15 +110,6 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_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 diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index e0216ec..a82d5ff 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -326,8 +326,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) void 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; if (hw->cvq) { virtio_dev_vring_start(hw->cvq, VTNET_CQ); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 08/24] virtio: Remove redundant vq_alignment 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (6 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 07/24] virtio: Remove unnecessary adapter structure Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 09/24] virtio: Fix how states are handled during initialization Ouyang Changchun ` (17 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Since vq_alignment is constant (always 4K), it does not need to be part of the vring struct. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 59b74b7..0d41e7f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -294,7 +294,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, 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; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82d5ff..b6d6832 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) * 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; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index f6ad98d..5b8a255 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -138,8 +138,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 */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 09/24] virtio: Fix how states are handled during initialization 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (7 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 08/24] virtio: Remove redundant vq_alignment Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 10/24] virtio: Make vtpci_get_status local Ouyang Changchun ` (16 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Change order of initialiazation to match Linux kernel. Don't blow away control queue by doing reset when stopped. Calling dev_stop then dev_start would not work. Dev_stop was calling virtio reset and that would clear all queues and clear all feature negotiation. Resolved by only doing reset on device removal. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 58 ++++++++++++++++++++--------------- lib/librte_pmd_virtio/virtio_pci.c | 10 ++---- lib/librte_pmd_virtio/virtio_pci.h | 3 +- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0d41e7f..47dd33d 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -398,9 +398,14 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, static void virtio_dev_close(struct rte_eth_dev *dev) { + struct virtio_hw *hw = dev->data->dev_private; + PMD_INIT_LOG(DEBUG, "virtio_dev_close"); - virtio_dev_stop(dev); + /* reset the NIC */ + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + vtpci_reset(hw); + virtio_dev_free_mbufs(dev); } static void @@ -889,6 +894,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (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; @@ -899,9 +907,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -990,6 +995,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* Setup interrupt callback */ rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); + + virtio_dev_cq_start(eth_dev); + return 0; } @@ -1044,7 +1052,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; - int ret; PMD_INIT_LOG(DEBUG, "configure"); @@ -1055,11 +1062,12 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; - ret = vtpci_irq_config(hw, 0); - if (ret != 0) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } - return ret; + return 0; } @@ -1069,17 +1077,6 @@ 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); - /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { @@ -1096,8 +1093,16 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Initialize Link state */ virtio_dev_link_update(dev, 0); + /* On restart after stop do not touch queues */ + if (hw->started) + return 0; + vtpci_reinit_complete(hw); + /* Do final configuration before rx/tx engine starts */ + virtio_dev_rxtx_start(dev); + hw->started = 1; + /*Notify the backend *Otherwise the tap backend might already stop its queue due to fullness. *vhost backend will have no chance to be waked up @@ -1168,17 +1173,20 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) } /* - * Stop device: disable rx and tx functions to allow for reconfiguring. + * Stop device: disable interrupt and mark link down */ static void virtio_dev_stop(struct rte_eth_dev *dev) { - struct virtio_hw *hw = dev->data->dev_private; + struct rte_eth_link link; - /* reset the NIC */ - vtpci_irq_config(hw, 0); - vtpci_reset(hw); - virtio_dev_free_mbufs(dev); + PMD_INIT_LOG(DEBUG, "stop"); + + if (dev->data->dev_conf.intr_conf.lsc) + rte_intr_disable(&dev->pci_dev->intr_handle); + + memset(&link, 0, sizeof(link)); + virtio_dev_atomic_write_link_status(dev, &link); } static int diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index 6d51032..b099e4f 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -137,15 +137,9 @@ vtpci_isr(struct virtio_hw *hw) /* Enable one vector (0) for Link State Intrerrupt */ -int +uint16_t 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; + return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); } diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6d93fac..0a4b578 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -170,6 +170,7 @@ struct virtio_hw { uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; + uint8_t started; uint8_t mac_addr[ETHER_ADDR_LEN]; }; @@ -266,6 +267,6 @@ void 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); +uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); #endif /* _VIRTIO_PCI_H_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 10/24] virtio: Make vtpci_get_status local 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (8 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 09/24] virtio: Fix how states are handled during initialization Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 11/24] virtio: Check for packet headroom at compile time Ouyang Changchun ` (15 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Make vtpci_get_status a local function as it is used in one file. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_pci.c | 4 +++- lib/librte_pmd_virtio/virtio_pci.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index b099e4f..2245bec 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -35,6 +35,8 @@ #include "virtio_pci.h" #include "virtio_logs.h" +static uint8_t vtpci_get_status(struct virtio_hw *); + void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -113,7 +115,7 @@ vtpci_reinit_complete(struct virtio_hw *hw) vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); } -uint8_t +static uint8_t vtpci_get_status(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 0a4b578..64d9c34 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -255,8 +255,6 @@ void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); -uint8_t vtpci_get_status(struct virtio_hw *); - void vtpci_set_status(struct virtio_hw *, uint8_t); uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 11/24] virtio: Check for packet headroom at compile time 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (9 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 10/24] virtio: Make vtpci_get_status local Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 12/24] virtio: Move allocation before initialization Ouyang Changchun ` (14 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Better to check at compile time than fail at runtime. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 47dd33d..9679c2f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -882,11 +882,7 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; - if (RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)) { - PMD_INIT_LOG(ERR, - "MBUF HEADROOM should be enough to hold virtio net hdr\n"); - return -1; - } + RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); eth_dev->dev_ops = &virtio_eth_dev_ops; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 12/24] virtio: Move allocation before initialization 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (10 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 11/24] virtio: Check for packet headroom at compile time Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 13/24] virtio: Add support for vlan filtering Ouyang Changchun ` (13 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev If allocation fails, don't want to leave virtio device stuck in middle of initialization sequence. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 9679c2f..39b1fb4 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -890,6 +890,15 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %d bytes needed to store MAC addresses", + ETHER_ADDR_LEN); + return -ENOMEM; + } + /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); @@ -916,15 +925,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr); } - /* Allocate memory for storing MAC addresses */ - eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); - if (eth_dev->data->mac_addrs == NULL) { - PMD_INIT_LOG(ERR, - "Failed to allocate %d bytes needed to store MAC addresses", - ETHER_ADDR_LEN); - return -ENOMEM; - } - /* Copy the permanent MAC address to: virtio_hw */ virtio_get_hwaddr(hw); ether_addr_copy((struct ether_addr *) hw->mac_addr, -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 13/24] virtio: Add support for vlan filtering 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (11 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 12/24] virtio: Move allocation before initialization Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 14/24] virtio: Add suport for multiple mac addresses Ouyang Changchun ` (12 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Virtio supports vlan filtering. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 39b1fb4..591d692 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -84,6 +84,8 @@ static void virtio_dev_tx_queue_release(__rte_unused void *txq); 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); +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, + uint16_t vlan_id, int on); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -511,6 +513,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, + .vlan_filter_set = virtio_vlan_filter_set, }; static inline int @@ -640,14 +643,31 @@ virtio_get_hwaddr(struct virtio_hw *hw) } } +static int +virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtio_pmd_ctrl ctrl; + int len; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) + return -ENOTSUP; + + ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN; + ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; + memcpy(ctrl.data, &vlan_id, sizeof(vlan_id)); + len = sizeof(vlan_id); + + return virtio_send_command(hw->cvq, &ctrl, &len, 1); +} static void virtio_negotiate_features(struct virtio_hw *hw) { uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_VLAN; - mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; + /* checksum offload not implemented */ + mask = VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding * checksum offload feature is also negotiated. @@ -1058,6 +1078,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; + if (rxmode->hw_vlan_filter + && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { + PMD_DRV_LOG(NOTICE, + "vlan filtering not available on this host"); + return -ENOTSUP; + } + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); return -EBUSY; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 14/24] virtio: Add suport for multiple mac addresses 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (12 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 13/24] virtio: Add support for vlan filtering Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 15/24] virtio: Add ability to set MAC address Ouyang Changchun ` (11 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Virtio support multiple MAC addresses. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 94 ++++++++++++++++++++++++++++++++++- lib/librte_pmd_virtio/virtio_ethdev.h | 3 +- lib/librte_pmd_virtio/virtqueue.h | 34 ++++++++++++- 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 591d692..0e74eea 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -86,6 +86,10 @@ static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); +static void virtio_mac_addr_add(struct rte_eth_dev *dev, + struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused); +static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -503,8 +507,6 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .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, /* meaningfull only to multiple queue */ .rx_queue_release = virtio_dev_rx_queue_release, @@ -514,6 +516,8 @@ static struct eth_dev_ops virtio_eth_dev_ops = { /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, .vlan_filter_set = virtio_vlan_filter_set, + .mac_addr_add = virtio_mac_addr_add, + .mac_addr_remove = virtio_mac_addr_remove, }; static inline int @@ -644,6 +648,92 @@ virtio_get_hwaddr(struct virtio_hw *hw) } static int +virtio_mac_table_set(struct virtio_hw *hw, + const struct virtio_net_ctrl_mac *uc, + const struct virtio_net_ctrl_mac *mc) +{ + struct virtio_pmd_ctrl ctrl; + int err, len[2]; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET; + + len[0] = uc->entries * ETHER_ADDR_LEN + sizeof(uc->entries); + memcpy(ctrl.data, uc, len[0]); + + len[1] = mc->entries * ETHER_ADDR_LEN + sizeof(mc->entries); + memcpy(ctrl.data + len[0], mc, len[1]); + + err = virtio_send_command(hw->cvq, &ctrl, len, 2); + if (err != 0) + PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err); + + return err; +} + +static void +virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused) +{ + struct virtio_hw *hw = dev->data->dev_private; + const struct ether_addr *addrs = dev->data->mac_addrs; + unsigned int i; + struct virtio_net_ctrl_mac *uc, *mc; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + const struct ether_addr *addr + = (i == index) ? mac_addr : addrs + i; + struct virtio_net_ctrl_mac *tbl + = is_multicast_ether_addr(addr) ? mc : uc; + + memcpy(&tbl->macs[tbl->entries++], addr, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static void +virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct ether_addr *addrs = dev->data->mac_addrs; + struct virtio_net_ctrl_mac *uc, *mc; + unsigned int i; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + struct virtio_net_ctrl_mac *tbl; + + if (i == index || is_zero_ether_addr(addrs + i)) + continue; + + tbl = is_multicast_ether_addr(addrs + i) ? mc : uc; + memcpy(&tbl->macs[tbl->entries++], addrs + i, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct virtio_hw *hw = dev->data->dev_private; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 55c9749..74ac7e0 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -51,7 +51,7 @@ #define VIRTIO_MAX_RX_QUEUES 128 #define VIRTIO_MAX_TX_QUEUES 128 -#define VIRTIO_MAX_MAC_ADDRS 1 +#define VIRTIO_MAX_MAC_ADDRS 64 #define VIRTIO_MIN_RX_BUFSIZE 64 #define VIRTIO_MAX_RX_PKTLEN 9728 @@ -60,6 +60,7 @@ (VIRTIO_NET_F_MAC | \ VIRTIO_NET_F_STATUS | \ VIRTIO_NET_F_MQ | \ + VIRTIO_NET_F_CTRL_MAC_ADDR | \ VIRTIO_NET_F_CTRL_VQ | \ VIRTIO_NET_F_CTRL_RX | \ VIRTIO_NET_F_CTRL_VLAN | \ diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 5b8a255..d210f4f 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -99,6 +99,34 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; #define VIRTIO_NET_CTRL_RX_NOBCAST 5 /** + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + uint32_t entries; + uint8_t macs[][ETHER_ADDR_LEN]; +} __attribute__((__packed__)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/** * Control VLAN filtering * * The VLAN filter table is controlled via a simple ADD/DEL interface. @@ -121,7 +149,7 @@ typedef uint8_t virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_MAX_CTRL_DATA 128 +#define VIRTIO_MAX_CTRL_DATA 2048 struct virtio_pmd_ctrl { struct virtio_net_ctrl_hdr hdr; @@ -180,6 +208,10 @@ struct virtqueue { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 #endif +#ifndef VIRTIO_NET_F_CTRL_MAC_ADDR +#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 +#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 +#endif /** * This is the first element of the scatter-gather list. If you don't -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 15/24] virtio: Add ability to set MAC address 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (13 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 14/24] virtio: Add suport for multiple mac addresses Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 16/24] virtio: Free mbuf's with threshold Ouyang Changchun ` (10 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Need to have do special things to set default mac address. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 5 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 94d6b2b..5a54276 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1240,6 +1240,10 @@ typedef void (*eth_mac_addr_add_t)(struct rte_eth_dev *dev, uint32_t vmdq); /**< @internal Set a MAC address into Receive Address Address Register */ +typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); +/**< @internal Set a MAC address into Receive Address Address Register */ + typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint8_t on); @@ -1459,6 +1463,7 @@ struct eth_dev_ops { priority_flow_ctrl_set_t priority_flow_ctrl_set; /**< Setup priority flow control.*/ eth_mac_addr_remove_t mac_addr_remove; /**< Remove MAC address */ eth_mac_addr_add_t mac_addr_add; /**< Add a MAC address */ + eth_mac_addr_set_t mac_addr_set; /**< Set a MAC address */ eth_uc_hash_table_set_t uc_hash_table_set; /**< Set Unicast Table Array */ eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */ eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0e74eea..b30ab2a 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -90,6 +90,8 @@ static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused); static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); +static void virtio_mac_addr_set(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -518,6 +520,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .vlan_filter_set = virtio_vlan_filter_set, .mac_addr_add = virtio_mac_addr_add, .mac_addr_remove = virtio_mac_addr_remove, + .mac_addr_set = virtio_mac_addr_set, }; static inline int @@ -733,6 +736,27 @@ virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) virtio_mac_table_set(hw, uc, mc); } +static void +virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) +{ + struct virtio_hw *hw = dev->data->dev_private; + + memcpy(hw->mac_addr, mac_addr, ETHER_ADDR_LEN); + + /* Use atomic update if available */ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { + struct virtio_pmd_ctrl ctrl; + int len = ETHER_ADDR_LEN; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; + + memcpy(ctrl.data, mac_addr, ETHER_ADDR_LEN); + virtio_send_command(hw->cvq, &ctrl, &len, 1); + } else if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) + virtio_set_hwaddr(hw); +} + static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 16/24] virtio: Free mbuf's with threshold 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (14 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 15/24] virtio: Add ability to set MAC address Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 17/24] virtio: Use port IO to get PCI resource Ouyang Changchun ` (9 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev This makes virtio driver work like ixgbe. Transmit buffers are held until a transmit threshold is reached. The previous behavior was to hold mbuf's until the ring entry was reused which caused more memory usage than needed. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 7 ++-- lib/librte_pmd_virtio/virtio_rxtx.c | 75 +++++++++++++++++++++++++---------- lib/librte_pmd_virtio/virtqueue.h | 3 +- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b30ab2a..8cd2d51 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -176,15 +176,16 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, virtqueue_notify(vq); - while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) + rte_rmb(); + while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { + rte_rmb(); usleep(100); + } while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; - virtio_rmb(); - used_idx = (uint32_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index b6d6832..580701a 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -129,17 +129,32 @@ virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, return i; } +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif + +/* Cleanup from completed transmits. */ static void -virtqueue_dequeue_pkt_tx(struct virtqueue *vq) +virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) { - struct vring_used_elem *uep; - uint16_t used_idx, desc_idx; + uint16_t i, used_idx, desc_idx; + for (i = 0; i < num; i++) { + struct vring_used_elem *uep; + struct vq_desc_extra *dxp; + + used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); + uep = &vq->vq_ring.used->ring[used_idx]; + dxp = &vq->vq_descx[used_idx]; + + desc_idx = (uint16_t) uep->id; + vq->vq_used_cons_idx++; + vq_ring_free_chain(vq, desc_idx); - used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); - uep = &vq->vq_ring.used->ring[used_idx]; - desc_idx = (uint16_t) uep->id; - vq->vq_used_cons_idx++; - vq_ring_free_chain(vq, desc_idx); + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } } @@ -203,8 +218,6 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) idx = head_idx; dxp = &txvq->vq_descx[idx]; - if (dxp->cookie != NULL) - rte_pktmbuf_free(dxp->cookie); dxp->cookie = (void *)cookie; dxp->ndescs = needed; @@ -404,6 +417,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; struct virtqueue *vq; + uint16_t tx_free_thresh; int ret; PMD_INIT_FUNC_TRACE(); @@ -421,6 +435,22 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, return ret; } + tx_free_thresh = tx_conf->tx_free_thresh; + if (tx_free_thresh == 0) + tx_free_thresh = + RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH); + + if (tx_free_thresh >= (vq->vq_nentries - 3)) { + RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the " + "number of TX entries minus 3 (%u)." + " (tx_free_thresh=%u port=%u queue=%u)\n", + vq->vq_nentries - 3, + tx_free_thresh, dev->data->port_id, queue_idx); + return -EINVAL; + } + + vq->vq_free_thresh = tx_free_thresh; + dev->data->tx_queues[queue_idx] = vq; return 0; } @@ -688,11 +718,9 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; - uint16_t nb_used, nb_tx, num; + uint16_t nb_used, nb_tx; int error; - nb_tx = 0; - if (unlikely(nb_pkts < 1)) return nb_pkts; @@ -700,21 +728,26 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); + if (likely(nb_used > txvq->vq_free_thresh)) + virtio_xmit_cleanup(txvq, nb_used); - num = (uint16_t)(likely(nb_used < VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ); + nb_tx = 0; while (nb_tx < nb_pkts) { /* Need one more descriptor for virtio header. */ int need = tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; - int deq_cnt = RTE_MIN(need, (int)num); - num -= (deq_cnt > 0) ? deq_cnt : 0; - while (deq_cnt > 0) { - virtqueue_dequeue_pkt_tx(txvq); - deq_cnt--; + /*Positive value indicates it need free vring descriptors */ + if (unlikely(need > 0)) { + nb_used = VIRTQUEUE_NUSED(txvq); + virtio_rmb(); + need = RTE_MIN(need, (int)nb_used); + + virtio_xmit_cleanup(txvq, need); + need = (int)tx_pkts[nb_tx]->nb_segs - + txvq->vq_free_cnt + 1; } - need = (int)tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; /* * Zero or negative value indicates it has enough free * descriptors to use for transmitting. @@ -723,7 +756,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) txm = tx_pkts[nb_tx]; /* Do VLAN tag insertion */ - if (txm->ol_flags & PKT_TX_VLAN_PKT) { + if (unlikely(txm->ol_flags & PKT_TX_VLAN_PKT)) { error = rte_vlan_insert(&txm); if (unlikely(error)) { rte_pktmbuf_free(txm); diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index d210f4f..6c45c27 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -164,6 +164,7 @@ struct virtqueue { struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint8_t port_id; /**< Device port identifier. */ + uint16_t vq_queue_index; /**< PCI queue index */ void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; @@ -172,7 +173,7 @@ struct virtqueue { struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_nentries; /**< vring desc numbers */ - uint16_t vq_queue_index; /**< PCI queue index */ + uint16_t vq_free_thresh; /**< free threshold */ /** * Head of the free chain in the descriptor table. If * there are no free descriptors, this will be set to -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 17/24] virtio: Use port IO to get PCI resource. 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (15 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 16/24] virtio: Free mbuf's with threshold Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 18/24] virtio: Fix descriptor index issue Ouyang Changchun ` (8 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- config/common_linuxapp | 2 + lib/librte_eal/common/include/rte_pci.h | 4 ++ lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_pmd_virtio/virtio_ethdev.c | 91 ++++++++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/config/common_linuxapp b/config/common_linuxapp index 2f9643b..a412457 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -100,6 +100,8 @@ CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n CONFIG_RTE_EAL_IGB_UIO=y CONFIG_RTE_EAL_VFIO=y +# Only for VIRTIO PMD currently +CONFIG_RTE_EAL_PORT_IO=n # # Special configurations in PCI Config Space for high performance diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..19abc1f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -193,6 +193,10 @@ struct rte_pci_driver { /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */ #define RTE_PCI_DRV_NEED_MAPPING 0x0001 +/** Device needs port IO(done with /proc/ioports) */ +#ifdef RTE_EAL_PORT_IO +#define RTE_PCI_DRV_PORT_IO 0x0002 +#endif /** Device driver must be registered several times until failure - deprecated */ #pragma GCC poison RTE_PCI_DRV_MULTIPLE /** Device needs to be unbound even if no module is provided */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..5db0059 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -574,7 +574,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d /* map resources for devices that use igb_uio */ ret = pci_map_device(dev); if (ret != 0) - return ret; +#ifdef RTE_EAL_PORT_IO + if ((dr->drv_flags & RTE_PCI_DRV_PORT_IO) == 0) +#endif + return ret; } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && rte_eal_process_type() == RTE_PROC_PRIMARY) { /* unbind current driver */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 8cd2d51..b905532 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -961,6 +961,71 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) start, size); return 0; } + +#ifdef RTE_EAL_PORT_IO +/* Extract port I/O numbers from proc/ioports */ +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_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; +} +#endif + #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -974,6 +1039,14 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) /* no setup required */ return 0; } + +#ifdef RTE_EAL_PORT_IO +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + /* no setup required */ + return 0; +} +#endif #endif /* @@ -1039,7 +1112,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev = eth_dev->pci_dev; if (virtio_resource_init(pci_dev) < 0) - return -1; +#ifdef RTE_EAL_PORT_IO + if (virtio_resource_init_by_portio(pci_dev) < 0) +#endif + return -1; hw->use_msix = virtio_has_msix(&pci_dev->addr); hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; @@ -1132,6 +1208,18 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 0; } +#ifdef RTE_EAL_PORT_IO +static struct eth_driver rte_virtio_pmd = { + { + .name = "rte_virtio_pmd", + .id_table = pci_id_virtio_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_PORT_IO | + RTE_PCI_DRV_INTR_LSC, + }, + .eth_dev_init = eth_virtio_dev_init, + .dev_private_size = sizeof(struct virtio_hw), +}; +#else static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", @@ -1141,6 +1229,7 @@ static struct eth_driver rte_virtio_pmd = { .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_hw), }; +#endif /* * Driver initialization routine. -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 18/24] virtio: Fix descriptor index issue 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (16 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 17/24] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 19/24] ether: Fix vlan strip/insert issue Ouyang Changchun ` (7 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev It should use vring descriptor index instead of used_ring index to index vq_descx. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 580701a..a82e8eb 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; - dxp = &vq->vq_descx[used_idx]; desc_idx = (uint16_t) uep->id; + dxp = &vq->vq_descx[desc_idx]; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 19/24] ether: Fix vlan strip/insert issue 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (17 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 18/24] virtio: Fix descriptor index issue Ouyang Changchun @ 2015-01-27 2:35 ` Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 20/24] example/vhost: Avoid inserting vlan twice Ouyang Changchun ` (6 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:35 UTC (permalink / raw) To: dev Need swap the data from cpu to BE(big endian) for vlan-type. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 74f71c2..0797908 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -351,7 +351,7 @@ 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) + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) return -1; struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); @@ -401,7 +401,7 @@ static inline int rte_vlan_insert(struct rte_mbuf **m) return -ENOSPC; memmove(nh, oh, 2 * ETHER_ADDR_LEN); - nh->ether_type = ETHER_TYPE_VLAN; + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vh = (struct vlan_hdr *) (nh + 1); vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 20/24] example/vhost: Avoid inserting vlan twice 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (18 preceding siblings ...) 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 19/24] ether: Fix vlan strip/insert issue Ouyang Changchun @ 2015-01-27 2:36 ` Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 21/24] example/vhost: Add vlan-strip cmd line option Ouyang Changchun ` (5 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:36 UTC (permalink / raw) To: dev Check if it has already been vlan-tagged packet, if true, avoid inserting a duplicated vlan tag into it. This is a possible case when guest has the capability of inserting vlan tag. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 04f0118..1d31520 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -1115,6 +1115,7 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) unsigned len, ret, offset = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; + struct ether_hdr *nh; /*check if destination is local VM*/ if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) { @@ -1135,7 +1136,15 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; - m->ol_flags = PKT_TX_VLAN_PKT; + nh = rte_pktmbuf_mtod(m, struct ether_hdr *); + if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) { + /* Guest has inserted the vlan tag. */ + struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1); + uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag); + if (vh->vlan_tci != vlan_tag_be) + vh->vlan_tci = vlan_tag_be; + } else { + m->ol_flags = PKT_TX_VLAN_PKT; /* * Find the right seg to adjust the data len when offset is @@ -1156,7 +1165,8 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) m->pkt_len += offset; } - m->vlan_tci = vlan_tag; + m->vlan_tci = vlan_tag; + } tx_q->m_table[len] = m; len++; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 21/24] example/vhost: Add vlan-strip cmd line option 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (19 preceding siblings ...) 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 20/24] example/vhost: Avoid inserting vlan twice Ouyang Changchun @ 2015-01-27 2:36 ` Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 22/24] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun ` (4 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:36 UTC (permalink / raw) To: dev Support turn on/off RX VLAN strip on host, this let guest get the chance of using its software VALN strip functionality. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 1d31520..4ff916d 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -159,6 +159,9 @@ static uint32_t num_devices; static uint32_t zero_copy; static int mergeable; +/* Do vlan strip on host, enabled on default */ +static uint32_t vlan_strip = 1; + /* number of descriptors to apply*/ static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP; static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP; @@ -564,6 +567,7 @@ us_vhost_usage(const char *prgname) " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n" " --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n" + " --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n" " --zero-copy [0|1]: disable(default)/enable rx/tx " @@ -591,6 +595,7 @@ us_vhost_parse_args(int argc, char **argv) {"rx-retry-delay", required_argument, NULL, 0}, {"rx-retry-num", required_argument, NULL, 0}, {"mergeable", required_argument, NULL, 0}, + {"vlan-strip", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {"dev-basename", required_argument, NULL, 0}, {"zero-copy", required_argument, NULL, 0}, @@ -691,6 +696,22 @@ us_vhost_parse_args(int argc, char **argv) } } + /* Enable/disable RX VLAN strip on host. */ + if (!strncmp(long_option[option_index].name, + "vlan-strip", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, + "Invalid argument for VLAN strip [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else { + vlan_strip = !!ret; + vmdq_conf_default.rxmode.hw_vlan_strip = + vlan_strip; + } + } + /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); @@ -950,7 +971,9 @@ link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m) dev->device_fh); /* Enable stripping of the vlan tag as we handle routing. */ - rte_eth_dev_set_vlan_strip_on_queue(ports[0], (uint16_t)vdev->vmdq_rx_q, 1); + if (vlan_strip) + rte_eth_dev_set_vlan_strip_on_queue(ports[0], + (uint16_t)vdev->vmdq_rx_q, 1); /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 22/24] virtio: Use soft vlan strip in mergeable Rx path 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (20 preceding siblings ...) 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 21/24] example/vhost: Add vlan-strip cmd line option Ouyang Changchun @ 2015-01-27 2:36 ` Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 23/24] virtio: Fix zero copy break issue Ouyang Changchun ` (3 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:36 UTC (permalink / raw) To: dev To keep the consistent logic with normal Rx path, the mergeable Rx path also needs software vlan strip/decap if it is enabled. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82e8eb..c6d9ae7 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, 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]; @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, seg_res -= rcv_cnt; } + if (hw->vlan_strip) + rte_vlan_strip(rx_pkts[nb_rx]); + VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], rx_pkts[nb_rx]->data_len); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 23/24] virtio: Fix zero copy break issue 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (21 preceding siblings ...) 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 22/24] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun @ 2015-01-27 2:36 ` Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 24/24] virtio: Remove hotspots Ouyang Changchun ` (2 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:36 UTC (permalink / raw) To: dev vHOST zero copy need get vring descriptor and its buffer address to set the DMA address of HW ring, it is done in new_device when ioctl set_backend is called. This requies virtio_dev_rxtx_start is called before vtpci_reinit_complete, which makes sure the vring descriptro and its buffer is ready before its using. this patch also fixes one set status issue, according to virtio spec, VIRTIO_CONFIG_STATUS_ACK should be set after virtio hw reset. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b905532..648c761 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -414,6 +414,7 @@ virtio_dev_close(struct rte_eth_dev *dev) /* reset the NIC */ vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); + hw->started = 0; virtio_dev_free_mbufs(dev); } @@ -1107,9 +1108,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return -ENOMEM; } - /* 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) #ifdef RTE_EAL_PORT_IO @@ -1123,6 +1121,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -1324,10 +1325,10 @@ virtio_dev_start(struct rte_eth_dev *dev) if (hw->started) return 0; - vtpci_reinit_complete(hw); - /* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start(dev); + vtpci_reinit_complete(hw); + hw->started = 1; /*Notify the backend -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v2 24/24] virtio: Remove hotspots 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (22 preceding siblings ...) 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 23/24] virtio: Fix zero copy break issue Ouyang Changchun @ 2015-01-27 2:36 ` Ouyang Changchun 2015-01-27 3:06 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Matthew Hall 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-27 2:36 UTC (permalink / raw) To: dev Remove those hotspots which is unnecessary when early returning occurs; Also reverse one likely to unlikely to let compiler has better decision; Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c6d9ae7..c4731b5 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -476,13 +476,13 @@ 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 virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; int error; - uint32_t i, nb_enqueued = 0; + uint32_t i, nb_enqueued; const uint32_t hdr_size = sizeof(struct virtio_net_hdr); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -491,7 +491,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) 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); - if (likely(num > DESC_PER_CACHELINE)) + if (unlikely(num > DESC_PER_CACHELINE)) num = num - ((rxvq->vq_used_cons_idx + num) % DESC_PER_CACHELINE); if (num == 0) @@ -499,6 +499,11 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, num); PMD_RX_LOG(DEBUG, "used:%d dequeue:%d", nb_used, num); + + hw = rxvq->hw; + nb_rx = 0; + nb_enqueued = 0; + for (i = 0; i < num ; i++) { rxm = rcv_pkts[i]; @@ -568,17 +573,17 @@ virtio_recv_mergeable_pkts(void *rx_queue, uint16_t nb_pkts) { struct virtqueue *rxvq = rx_queue; - struct virtio_hw *hw = rxvq->hw; + struct virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *prev; int error; - uint32_t i = 0, nb_enqueued = 0; - uint32_t seg_num = 0; - uint16_t extra_idx = 0; - uint32_t seg_res = 0; + uint32_t i, nb_enqueued; + uint32_t seg_num; + uint16_t extra_idx; + uint32_t seg_res; const uint32_t hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -590,6 +595,14 @@ virtio_recv_mergeable_pkts(void *rx_queue, PMD_RX_LOG(DEBUG, "used:%d\n", nb_used); + hw = rxvq->hw; + nb_rx = 0; + i = 0; + nb_enqueued = 0; + seg_num = 0; + extra_idx = 0; + seg_res = 0; + while (i < nb_used) { struct virtio_net_hdr_mrg_rxbuf *header; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (23 preceding siblings ...) 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 24/24] virtio: Remove hotspots Ouyang Changchun @ 2015-01-27 3:06 ` Matthew Hall 2015-01-27 3:42 ` Wiles, Keith 2015-01-27 10:02 ` Stephen Hemminger 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun 25 siblings, 2 replies; 132+ messages in thread From: Matthew Hall @ 2015-01-27 3:06 UTC (permalink / raw) To: Ouyang Changchun; +Cc: dev On Tue, Jan 27, 2015 at 10:35:40AM +0800, Ouyang Changchun wrote: > This is the patch set for single virtio implementation. > > Why we need single virtio? > ============================ > As we know currently there are at least 3 virtio PMD driver implementations: > A) lib/librte_pmd_virtio(refer as virtio A); > B) virtio_net_pmd by 6wind(refer as virtio B); > C) virtio by Brocade/vyatta(refer as virtio C); > > Integrating 3 implementations into one could reduce the maintaining cost and time, > in other hand, user don't need practice their application on 3 variant one by one to see > which one is the best for them; Thank you so much for this, using virtio drivers in DPDK has been messy and unpleasant in the past, and you clearly wrote a lot of nice new code to help improve it all. Previously I'd reported a bug, where all RTE virtio drivers I tried (A and B, because I did not know C existed), failed to work with the virtio-net interfaces exposed in VirtualBox, due to various strange errors, and they all only worked with the virtio-net interfaces from qemu. I wanted to find out if we managed to fix this other problem, because I would really like to use the Vagrant VM deployment tool (https://www.vagrantup.com/) to distribute my open-source DPDK based application to everyone in the open source community. The better the out-of-box experience of practical community-created DPDK-based real-life example applications similar to mine, the more adoption of DPDK and better DPDK community we will be able to have as time marches forward. If we could manage to get it to work in VirtualBox, then I could surely help do some app-level testing on the new code, if we could see it in a test branch or test repo somewhere I could access it. Sincerely, Matthew Hall ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-27 3:06 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Matthew Hall @ 2015-01-27 3:42 ` Wiles, Keith 2015-01-27 9:41 ` Matthew Hall 2015-01-27 10:02 ` Stephen Hemminger 1 sibling, 1 reply; 132+ messages in thread From: Wiles, Keith @ 2015-01-27 3:42 UTC (permalink / raw) To: Matthew Hall, Ouyang, Changchun; +Cc: dev On 1/26/15, 8:06 PM, "Matthew Hall" <mhall@mhcomputing.net> wrote: >On Tue, Jan 27, 2015 at 10:35:40AM +0800, Ouyang Changchun wrote: >> This is the patch set for single virtio implementation. >> >> Why we need single virtio? >> ============================ >> As we know currently there are at least 3 virtio PMD driver >>implementations: >> A) lib/librte_pmd_virtio(refer as virtio A); >> B) virtio_net_pmd by 6wind(refer as virtio B); >> C) virtio by Brocade/vyatta(refer as virtio C); >> >> Integrating 3 implementations into one could reduce the maintaining >>cost and time, >> in other hand, user don't need practice their application on 3 variant >>one by one to see >> which one is the best for them; > >Thank you so much for this, using virtio drivers in DPDK has been messy >and >unpleasant in the past, and you clearly wrote a lot of nice new code to >help >improve it all. > >Previously I'd reported a bug, where all RTE virtio drivers I tried (A >and B, >because I did not know C existed), failed to work with the virtio-net >interfaces exposed in VirtualBox, due to various strange errors, and they >all >only worked with the virtio-net interfaces from qemu. > >I wanted to find out if we managed to fix this other problem, because I >would >really like to use the Vagrant VM deployment tool >(https://www.vagrantup.com/) >to distribute my open-source DPDK based application to everyone in the >open source community. > >The better the out-of-box experience of practical community-created >DPDK-based >real-life example applications similar to mine, the more adoption of DPDK >and >better DPDK community we will be able to have as time marches forward. > >If we could manage to get it to work in VirtualBox, then I could surely >help >do some app-level testing on the new code, if we could see it in a test >branch >or test repo somewhere I could access it. There is an app note on how to get DPDK working in VirtualBox, it is a bit bumpy on getting it work. Here is the link: http://plvision.eu/blog/deploying-intel-dpdk-in-oracle-virtualbox/ I have not tried it, but it was suggested to me it should work. It will be nice if the new driver works better :-) > >Sincerely, >Matthew Hall ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-27 3:42 ` Wiles, Keith @ 2015-01-27 9:41 ` Matthew Hall 0 siblings, 0 replies; 132+ messages in thread From: Matthew Hall @ 2015-01-27 9:41 UTC (permalink / raw) To: Wiles, Keith; +Cc: dev On Tue, Jan 27, 2015 at 03:42:00AM +0000, Wiles, Keith wrote: > There is an app note on how to get DPDK working in VirtualBox, it is a bit > bumpy on getting it work. > Here is the link: > http://plvision.eu/blog/deploying-intel-dpdk-in-oracle-virtualbox/ > > I have not tried it, but it was suggested to me it should work. It will be > nice if the new driver works better :-) I already used a derivative of these directions... "cheated" and used the igb driver like they did. Unlike them I automated the entire process, including updating the base OS to latest kernel and recompiling against it, as well as auto-enabling the NICs, the SSE instruction sets, etc. etc. However their directions use an IGB NIC not a virtio-net NIC which would be much better for performance and resource consumption. So I really would be very very happy if we had a virtio-net which worked properly with both qemu and VirtualBox. Matthew. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-27 3:06 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Matthew Hall 2015-01-27 3:42 ` Wiles, Keith @ 2015-01-27 10:02 ` Stephen Hemminger 2015-01-27 18:59 ` Matthew Hall 1 sibling, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-01-27 10:02 UTC (permalink / raw) To: Matthew Hall; +Cc: dev On Mon, 26 Jan 2015 19:06:12 -0800 Matthew Hall <mhall@mhcomputing.net> wrote: > Thank you so much for this, using virtio drivers in DPDK has been messy and > unpleasant in the past, and you clearly wrote a lot of nice new code to help > improve it all. > > Previously I'd reported a bug, where all RTE virtio drivers I tried (A and B, > because I did not know C existed), failed to work with the virtio-net > interfaces exposed in VirtualBox, due to various strange errors, and they all > only worked with the virtio-net interfaces from qemu. I suspect a problem with features required (and not supported by VirtualBox). Build driver with debug enabled and send the log please. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v2 00/24] Single virtio implementation 2015-01-27 10:02 ` Stephen Hemminger @ 2015-01-27 18:59 ` Matthew Hall 0 siblings, 0 replies; 132+ messages in thread From: Matthew Hall @ 2015-01-27 18:59 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev On Tue, Jan 27, 2015 at 10:02:24AM +0000, Stephen Hemminger wrote: > On Mon, 26 Jan 2015 19:06:12 -0800 > Matthew Hall <mhall@mhcomputing.net> wrote: > > > Thank you so much for this, using virtio drivers in DPDK has been messy and > > unpleasant in the past, and you clearly wrote a lot of nice new code to help > > improve it all. > > > > Previously I'd reported a bug, where all RTE virtio drivers I tried (A and B, > > because I did not know C existed), failed to work with the virtio-net > > interfaces exposed in VirtualBox, due to various strange errors, and they all > > only worked with the virtio-net interfaces from qemu. > > I suspect a problem with features required (and not supported by VirtualBox). > Build driver with debug enabled and send the log please. Hi Stephen, Here is everything that happened when I tried it before. http://dpdk.org/ml/archives/dev/2014-October/006623.html Matthew. ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 00/25] Single virtio implementation 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun ` (24 preceding siblings ...) 2015-01-27 3:06 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Matthew Hall @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 01/25] virtio: Rearrange resource initialization Ouyang Changchun ` (25 more replies) 25 siblings, 26 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev This is the patch set for single virtio implementation. Why we need single virtio? ============================ As we know currently there are at least 3 virtio PMD driver implementations: A) lib/librte_pmd_virtio(refer as virtio A); B) virtio_net_pmd by 6wind(refer as virtio B); C) virtio by Brocade/vyatta(refer as virtio C); Integrating 3 implementations into one could reduce the maintaining cost and time, in other hand, user don't need practice their application on 3 variant one by one to see which one is the best for them; What's the status? ==================== Currently virtio A has covered most features of virtio B except for using port io to get pci resource, so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some issues in original codes. What this patch set contains: =============================== 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; 2) virtio: Use weaker barriers, as 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 may help performance a bit; 3) virtio: Allow starting with link down, other driver has similar behavior; 4) virtio: Add support for Link State interrupt; 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; 6) virtio: Use software vlan stripping; 7) virtio: Remove unnecessary adapter structure; 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; 10) virtio: Make vtpci_get_status a local function as it is used in one file; 11) virtio: Check for packet headroom at compile time; 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; 13) virtio: Add support for vlan filtering; 14) virtio: Add support for multiple mac addresses; 15) virtio: Add ability to set MAC address; 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; 18) virtio: Fix descriptor index issue; 19) ether: Fix vlan strip/insert issue; 20) example/vhost: Avoid inserting vlan twice and guest and host; 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic with the normal Rx path. Changes in v2: 23) virtio: Fix zero copy break issue, the vring should be ready before virtio PMD set the status of DRIVER_OK; 24) virtio: Remove unnecessary hotspots in data path. Changes in v3: 25) virtio: Fix wmb issue; 26) Fix one minor issue in patch 20, also fix its idention. Changchun Ouyang (9): virtio: Use port IO to get PCI resource. virtio: Fix descriptor index issue ether: Fix vlan strip/insert issue example/vhost: Avoid inserting vlan twice example/vhost: Add vlan-strip cmd line option virtio: Use soft vlan strip in mergeable Rx path virtio: Fix zero copy break issue virtio: Remove hotspots virtio: Fix wmb issue Stephen Hemminger (16): virtio: Rearrange resource initialization virtio: Use weaker barriers virtio: Allow starting with link down virtio: Add support for Link State interrupt ether: Add soft vlan encap/decap functions virtio: Use software vlan stripping virtio: Remove unnecessary adapter structure virtio: Remove redundant vq_alignment virtio: Fix how states are handled during initialization virtio: Make vtpci_get_status local virtio: Check for packet headroom at compile time virtio: Move allocation before initialization virtio: Add support for vlan filtering virtio: Add suport for multiple mac addresses virtio: Add ability to set MAC address virtio: Free mbuf's with threshold config/common_linuxapp | 2 + examples/vhost/main.c | 70 +++-- lib/librte_eal/common/include/rte_pci.h | 4 + lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_ether/rte_ethdev.h | 8 + lib/librte_ether/rte_ether.h | 76 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 492 +++++++++++++++++++++++++------- lib/librte_pmd_virtio/virtio_ethdev.h | 12 +- lib/librte_pmd_virtio/virtio_pci.c | 20 +- lib/librte_pmd_virtio/virtio_pci.h | 8 +- lib/librte_pmd_virtio/virtio_rxtx.c | 137 ++++++--- lib/librte_pmd_virtio/virtqueue.h | 59 +++- 12 files changed, 708 insertions(+), 185 deletions(-) -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 01/25] virtio: Rearrange resource initialization 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 02/25] virtio: Use weaker barriers Ouyang Changchun ` (24 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 76 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b3b5bb6..662a49c 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -794,6 +794,41 @@ virtio_has_msix(const struct rte_pci_addr *loc) 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) @@ -801,6 +836,12 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) /* 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 /* @@ -831,40 +872,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 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; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 02/25] virtio: Use weaker barriers 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 01/25] virtio: Rearrange resource initialization Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 03/25] virtio: Allow starting with link down Ouyang Changchun ` (23 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev The 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 662a49c..dc47e72 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -175,7 +175,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, uint32_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)); diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c013f97..78af334 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -456,7 +456,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) 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); @@ -516,6 +516,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } if (likely(nb_enqueued)) { + virtio_wmb(); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); @@ -547,7 +548,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, nb_used = VIRTQUEUE_NUSED(rxvq); - rmb(); + virtio_rmb(); if (nb_used == 0) return 0; @@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) PMD_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); @@ -735,6 +736,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) } } vq_update_avail_idx(txvq); + virtio_wmb(); txvq->packets += nb_tx; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index fdee054..f6ad98d 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -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) @@ -225,7 +234,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - rte_compiler_barrier(); + virtio_rmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } @@ -255,7 +264,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. */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 03/25] virtio: Allow starting with link down 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 01/25] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 02/25] virtio: Use weaker barriers Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 04/25] virtio: Add support for Link State interrupt Ouyang Changchun ` (22 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Starting driver with link down should be ok, it is with every other driver. So just allow it. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index dc47e72..5df3b54 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1057,14 +1057,12 @@ virtio_dev_start(struct rte_eth_dev *dev) vtpci_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); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 04/25] virtio: Add support for Link State interrupt 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (2 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 03/25] virtio: Allow starting with link down Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 05/25] ether: Add soft vlan encap/decap functions Ouyang Changchun ` (21 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Virtio has link state interrupt which can be used. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 5df3b54..ef87ff8 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) #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. */ @@ -968,6 +996,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, PMD_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; } @@ -975,7 +1007,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), @@ -1021,6 +1053,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"); @@ -1029,7 +1064,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return (-EINVAL); } - return 0; + ret = vtpci_irq_config(hw, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, "failed to set config vector"); + + return ret; } @@ -1037,7 +1076,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); @@ -1052,18 +1090,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 @@ -1145,6 +1187,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); } @@ -1161,6 +1204,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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, @@ -1179,10 +1223,8 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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 diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index ca9c748..6d51032 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uint8_t status) VIRTIO_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; +} diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 373f9dc..6998737 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void 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_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 05/25] ether: Add soft vlan encap/decap functions 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (3 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 04/25] virtio: Add support for Link State interrupt Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 06/25] virtio: Use software vlan stripping Ouyang Changchun ` (20 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev It is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software. This allows application to be device independent. Avoid discarding shared mbufs. Make a copy in rte_vlan_insert() of any packet to be tagged that has a reference count > 1. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 7e7d22c..74f71c2 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -49,6 +49,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. */ @@ -333,6 +335,80 @@ struct vxlan_hdr { #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) /**< VXLAN tunnel header length. */ +/** + * 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->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_REFCNT + /* Can't insert header if mbuf is shared */ + if (rte_mbuf_refcnt_read(*m) > 1) { + struct rte_mbuf *copy; + + copy = rte_pktmbuf_clone(*m, (*m)->pool); + if (unlikely(copy == NULL)) + return -ENOMEM; + rte_pktmbuf_free(*m); + *m = copy; + } +#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)->vlan_tci); + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 06/25] virtio: Use software vlan stripping 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (4 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 05/25] ether: Add soft vlan encap/decap functions Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 07/25] virtio: Remove unnecessary adapter structure Ouyang Changchun ` (19 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Implement VLAN stripping in software. This allows application to be device independent. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 3 +++ lib/librte_pmd_virtio/virtio_ethdev.c | 2 ++ lib/librte_pmd_virtio/virtio_pci.h | 1 + lib/librte_pmd_virtio/virtio_rxtx.c | 20 ++++++++++++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 1200c1c..94d6b2b 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -643,6 +643,9 @@ struct rte_eth_rxconf { #define ETH_TXQ_FLAGS_NOOFFLOADS \ (ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | \ ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) +#define ETH_TXQ_FLAGS_NOXSUMS \ + (ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ + ETH_TXQ_FLAGS_NOXSUMTCP) /** * A structure used to configure a TX ring of an Ethernet port. */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index ef87ff8..da74659 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1064,6 +1064,8 @@ virtio_dev_configure(struct rte_eth_dev *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"); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6998737..6d93fac 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -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]; }; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 78af334..e0216ec 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -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" @@ -408,8 +409,8 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, 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; } @@ -446,6 +447,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]; @@ -489,6 +491,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->pkt_len = (uint32_t)(len[i] - hdr_size); rxm->data_len = (uint16_t)(len[i] - hdr_size); + if (hw->vlan_strip) + rte_vlan_strip(rxm); + VIRTIO_DUMP_PACKET(rxm, rxm->data_len); rx_pkts[nb_rx++] = rxm; @@ -717,6 +722,17 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) */ if (likely(need <= 0)) { 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)) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 07/25] virtio: Remove unnecessary adapter structure 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (5 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 06/25] virtio: Use software vlan stripping Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 08/25] virtio: Remove redundant vq_alignment Ouyang Changchun ` (18 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Cleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure. Also allows removing unneeded macro, making code clearer. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 43 ++++++++++++----------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 -------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index da74659..59b74b7 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -207,8 +207,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, static 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; @@ -242,8 +241,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, const 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 */ @@ -383,8 +381,7 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, struct 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, @@ -410,8 +407,7 @@ virtio_dev_close(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -430,8 +426,7 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -450,8 +445,7 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -470,8 +464,7 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -853,8 +846,7 @@ 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); + struct virtio_hw *hw = dev->data->dev_private; uint8_t isr; /* Read interrupt status which clears interrupt */ @@ -880,12 +872,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, @@ -1010,7 +1001,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), }; /* @@ -1053,8 +1044,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"); @@ -1078,8 +1068,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); @@ -1185,8 +1174,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) static 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); @@ -1199,8 +1187,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet { 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; @@ -1232,7 +1219,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet static 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; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 1da3c62..55c9749 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -110,15 +110,6 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_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 diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index e0216ec..a82d5ff 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -326,8 +326,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) void 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; if (hw->cvq) { virtio_dev_vring_start(hw->cvq, VTNET_CQ); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 08/25] virtio: Remove redundant vq_alignment 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (6 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 07/25] virtio: Remove unnecessary adapter structure Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 09/25] virtio: Fix how states are handled during initialization Ouyang Changchun ` (17 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Since vq_alignment is constant (always 4K), it does not need to be part of the vring struct. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 59b74b7..0d41e7f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -294,7 +294,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, 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; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82d5ff..b6d6832 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) * 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; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index f6ad98d..5b8a255 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -138,8 +138,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 */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 09/25] virtio: Fix how states are handled during initialization 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (7 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 08/25] virtio: Remove redundant vq_alignment Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 10/25] virtio: Make vtpci_get_status local Ouyang Changchun ` (16 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Change order of initialiazation to match Linux kernel. Don't blow away control queue by doing reset when stopped. Calling dev_stop then dev_start would not work. Dev_stop was calling virtio reset and that would clear all queues and clear all feature negotiation. Resolved by only doing reset on device removal. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 58 ++++++++++++++++++++--------------- lib/librte_pmd_virtio/virtio_pci.c | 10 ++---- lib/librte_pmd_virtio/virtio_pci.h | 3 +- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0d41e7f..47dd33d 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -398,9 +398,14 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, static void virtio_dev_close(struct rte_eth_dev *dev) { + struct virtio_hw *hw = dev->data->dev_private; + PMD_INIT_LOG(DEBUG, "virtio_dev_close"); - virtio_dev_stop(dev); + /* reset the NIC */ + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + vtpci_reset(hw); + virtio_dev_free_mbufs(dev); } static void @@ -889,6 +894,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (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; @@ -899,9 +907,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -990,6 +995,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* Setup interrupt callback */ rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); + + virtio_dev_cq_start(eth_dev); + return 0; } @@ -1044,7 +1052,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; - int ret; PMD_INIT_LOG(DEBUG, "configure"); @@ -1055,11 +1062,12 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; - ret = vtpci_irq_config(hw, 0); - if (ret != 0) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } - return ret; + return 0; } @@ -1069,17 +1077,6 @@ 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); - /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { @@ -1096,8 +1093,16 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Initialize Link state */ virtio_dev_link_update(dev, 0); + /* On restart after stop do not touch queues */ + if (hw->started) + return 0; + vtpci_reinit_complete(hw); + /* Do final configuration before rx/tx engine starts */ + virtio_dev_rxtx_start(dev); + hw->started = 1; + /*Notify the backend *Otherwise the tap backend might already stop its queue due to fullness. *vhost backend will have no chance to be waked up @@ -1168,17 +1173,20 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) } /* - * Stop device: disable rx and tx functions to allow for reconfiguring. + * Stop device: disable interrupt and mark link down */ static void virtio_dev_stop(struct rte_eth_dev *dev) { - struct virtio_hw *hw = dev->data->dev_private; + struct rte_eth_link link; - /* reset the NIC */ - vtpci_irq_config(hw, 0); - vtpci_reset(hw); - virtio_dev_free_mbufs(dev); + PMD_INIT_LOG(DEBUG, "stop"); + + if (dev->data->dev_conf.intr_conf.lsc) + rte_intr_disable(&dev->pci_dev->intr_handle); + + memset(&link, 0, sizeof(link)); + virtio_dev_atomic_write_link_status(dev, &link); } static int diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index 6d51032..b099e4f 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -137,15 +137,9 @@ vtpci_isr(struct virtio_hw *hw) /* Enable one vector (0) for Link State Intrerrupt */ -int +uint16_t 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; + return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); } diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6d93fac..0a4b578 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -170,6 +170,7 @@ struct virtio_hw { uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; + uint8_t started; uint8_t mac_addr[ETHER_ADDR_LEN]; }; @@ -266,6 +267,6 @@ void 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); +uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); #endif /* _VIRTIO_PCI_H_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 10/25] virtio: Make vtpci_get_status local 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (8 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 09/25] virtio: Fix how states are handled during initialization Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 11/25] virtio: Check for packet headroom at compile time Ouyang Changchun ` (15 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Make vtpci_get_status a local function as it is used in one file. igned-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_pci.c | 4 +++- lib/librte_pmd_virtio/virtio_pci.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index b099e4f..2245bec 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -35,6 +35,8 @@ #include "virtio_pci.h" #include "virtio_logs.h" +static uint8_t vtpci_get_status(struct virtio_hw *); + void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -113,7 +115,7 @@ vtpci_reinit_complete(struct virtio_hw *hw) vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); } -uint8_t +static uint8_t vtpci_get_status(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 0a4b578..64d9c34 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -255,8 +255,6 @@ void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); -uint8_t vtpci_get_status(struct virtio_hw *); - void vtpci_set_status(struct virtio_hw *, uint8_t); uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 11/25] virtio: Check for packet headroom at compile time 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (9 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 10/25] virtio: Make vtpci_get_status local Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 12/25] virtio: Move allocation before initialization Ouyang Changchun ` (14 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Better to check at compile time than fail at runtime. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 47dd33d..9679c2f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -882,11 +882,7 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; - if (RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)) { - PMD_INIT_LOG(ERR, - "MBUF HEADROOM should be enough to hold virtio net hdr\n"); - return -1; - } + RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); eth_dev->dev_ops = &virtio_eth_dev_ops; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 12/25] virtio: Move allocation before initialization 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (10 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 11/25] virtio: Check for packet headroom at compile time Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 13/25] virtio: Add support for vlan filtering Ouyang Changchun ` (13 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev If allocation fails, don't want to leave virtio device stuck in middle of initialization sequence. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 9679c2f..39b1fb4 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -890,6 +890,15 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %d bytes needed to store MAC addresses", + ETHER_ADDR_LEN); + return -ENOMEM; + } + /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); @@ -916,15 +925,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr); } - /* Allocate memory for storing MAC addresses */ - eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); - if (eth_dev->data->mac_addrs == NULL) { - PMD_INIT_LOG(ERR, - "Failed to allocate %d bytes needed to store MAC addresses", - ETHER_ADDR_LEN); - return -ENOMEM; - } - /* Copy the permanent MAC address to: virtio_hw */ virtio_get_hwaddr(hw); ether_addr_copy((struct ether_addr *) hw->mac_addr, -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 13/25] virtio: Add support for vlan filtering 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (11 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 12/25] virtio: Move allocation before initialization Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 14/25] virtio: Add suport for multiple mac addresses Ouyang Changchun ` (12 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Virtio supports vlan filtering. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 39b1fb4..591d692 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -84,6 +84,8 @@ static void virtio_dev_tx_queue_release(__rte_unused void *txq); 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); +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, + uint16_t vlan_id, int on); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -511,6 +513,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, + .vlan_filter_set = virtio_vlan_filter_set, }; static inline int @@ -640,14 +643,31 @@ virtio_get_hwaddr(struct virtio_hw *hw) } } +static int +virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtio_pmd_ctrl ctrl; + int len; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) + return -ENOTSUP; + + ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN; + ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; + memcpy(ctrl.data, &vlan_id, sizeof(vlan_id)); + len = sizeof(vlan_id); + + return virtio_send_command(hw->cvq, &ctrl, &len, 1); +} static void virtio_negotiate_features(struct virtio_hw *hw) { uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_VLAN; - mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; + /* checksum offload not implemented */ + mask = VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding * checksum offload feature is also negotiated. @@ -1058,6 +1078,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; + if (rxmode->hw_vlan_filter + && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { + PMD_DRV_LOG(NOTICE, + "vlan filtering not available on this host"); + return -ENOTSUP; + } + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); return -EBUSY; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 14/25] virtio: Add suport for multiple mac addresses 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (12 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 13/25] virtio: Add support for vlan filtering Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 15/25] virtio: Add ability to set MAC address Ouyang Changchun ` (11 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Virtio support multiple MAC addresses. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 94 ++++++++++++++++++++++++++++++++++- lib/librte_pmd_virtio/virtio_ethdev.h | 3 +- lib/librte_pmd_virtio/virtqueue.h | 34 ++++++++++++- 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 591d692..0e74eea 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -86,6 +86,10 @@ static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); +static void virtio_mac_addr_add(struct rte_eth_dev *dev, + struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused); +static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -503,8 +507,6 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .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, /* meaningfull only to multiple queue */ .rx_queue_release = virtio_dev_rx_queue_release, @@ -514,6 +516,8 @@ static struct eth_dev_ops virtio_eth_dev_ops = { /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, .vlan_filter_set = virtio_vlan_filter_set, + .mac_addr_add = virtio_mac_addr_add, + .mac_addr_remove = virtio_mac_addr_remove, }; static inline int @@ -644,6 +648,92 @@ virtio_get_hwaddr(struct virtio_hw *hw) } static int +virtio_mac_table_set(struct virtio_hw *hw, + const struct virtio_net_ctrl_mac *uc, + const struct virtio_net_ctrl_mac *mc) +{ + struct virtio_pmd_ctrl ctrl; + int err, len[2]; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET; + + len[0] = uc->entries * ETHER_ADDR_LEN + sizeof(uc->entries); + memcpy(ctrl.data, uc, len[0]); + + len[1] = mc->entries * ETHER_ADDR_LEN + sizeof(mc->entries); + memcpy(ctrl.data + len[0], mc, len[1]); + + err = virtio_send_command(hw->cvq, &ctrl, len, 2); + if (err != 0) + PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err); + + return err; +} + +static void +virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused) +{ + struct virtio_hw *hw = dev->data->dev_private; + const struct ether_addr *addrs = dev->data->mac_addrs; + unsigned int i; + struct virtio_net_ctrl_mac *uc, *mc; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + const struct ether_addr *addr + = (i == index) ? mac_addr : addrs + i; + struct virtio_net_ctrl_mac *tbl + = is_multicast_ether_addr(addr) ? mc : uc; + + memcpy(&tbl->macs[tbl->entries++], addr, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static void +virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct ether_addr *addrs = dev->data->mac_addrs; + struct virtio_net_ctrl_mac *uc, *mc; + unsigned int i; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + struct virtio_net_ctrl_mac *tbl; + + if (i == index || is_zero_ether_addr(addrs + i)) + continue; + + tbl = is_multicast_ether_addr(addrs + i) ? mc : uc; + memcpy(&tbl->macs[tbl->entries++], addrs + i, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct virtio_hw *hw = dev->data->dev_private; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 55c9749..74ac7e0 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -51,7 +51,7 @@ #define VIRTIO_MAX_RX_QUEUES 128 #define VIRTIO_MAX_TX_QUEUES 128 -#define VIRTIO_MAX_MAC_ADDRS 1 +#define VIRTIO_MAX_MAC_ADDRS 64 #define VIRTIO_MIN_RX_BUFSIZE 64 #define VIRTIO_MAX_RX_PKTLEN 9728 @@ -60,6 +60,7 @@ (VIRTIO_NET_F_MAC | \ VIRTIO_NET_F_STATUS | \ VIRTIO_NET_F_MQ | \ + VIRTIO_NET_F_CTRL_MAC_ADDR | \ VIRTIO_NET_F_CTRL_VQ | \ VIRTIO_NET_F_CTRL_RX | \ VIRTIO_NET_F_CTRL_VLAN | \ diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 5b8a255..d210f4f 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -99,6 +99,34 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; #define VIRTIO_NET_CTRL_RX_NOBCAST 5 /** + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + uint32_t entries; + uint8_t macs[][ETHER_ADDR_LEN]; +} __attribute__((__packed__)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/** * Control VLAN filtering * * The VLAN filter table is controlled via a simple ADD/DEL interface. @@ -121,7 +149,7 @@ typedef uint8_t virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_MAX_CTRL_DATA 128 +#define VIRTIO_MAX_CTRL_DATA 2048 struct virtio_pmd_ctrl { struct virtio_net_ctrl_hdr hdr; @@ -180,6 +208,10 @@ struct virtqueue { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 #endif +#ifndef VIRTIO_NET_F_CTRL_MAC_ADDR +#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 +#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 +#endif /** * This is the first element of the scatter-gather list. If you don't -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 15/25] virtio: Add ability to set MAC address 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (13 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 14/25] virtio: Add suport for multiple mac addresses Ouyang Changchun @ 2015-01-29 7:23 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 16/25] virtio: Free mbuf's with threshold Ouyang Changchun ` (10 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:23 UTC (permalink / raw) To: dev Need to have do special things to set default mac address. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 5 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 94d6b2b..5a54276 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1240,6 +1240,10 @@ typedef void (*eth_mac_addr_add_t)(struct rte_eth_dev *dev, uint32_t vmdq); /**< @internal Set a MAC address into Receive Address Address Register */ +typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); +/**< @internal Set a MAC address into Receive Address Address Register */ + typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint8_t on); @@ -1459,6 +1463,7 @@ struct eth_dev_ops { priority_flow_ctrl_set_t priority_flow_ctrl_set; /**< Setup priority flow control.*/ eth_mac_addr_remove_t mac_addr_remove; /**< Remove MAC address */ eth_mac_addr_add_t mac_addr_add; /**< Add a MAC address */ + eth_mac_addr_set_t mac_addr_set; /**< Set a MAC address */ eth_uc_hash_table_set_t uc_hash_table_set; /**< Set Unicast Table Array */ eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */ eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0e74eea..b30ab2a 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -90,6 +90,8 @@ static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused); static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); +static void virtio_mac_addr_set(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -518,6 +520,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .vlan_filter_set = virtio_vlan_filter_set, .mac_addr_add = virtio_mac_addr_add, .mac_addr_remove = virtio_mac_addr_remove, + .mac_addr_set = virtio_mac_addr_set, }; static inline int @@ -733,6 +736,27 @@ virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) virtio_mac_table_set(hw, uc, mc); } +static void +virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) +{ + struct virtio_hw *hw = dev->data->dev_private; + + memcpy(hw->mac_addr, mac_addr, ETHER_ADDR_LEN); + + /* Use atomic update if available */ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { + struct virtio_pmd_ctrl ctrl; + int len = ETHER_ADDR_LEN; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; + + memcpy(ctrl.data, mac_addr, ETHER_ADDR_LEN); + virtio_send_command(hw->cvq, &ctrl, &len, 1); + } else if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) + virtio_set_hwaddr(hw); +} + static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 16/25] virtio: Free mbuf's with threshold 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (14 preceding siblings ...) 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 15/25] virtio: Add ability to set MAC address Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource Ouyang Changchun ` (9 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev This makes virtio driver work like ixgbe. Transmit buffers are held until a transmit threshold is reached. The previous behavior was to hold mbuf's until the ring entry was reused which caused more memory usage than needed. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 7 ++-- lib/librte_pmd_virtio/virtio_rxtx.c | 75 +++++++++++++++++++++++++---------- lib/librte_pmd_virtio/virtqueue.h | 3 +- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b30ab2a..8cd2d51 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -176,15 +176,16 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, virtqueue_notify(vq); - while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) + rte_rmb(); + while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { + rte_rmb(); usleep(100); + } while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; - virtio_rmb(); - used_idx = (uint32_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index b6d6832..580701a 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -129,17 +129,32 @@ virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, return i; } +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif + +/* Cleanup from completed transmits. */ static void -virtqueue_dequeue_pkt_tx(struct virtqueue *vq) +virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) { - struct vring_used_elem *uep; - uint16_t used_idx, desc_idx; + uint16_t i, used_idx, desc_idx; + for (i = 0; i < num; i++) { + struct vring_used_elem *uep; + struct vq_desc_extra *dxp; + + used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); + uep = &vq->vq_ring.used->ring[used_idx]; + dxp = &vq->vq_descx[used_idx]; + + desc_idx = (uint16_t) uep->id; + vq->vq_used_cons_idx++; + vq_ring_free_chain(vq, desc_idx); - used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); - uep = &vq->vq_ring.used->ring[used_idx]; - desc_idx = (uint16_t) uep->id; - vq->vq_used_cons_idx++; - vq_ring_free_chain(vq, desc_idx); + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } } @@ -203,8 +218,6 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) idx = head_idx; dxp = &txvq->vq_descx[idx]; - if (dxp->cookie != NULL) - rte_pktmbuf_free(dxp->cookie); dxp->cookie = (void *)cookie; dxp->ndescs = needed; @@ -404,6 +417,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; struct virtqueue *vq; + uint16_t tx_free_thresh; int ret; PMD_INIT_FUNC_TRACE(); @@ -421,6 +435,22 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, return ret; } + tx_free_thresh = tx_conf->tx_free_thresh; + if (tx_free_thresh == 0) + tx_free_thresh = + RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH); + + if (tx_free_thresh >= (vq->vq_nentries - 3)) { + RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the " + "number of TX entries minus 3 (%u)." + " (tx_free_thresh=%u port=%u queue=%u)\n", + vq->vq_nentries - 3, + tx_free_thresh, dev->data->port_id, queue_idx); + return -EINVAL; + } + + vq->vq_free_thresh = tx_free_thresh; + dev->data->tx_queues[queue_idx] = vq; return 0; } @@ -688,11 +718,9 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; - uint16_t nb_used, nb_tx, num; + uint16_t nb_used, nb_tx; int error; - nb_tx = 0; - if (unlikely(nb_pkts < 1)) return nb_pkts; @@ -700,21 +728,26 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); + if (likely(nb_used > txvq->vq_free_thresh)) + virtio_xmit_cleanup(txvq, nb_used); - num = (uint16_t)(likely(nb_used < VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ); + nb_tx = 0; while (nb_tx < nb_pkts) { /* Need one more descriptor for virtio header. */ int need = tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; - int deq_cnt = RTE_MIN(need, (int)num); - num -= (deq_cnt > 0) ? deq_cnt : 0; - while (deq_cnt > 0) { - virtqueue_dequeue_pkt_tx(txvq); - deq_cnt--; + /*Positive value indicates it need free vring descriptors */ + if (unlikely(need > 0)) { + nb_used = VIRTQUEUE_NUSED(txvq); + virtio_rmb(); + need = RTE_MIN(need, (int)nb_used); + + virtio_xmit_cleanup(txvq, need); + need = (int)tx_pkts[nb_tx]->nb_segs - + txvq->vq_free_cnt + 1; } - need = (int)tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; /* * Zero or negative value indicates it has enough free * descriptors to use for transmitting. @@ -723,7 +756,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) txm = tx_pkts[nb_tx]; /* Do VLAN tag insertion */ - if (txm->ol_flags & PKT_TX_VLAN_PKT) { + if (unlikely(txm->ol_flags & PKT_TX_VLAN_PKT)) { error = rte_vlan_insert(&txm); if (unlikely(error)) { rte_pktmbuf_free(txm); diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index d210f4f..6c45c27 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -164,6 +164,7 @@ struct virtqueue { struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint8_t port_id; /**< Device port identifier. */ + uint16_t vq_queue_index; /**< PCI queue index */ void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; @@ -172,7 +173,7 @@ struct virtqueue { struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_nentries; /**< vring desc numbers */ - uint16_t vq_queue_index; /**< PCI queue index */ + uint16_t vq_free_thresh; /**< free threshold */ /** * Head of the free chain in the descriptor table. If * there are no free descriptors, this will be set to -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource. 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (15 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 16/25] virtio: Free mbuf's with threshold Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 23:14 ` Thomas Monjalon 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 18/25] virtio: Fix descriptor index issue Ouyang Changchun ` (8 subsequent siblings) 25 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- config/common_linuxapp | 2 + lib/librte_eal/common/include/rte_pci.h | 4 ++ lib/librte_eal/linuxapp/eal/eal_pci.c | 5 +- lib/librte_pmd_virtio/virtio_ethdev.c | 91 ++++++++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/config/common_linuxapp b/config/common_linuxapp index 2f9643b..a412457 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -100,6 +100,8 @@ CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n CONFIG_RTE_EAL_IGB_UIO=y CONFIG_RTE_EAL_VFIO=y +# Only for VIRTIO PMD currently +CONFIG_RTE_EAL_PORT_IO=n # # Special configurations in PCI Config Space for high performance diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..19abc1f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -193,6 +193,10 @@ struct rte_pci_driver { /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */ #define RTE_PCI_DRV_NEED_MAPPING 0x0001 +/** Device needs port IO(done with /proc/ioports) */ +#ifdef RTE_EAL_PORT_IO +#define RTE_PCI_DRV_PORT_IO 0x0002 +#endif /** Device driver must be registered several times until failure - deprecated */ #pragma GCC poison RTE_PCI_DRV_MULTIPLE /** Device needs to be unbound even if no module is provided */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..5db0059 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -574,7 +574,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d /* map resources for devices that use igb_uio */ ret = pci_map_device(dev); if (ret != 0) - return ret; +#ifdef RTE_EAL_PORT_IO + if ((dr->drv_flags & RTE_PCI_DRV_PORT_IO) == 0) +#endif + return ret; } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && rte_eal_process_type() == RTE_PROC_PRIMARY) { /* unbind current driver */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 8cd2d51..b905532 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -961,6 +961,71 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) start, size); return 0; } + +#ifdef RTE_EAL_PORT_IO +/* Extract port I/O numbers from proc/ioports */ +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_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; +} +#endif + #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -974,6 +1039,14 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) /* no setup required */ return 0; } + +#ifdef RTE_EAL_PORT_IO +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) +{ + /* no setup required */ + return 0; +} +#endif #endif /* @@ -1039,7 +1112,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev = eth_dev->pci_dev; if (virtio_resource_init(pci_dev) < 0) - return -1; +#ifdef RTE_EAL_PORT_IO + if (virtio_resource_init_by_portio(pci_dev) < 0) +#endif + return -1; hw->use_msix = virtio_has_msix(&pci_dev->addr); hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; @@ -1132,6 +1208,18 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 0; } +#ifdef RTE_EAL_PORT_IO +static struct eth_driver rte_virtio_pmd = { + { + .name = "rte_virtio_pmd", + .id_table = pci_id_virtio_map, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_PORT_IO | + RTE_PCI_DRV_INTR_LSC, + }, + .eth_dev_init = eth_virtio_dev_init, + .dev_private_size = sizeof(struct virtio_hw), +}; +#else static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", @@ -1141,6 +1229,7 @@ static struct eth_driver rte_virtio_pmd = { .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_hw), }; +#endif /* * Driver initialization routine. -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource. 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-01-29 23:14 ` Thomas Monjalon 2015-02-04 1:31 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Thomas Monjalon @ 2015-01-29 23:14 UTC (permalink / raw) To: Ouyang Changchun; +Cc: dev Hi Changchun, 2015-01-29 15:24, Ouyang Changchun: > Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. Thanks for your effort. I think port IO is a really interesting option but it needs more EAL rework to be correctly integrated. Then virtio-net-pmd (http://dpdk.org/browse/virtio-net-pmd/) will be obsolete and moved in a deprecated area. > --- a/config/common_linuxapp > +++ b/config/common_linuxapp > +# Only for VIRTIO PMD currently > +CONFIG_RTE_EAL_PORT_IO=n This is the first problem. We must stop adding new build-time options. We should be able to choose between PCI mapping and port IO at runtime. > +/** Device needs port IO(done with /proc/ioports) */ > +#ifdef RTE_EAL_PORT_IO > +#define RTE_PCI_DRV_PORT_IO 0x0002 > +#endif A flag should never be ifdef'ed. > @@ -574,7 +574,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d > /* map resources for devices that use igb_uio */ > ret = pci_map_device(dev); > if (ret != 0) > - return ret; > +#ifdef RTE_EAL_PORT_IO > + if ((dr->drv_flags & RTE_PCI_DRV_PORT_IO) == 0) > +#endif > + return ret; > } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && > rte_eal_process_type() == RTE_PROC_PRIMARY) { > /* unbind current driver */ Why do you need this ugly return? > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > @@ -961,6 +961,71 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) > start, size); > return 0; > } > + > +#ifdef RTE_EAL_PORT_IO > +/* Extract port I/O numbers from proc/ioports */ > +static int virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) > +{ > + uint16_t start, end; > + int size; > + FILE *fp; > + char *line = NULL; > + char pci_id[16]; > + int found = 0; > + size_t linesz; > + > + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, > + pci_dev->addr.domain, > + pci_dev->addr.bus, > + pci_dev->addr.devid, > + pci_dev->addr.function); > + > + fp = fopen("/proc/ioports", "r"); > + if (fp == NULL) { > + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); > + return -1; > + } > + > + while (getdelim(&line, &linesz, '\n', fp) > 0) { > + char *ptr = line; > + char *left; > + int n; > + > + n = strcspn(ptr, ":"); > + ptr[n] = 0; > + left = &ptr[n+1]; > + > + while (*left && isspace(*left)) > + left++; > + > + if (!strncmp(left, pci_id, strlen(pci_id))) { > + found = 1; > + > + while (*ptr && isspace(*ptr)) > + ptr++; > + > + sscanf(ptr, "%04hx-%04hx", &start, &end); > + size = end - start + 1; > + > + break; > + } > + } > + > + free(line); > + fclose(fp); > + > + if (!found) > + return -1; > + > + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_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; > +} > +#endif This part should be a Linux EAL service. > +#ifdef RTE_EAL_PORT_IO > +static struct eth_driver rte_virtio_pmd = { > + { > + .name = "rte_virtio_pmd", > + .id_table = pci_id_virtio_map, > + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_PORT_IO | Why does it need PCI mapping in port IO mode? > + RTE_PCI_DRV_INTR_LSC, > + }, > + .eth_dev_init = eth_virtio_dev_init, > + .dev_private_size = sizeof(struct virtio_hw), > +}; > +#else > static struct eth_driver rte_virtio_pmd = { > { > .name = "rte_virtio_pmd", This is the biggest problem. You are defining port IO as a different driver instead of providing a way to choose the method for each virtio device. I think that you should use devargs to configure the pci device. Thanks -- Thomas ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource. 2015-01-29 23:14 ` Thomas Monjalon @ 2015-02-04 1:31 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-02-04 1:31 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev Hi Thomas, > -----Original Message----- > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > Sent: Friday, January 30, 2015 7:14 AM > To: Ouyang, Changchun > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI > resource. > > Hi Changchun, > > 2015-01-29 15:24, Ouyang Changchun: > > Make virtio not require UIO for some security reasons, this is to match > 6Wind's virtio-net-pmd. > > Thanks for your effort. > I think port IO is a really interesting option but it needs more EAL rework to > be correctly integrated. Then virtio-net-pmd (http://dpdk.org/browse/virtio- > net-pmd/) > will be obsolete and moved in a deprecated area. > > > --- a/config/common_linuxapp > > +++ b/config/common_linuxapp > > +# Only for VIRTIO PMD currently > > +CONFIG_RTE_EAL_PORT_IO=n > > This is the first problem. We must stop adding new build-time options. > We should be able to choose between PCI mapping and port IO at runtime. > But I don't think choosing between PCI mapping and port IO at runtime is easy way, That means virtio-pmd need support both method, as we discussed before, port IO can't support lsc interrupt, while pci mapping can support lsc interrupt, they are contradict, e.g. the driver flag has issue to set its value. So I think using build flag should be a better way to let virtio-pmd determine its method at compilation time. > > +/** Device needs port IO(done with /proc/ioports) */ #ifdef > > +RTE_EAL_PORT_IO #define RTE_PCI_DRV_PORT_IO 0x0002 #endif > > A flag should never be ifdef'ed. I can remove the ifdef'ed. > > @@ -574,7 +574,10 @@ rte_eal_pci_probe_one_driver(struct > rte_pci_driver *dr, struct rte_pci_device *d > > /* map resources for devices that use igb_uio */ > > ret = pci_map_device(dev); > > if (ret != 0) > > - return ret; > > +#ifdef RTE_EAL_PORT_IO > > + if ((dr->drv_flags & RTE_PCI_DRV_PORT_IO) > == 0) #endif > > + return ret; > > } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && > > rte_eal_process_type() == RTE_PROC_PRIMARY) { > > /* unbind current driver */ > > Why do you need this ugly return? Without it, port-io method will return error when probe one driver the vritio device, As it don't use uio, so it can't map bar to virtual address. Here, just let port-io method don't check the return value of pci_map_device. > > > --- a/lib/librte_pmd_virtio/virtio_ethdev.c > > +++ b/lib/librte_pmd_virtio/virtio_ethdev.c > > @@ -961,6 +961,71 @@ static int virtio_resource_init(struct rte_pci_device > *pci_dev) > > start, size); > > return 0; > > } > > + > > +#ifdef RTE_EAL_PORT_IO > > +/* Extract port I/O numbers from proc/ioports */ static int > > +virtio_resource_init_by_portio(struct rte_pci_device *pci_dev) { > > + uint16_t start, end; > > + int size; > > + FILE *fp; > > + char *line = NULL; > > + char pci_id[16]; > > + int found = 0; > > + size_t linesz; > > + > > + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, > > + pci_dev->addr.domain, > > + pci_dev->addr.bus, > > + pci_dev->addr.devid, > > + pci_dev->addr.function); > > + > > + fp = fopen("/proc/ioports", "r"); > > + if (fp == NULL) { > > + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); > > + return -1; > > + } > > + > > + while (getdelim(&line, &linesz, '\n', fp) > 0) { > > + char *ptr = line; > > + char *left; > > + int n; > > + > > + n = strcspn(ptr, ":"); > > + ptr[n] = 0; > > + left = &ptr[n+1]; > > + > > + while (*left && isspace(*left)) > > + left++; > > + > > + if (!strncmp(left, pci_id, strlen(pci_id))) { > > + found = 1; > > + > > + while (*ptr && isspace(*ptr)) > > + ptr++; > > + > > + sscanf(ptr, "%04hx-%04hx", &start, &end); > > + size = end - start + 1; > > + > > + break; > > + } > > + } > > + > > + free(line); > > + fclose(fp); > > + > > + if (!found) > > + return -1; > > + > > + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_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; > > +} > > +#endif > > This part should be a Linux EAL service. As the port-io method is not used by other pmd code but only for virtio pmd, so we can say it is virtio specific codes, so Putting them here is good way. out of similar reason, the function get_uio_dev for uio method also is put here. So just keep the consistence between both uio and port-io methods. > > > +#ifdef RTE_EAL_PORT_IO > > +static struct eth_driver rte_virtio_pmd = { > > + { > > + .name = "rte_virtio_pmd", > > + .id_table = pci_id_virtio_map, > > + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | > RTE_PCI_DRV_PORT_IO | > > Why does it need PCI mapping in port IO mode? Good catch, I need remove the pci mapping here in next patch. > > > + RTE_PCI_DRV_INTR_LSC, > > + }, > > + .eth_dev_init = eth_virtio_dev_init, > > + .dev_private_size = sizeof(struct virtio_hw), }; #else > > static struct eth_driver rte_virtio_pmd = { > > { > > .name = "rte_virtio_pmd", > > This is the biggest problem. > You are defining port IO as a different driver instead of providing a way to > choose the method for each virtio device. > I think that you should use devargs to configure the pci device. Do you mean I need new rte_devtype to handle it? Currently the implement check if the virtio dev is bind to igb_uio or not, If it bind to igb_uio, then it use uio/mapping method to get the address, If it doesn't bind to igb_uio, and it is in white list, then use port-io method to get the address. I don't see any big issue here for the logic. Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 18/25] virtio: Fix descriptor index issue 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (16 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue Ouyang Changchun ` (7 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev It should use vring descriptor index instead of used_ring index to index vq_descx. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 580701a..a82e8eb 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; - dxp = &vq->vq_descx[used_idx]; desc_idx = (uint16_t) uep->id; + dxp = &vq->vq_descx[desc_idx]; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (17 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 18/25] virtio: Fix descriptor index issue Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-02-04 10:54 ` Xie, Huawei 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 20/25] example/vhost: Avoid inserting vlan twice Ouyang Changchun ` (6 subsequent siblings) 25 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev Need swap the data from cpu to BE(big endian) for vlan-type. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 74f71c2..0797908 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -351,7 +351,7 @@ 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) + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) return -1; struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); @@ -401,7 +401,7 @@ static inline int rte_vlan_insert(struct rte_mbuf **m) return -ENOSPC; memmove(nh, oh, 2 * ETHER_ADDR_LEN); - nh->ether_type = ETHER_TYPE_VLAN; + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vh = (struct vlan_hdr *) (nh + 1); vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue Ouyang Changchun @ 2015-02-04 10:54 ` Xie, Huawei 2015-02-05 0:54 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-02-04 10:54 UTC (permalink / raw) To: Ouyang, Changchun, dev On 1/29/2015 3:24 PM, Ouyang Changchun wrote: > Need swap the data from cpu to BE(big endian) for vlan-type. > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > --- > lib/librte_ether/rte_ether.h | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h > index 74f71c2..0797908 100644 > --- a/lib/librte_ether/rte_ether.h > +++ b/lib/librte_ether/rte_ether.h > @@ -351,7 +351,7 @@ 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) > + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) rte_be_to_cpu_16? > return -1; > > struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); > @@ -401,7 +401,7 @@ static inline int rte_vlan_insert(struct rte_mbuf > **m) > return -ENOSPC; > > memmove(nh, oh, 2 * ETHER_ADDR_LEN); > - nh->ether_type = ETHER_TYPE_VLAN; > + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); rte_be_to_cpu_16? > > vh = (struct vlan_hdr *) (nh + 1); > vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue 2015-02-04 10:54 ` Xie, Huawei @ 2015-02-05 0:54 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-02-05 0:54 UTC (permalink / raw) To: Xie, Huawei, dev Hi huawei, > -----Original Message----- > From: Xie, Huawei > Sent: Wednesday, February 4, 2015 6:54 PM > To: Ouyang, Changchun; dev@dpdk.org > Cc: stephen@networkplumber.org; Cao, Waterman; Xu, Qian Q > Subject: Re: [PATCH v3 19/25] ether: Fix vlan strip/insert issue > > On 1/29/2015 3:24 PM, Ouyang Changchun wrote: > > Need swap the data from cpu to BE(big endian) for vlan-type. > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > --- > > lib/librte_ether/rte_ether.h | 4 ++-- > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > diff --git a/lib/librte_ether/rte_ether.h > > b/lib/librte_ether/rte_ether.h index 74f71c2..0797908 100644 > > --- a/lib/librte_ether/rte_ether.h > > +++ b/lib/librte_ether/rte_ether.h > > @@ -351,7 +351,7 @@ 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) > > + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) > rte_be_to_cpu_16? Eh->ether_type is in network byte order(big endian), While ETHER_TYPE_VLAN is host byte order(little endian on x86), so it need change into big endian. > > return -1; > > > > struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); @@ -401,7 > > +401,7 @@ static inline int rte_vlan_insert(struct rte_mbuf > > **m) > > return -ENOSPC; > > > > memmove(nh, oh, 2 * ETHER_ADDR_LEN); > > - nh->ether_type = ETHER_TYPE_VLAN; > > + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); > rte_be_to_cpu_16? Similar reason as above. Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 20/25] example/vhost: Avoid inserting vlan twice 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (18 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 21/25] example/vhost: Add vlan-strip cmd line option Ouyang Changchun ` (5 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev Check if it has already been vlan-tagged packet, if true, avoid inserting a duplicated vlan tag into it. This is a possible case when guest has the capability of inserting vlan tag. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 04f0118..6af7874 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -1115,6 +1115,7 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) unsigned len, ret, offset = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; + struct ether_hdr *nh; /*check if destination is local VM*/ if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) { @@ -1135,28 +1136,38 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; - m->ol_flags = PKT_TX_VLAN_PKT; + nh = rte_pktmbuf_mtod(m, struct ether_hdr *); + if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) { + /* Guest has inserted the vlan tag. */ + struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1); + uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag); + if ((vm2vm_mode == VM2VM_HARDWARE) && + (vh->vlan_tci != vlan_tag_be)) + vh->vlan_tci = vlan_tag_be; + } else { + m->ol_flags = PKT_TX_VLAN_PKT; - /* - * Find the right seg to adjust the data len when offset is - * bigger than tail room size. - */ - if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { - if (likely(offset <= rte_pktmbuf_tailroom(m))) - m->data_len += offset; - else { - struct rte_mbuf *seg = m; + /* + * Find the right seg to adjust the data len when offset is + * bigger than tail room size. + */ + if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { + if (likely(offset <= rte_pktmbuf_tailroom(m))) + m->data_len += offset; + else { + struct rte_mbuf *seg = m; - while ((seg->next != NULL) && - (offset > rte_pktmbuf_tailroom(seg))) - seg = seg->next; + while ((seg->next != NULL) && + (offset > rte_pktmbuf_tailroom(seg))) + seg = seg->next; - seg->data_len += offset; + seg->data_len += offset; + } + m->pkt_len += offset; } - m->pkt_len += offset; - } - m->vlan_tci = vlan_tag; + m->vlan_tci = vlan_tag; + } tx_q->m_table[len] = m; len++; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 21/25] example/vhost: Add vlan-strip cmd line option 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (19 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 20/25] example/vhost: Avoid inserting vlan twice Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 22/25] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun ` (4 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev Support turn on/off RX VLAN strip on host, this let guest get the chance of using its software VALN strip functionality. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 6af7874..1876c8e 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -159,6 +159,9 @@ static uint32_t num_devices; static uint32_t zero_copy; static int mergeable; +/* Do vlan strip on host, enabled on default */ +static uint32_t vlan_strip = 1; + /* number of descriptors to apply*/ static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP; static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP; @@ -564,6 +567,7 @@ us_vhost_usage(const char *prgname) " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n" " --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n" + " --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n" " --zero-copy [0|1]: disable(default)/enable rx/tx " @@ -591,6 +595,7 @@ us_vhost_parse_args(int argc, char **argv) {"rx-retry-delay", required_argument, NULL, 0}, {"rx-retry-num", required_argument, NULL, 0}, {"mergeable", required_argument, NULL, 0}, + {"vlan-strip", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {"dev-basename", required_argument, NULL, 0}, {"zero-copy", required_argument, NULL, 0}, @@ -691,6 +696,22 @@ us_vhost_parse_args(int argc, char **argv) } } + /* Enable/disable RX VLAN strip on host. */ + if (!strncmp(long_option[option_index].name, + "vlan-strip", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, + "Invalid argument for VLAN strip [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else { + vlan_strip = !!ret; + vmdq_conf_default.rxmode.hw_vlan_strip = + vlan_strip; + } + } + /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); @@ -950,7 +971,9 @@ link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m) dev->device_fh); /* Enable stripping of the vlan tag as we handle routing. */ - rte_eth_dev_set_vlan_strip_on_queue(ports[0], (uint16_t)vdev->vmdq_rx_q, 1); + if (vlan_strip) + rte_eth_dev_set_vlan_strip_on_queue(ports[0], + (uint16_t)vdev->vmdq_rx_q, 1); /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 22/25] virtio: Use soft vlan strip in mergeable Rx path 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (20 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 21/25] example/vhost: Add vlan-strip cmd line option Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 23/25] virtio: Fix zero copy break issue Ouyang Changchun ` (3 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev To keep the consistent logic with normal Rx path, the mergeable Rx path also needs software vlan strip/decap if it is enabled. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82e8eb..c6d9ae7 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, 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]; @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, seg_res -= rcv_cnt; } + if (hw->vlan_strip) + rte_vlan_strip(rx_pkts[nb_rx]); + VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], rx_pkts[nb_rx]->data_len); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 23/25] virtio: Fix zero copy break issue 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (21 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 22/25] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 24/25] virtio: Remove hotspots Ouyang Changchun ` (2 subsequent siblings) 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev vHOST zero copy need get vring descriptor and its buffer address to set the DMA address of HW ring, it is done in new_device when ioctl set_backend is called. This requies virtio_dev_rxtx_start is called before vtpci_reinit_complete, which makes sure the vring descriptro and its buffer is ready before its using. this patch also fixes one set status issue, according to virtio spec, VIRTIO_CONFIG_STATUS_ACK should be set after virtio hw reset. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b905532..648c761 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -414,6 +414,7 @@ virtio_dev_close(struct rte_eth_dev *dev) /* reset the NIC */ vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); + hw->started = 0; virtio_dev_free_mbufs(dev); } @@ -1107,9 +1108,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return -ENOMEM; } - /* 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) #ifdef RTE_EAL_PORT_IO @@ -1123,6 +1121,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -1324,10 +1325,10 @@ virtio_dev_start(struct rte_eth_dev *dev) if (hw->started) return 0; - vtpci_reinit_complete(hw); - /* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start(dev); + vtpci_reinit_complete(hw); + hw->started = 1; /*Notify the backend -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 24/25] virtio: Remove hotspots 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (22 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 23/25] virtio: Fix zero copy break issue Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 25/25] virtio: Fix wmb issue Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev Remove those hotspots which is unnecessary when early returning occurs; Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c6d9ae7..0225cc9 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -476,13 +476,13 @@ 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 virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; int error; - uint32_t i, nb_enqueued = 0; + uint32_t i, nb_enqueued; const uint32_t hdr_size = sizeof(struct virtio_net_hdr); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -499,6 +499,11 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, num); PMD_RX_LOG(DEBUG, "used:%d dequeue:%d", nb_used, num); + + hw = rxvq->hw; + nb_rx = 0; + nb_enqueued = 0; + for (i = 0; i < num ; i++) { rxm = rcv_pkts[i]; @@ -568,17 +573,17 @@ virtio_recv_mergeable_pkts(void *rx_queue, uint16_t nb_pkts) { struct virtqueue *rxvq = rx_queue; - struct virtio_hw *hw = rxvq->hw; + struct virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *prev; int error; - uint32_t i = 0, nb_enqueued = 0; - uint32_t seg_num = 0; - uint16_t extra_idx = 0; - uint32_t seg_res = 0; + uint32_t i, nb_enqueued; + uint32_t seg_num; + uint16_t extra_idx; + uint32_t seg_res; const uint32_t hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -590,6 +595,14 @@ virtio_recv_mergeable_pkts(void *rx_queue, PMD_RX_LOG(DEBUG, "used:%d\n", nb_used); + hw = rxvq->hw; + nb_rx = 0; + i = 0; + nb_enqueued = 0; + seg_num = 0; + extra_idx = 0; + seg_res = 0; + while (i < nb_used) { struct virtio_net_hdr_mrg_rxbuf *header; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v3 25/25] virtio: Fix wmb issue 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (23 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 24/25] virtio: Remove hotspots Ouyang Changchun @ 2015-01-29 7:24 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun 25 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-01-29 7:24 UTC (permalink / raw) To: dev It needs use virtio_wmb instead of virtio_rmb for store memory barrier. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 6c45c27..41dda50 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -266,7 +266,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - virtio_rmb(); + virtio_wmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 00/26] Single virtio implementation 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun ` (24 preceding siblings ...) 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 25/25] virtio: Fix wmb issue Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 01/26] virtio: Rearrange resource initialization Ouyang Changchun ` (26 more replies) 25 siblings, 27 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev This is the patch set for single virtio implementation. Why we need single virtio? ============================ As we know currently there are at least 3 virtio PMD driver implementations: A) lib/librte_pmd_virtio(refer as virtio A); B) virtio_net_pmd by 6wind(refer as virtio B); C) virtio by Brocade/vyatta(refer as virtio C); Integrating 3 implementations into one could reduce the maintaining cost and time, in other hand, user don't need practice their application on 3 variant one by one to see which one is the best for them; What's the status? ==================== Currently virtio A has covered most features of virtio B except for using port io to get pci resource, so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some issues in original codes. What this patch set contains: =============================== 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; 2) virtio: Use weaker barriers, as 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 may help performance a bit; 3) virtio: Allow starting with link down, other driver has similar behavior; 4) virtio: Add support for Link State interrupt; 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; 6) virtio: Use software vlan stripping; 7) virtio: Remove unnecessary adapter structure; 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; 10) virtio: Make vtpci_get_status a local function as it is used in one file; 11) virtio: Check for packet headroom at compile time; 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; 13) virtio: Add support for vlan filtering; 14) virtio: Add support for multiple mac addresses; 15) virtio: Add ability to set MAC address; 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; 18) virtio: Fix descriptor index issue; 19) ether: Fix vlan strip/insert issue; 20) example/vhost: Avoid inserting vlan twice and guest and host; 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic with the normal Rx path. Changes in v2: 23) virtio: Fix zero copy break issue, the vring should be ready before virtio PMD set the status of DRIVER_OK; 24) virtio: Remove unnecessary hotspots in data path. Changes in v3: 25) virtio: Fix wmb issue; 26) Fix one minor issue in patch 20, also fix its idention. Changes in v4: 27) Fix updating vring descriptor index issue and memory barrier issue; 28) Reslove comments for patch 17. Changchun Ouyang (10): virtio: Use port IO to get PCI resource. virtio: Fix descriptor index issue ether: Fix vlan strip/insert issue example/vhost: Avoid inserting vlan twice example/vhost: Add vlan-strip cmd line option virtio: Use soft vlan strip in mergeable Rx path virtio: Fix zero copy break issue virtio: Remove hotspots virtio: Fix wmb issue virtio: Fix updating vring descriptor index issue Stephen Hemminger (16): virtio: Rearrange resource initialization virtio: Use weaker barriers virtio: Allow starting with link down virtio: Add support for Link State interrupt ether: Add soft vlan encap/decap functions virtio: Use software vlan stripping virtio: Remove unnecessary adapter structure virtio: Remove redundant vq_alignment virtio: Fix how states are handled during initialization virtio: Make vtpci_get_status local virtio: Check for packet headroom at compile time virtio: Move allocation before initialization virtio: Add support for vlan filtering virtio: Add suport for multiple mac addresses virtio: Add ability to set MAC address virtio: Free mbuf's with threshold examples/vhost/main.c | 70 +++-- lib/librte_ether/rte_ethdev.h | 8 + lib/librte_ether/rte_ether.h | 76 +++++ lib/librte_pmd_virtio/Makefile | 2 + lib/librte_pmd_virtio/virtio_ethdev.c | 519 ++++++++++++++++++++++++++-------- lib/librte_pmd_virtio/virtio_ethdev.h | 12 +- lib/librte_pmd_virtio/virtio_pci.c | 20 +- lib/librte_pmd_virtio/virtio_pci.h | 8 +- lib/librte_pmd_virtio/virtio_rxtx.c | 154 +++++++--- lib/librte_pmd_virtio/virtqueue.h | 59 +++- 10 files changed, 729 insertions(+), 199 deletions(-) -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 01/26] virtio: Rearrange resource initialization 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 02/26] virtio: Use weaker barriers Ouyang Changchun ` (25 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 76 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b3b5bb6..662a49c 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -794,6 +794,41 @@ virtio_has_msix(const struct rte_pci_addr *loc) 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) @@ -801,6 +836,12 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) /* 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 /* @@ -831,40 +872,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return 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; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 02/26] virtio: Use weaker barriers 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 01/26] virtio: Rearrange resource initialization Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 03/26] virtio: Allow starting with link down Ouyang Changchun ` (24 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev The 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. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 662a49c..dc47e72 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -175,7 +175,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, uint32_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)); diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c013f97..78af334 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -456,7 +456,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) 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); @@ -516,6 +516,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } if (likely(nb_enqueued)) { + virtio_wmb(); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); @@ -547,7 +548,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, nb_used = VIRTQUEUE_NUSED(rxvq); - rmb(); + virtio_rmb(); if (nb_used == 0) return 0; @@ -694,7 +695,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) PMD_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); @@ -735,6 +736,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) } } vq_update_avail_idx(txvq); + virtio_wmb(); txvq->packets += nb_tx; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index fdee054..f6ad98d 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -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) @@ -225,7 +234,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - rte_compiler_barrier(); + virtio_rmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } @@ -255,7 +264,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. */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 03/26] virtio: Allow starting with link down 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 01/26] virtio: Rearrange resource initialization Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 02/26] virtio: Use weaker barriers Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 04/26] virtio: Add support for Link State interrupt Ouyang Changchun ` (23 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Starting driver with link down should be ok, it is with every other driver. So just allow it. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index dc47e72..5df3b54 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1057,14 +1057,12 @@ virtio_dev_start(struct rte_eth_dev *dev) vtpci_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); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 04/26] virtio: Add support for Link State interrupt 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (2 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 03/26] virtio: Allow starting with link down Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 05/26] ether: Add soft vlan encap/decap functions Ouyang Changchun ` (22 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Virtio has link state interrupt which can be used. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 5df3b54..ef87ff8 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) #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. */ @@ -968,6 +996,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, PMD_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; } @@ -975,7 +1007,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), @@ -1021,6 +1053,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"); @@ -1029,7 +1064,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return (-EINVAL); } - return 0; + ret = vtpci_irq_config(hw, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, "failed to set config vector"); + + return ret; } @@ -1037,7 +1076,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); @@ -1052,18 +1090,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 @@ -1145,6 +1187,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); } @@ -1161,6 +1204,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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, @@ -1179,10 +1223,8 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet 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 diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index ca9c748..6d51032 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uint8_t status) VIRTIO_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; +} diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 373f9dc..6998737 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void 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_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 05/26] ether: Add soft vlan encap/decap functions 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (3 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 04/26] virtio: Add support for Link State interrupt Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 06/26] virtio: Use software vlan stripping Ouyang Changchun ` (21 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev It is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software. This allows application to be device independent. Avoid discarding shared mbufs. Make a copy in rte_vlan_insert() of any packet to be tagged that has a reference count > 1. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 7e7d22c..74f71c2 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -49,6 +49,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. */ @@ -333,6 +335,80 @@ struct vxlan_hdr { #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) /**< VXLAN tunnel header length. */ +/** + * 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->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_REFCNT + /* Can't insert header if mbuf is shared */ + if (rte_mbuf_refcnt_read(*m) > 1) { + struct rte_mbuf *copy; + + copy = rte_pktmbuf_clone(*m, (*m)->pool); + if (unlikely(copy == NULL)) + return -ENOMEM; + rte_pktmbuf_free(*m); + *m = copy; + } +#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)->vlan_tci); + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 06/26] virtio: Use software vlan stripping 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (4 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 05/26] ether: Add soft vlan encap/decap functions Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 07/26] virtio: Remove unnecessary adapter structure Ouyang Changchun ` (20 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Implement VLAN stripping in software. This allows application to be device independent. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 3 +++ lib/librte_pmd_virtio/virtio_ethdev.c | 2 ++ lib/librte_pmd_virtio/virtio_pci.h | 1 + lib/librte_pmd_virtio/virtio_rxtx.c | 20 ++++++++++++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 1200c1c..94d6b2b 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -643,6 +643,9 @@ struct rte_eth_rxconf { #define ETH_TXQ_FLAGS_NOOFFLOADS \ (ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | \ ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) +#define ETH_TXQ_FLAGS_NOXSUMS \ + (ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ + ETH_TXQ_FLAGS_NOXSUMTCP) /** * A structure used to configure a TX ring of an Ethernet port. */ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index ef87ff8..da74659 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -1064,6 +1064,8 @@ virtio_dev_configure(struct rte_eth_dev *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"); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6998737..6d93fac 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -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]; }; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 78af334..e0216ec 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -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" @@ -408,8 +409,8 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, 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; } @@ -446,6 +447,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]; @@ -489,6 +491,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->pkt_len = (uint32_t)(len[i] - hdr_size); rxm->data_len = (uint16_t)(len[i] - hdr_size); + if (hw->vlan_strip) + rte_vlan_strip(rxm); + VIRTIO_DUMP_PACKET(rxm, rxm->data_len); rx_pkts[nb_rx++] = rxm; @@ -717,6 +722,17 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) */ if (likely(need <= 0)) { 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)) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 07/26] virtio: Remove unnecessary adapter structure 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (5 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 06/26] virtio: Use software vlan stripping Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 08/26] virtio: Remove redundant vq_alignment Ouyang Changchun ` (19 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Cleanup virtio code by eliminating unnecessary nesting of virtio hardware structure inside adapter structure. Also allows removing unneeded macro, making code clearer. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 43 ++++++++++++----------------------- lib/librte_pmd_virtio/virtio_ethdev.h | 9 -------- lib/librte_pmd_virtio/virtio_rxtx.c | 3 +-- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index da74659..59b74b7 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -207,8 +207,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, static 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; @@ -242,8 +241,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, const 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 */ @@ -383,8 +381,7 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, struct 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, @@ -410,8 +407,7 @@ virtio_dev_close(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -430,8 +426,7 @@ virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) static void virtio_dev_promiscuous_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -450,8 +445,7 @@ virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_enable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -470,8 +464,7 @@ virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) static void virtio_dev_allmulticast_disable(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; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; @@ -853,8 +846,7 @@ 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); + struct virtio_hw *hw = dev->data->dev_private; uint8_t isr; /* Read interrupt status which clears interrupt */ @@ -880,12 +872,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, @@ -1010,7 +1001,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), }; /* @@ -1053,8 +1044,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"); @@ -1078,8 +1068,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); @@ -1185,8 +1174,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) static 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); @@ -1199,8 +1187,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet { 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; @@ -1232,7 +1219,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet static 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; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 1da3c62..55c9749 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -110,15 +110,6 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_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 diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index e0216ec..a82d5ff 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -326,8 +326,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) void 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; if (hw->cvq) { virtio_dev_vring_start(hw->cvq, VTNET_CQ); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 08/26] virtio: Remove redundant vq_alignment 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (6 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 07/26] virtio: Remove unnecessary adapter structure Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 09/26] virtio: Fix how states are handled during initialization Ouyang Changchun ` (18 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Since vq_alignment is constant (always 4K), it does not need to be part of the vring struct. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- 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(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 59b74b7..0d41e7f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -294,7 +294,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, 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; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82d5ff..b6d6832 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -258,7 +258,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) * 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; diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index f6ad98d..5b8a255 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -138,8 +138,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 */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 09/26] virtio: Fix how states are handled during initialization 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (7 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 08/26] virtio: Remove redundant vq_alignment Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 10/26] virtio: Make vtpci_get_status local Ouyang Changchun ` (17 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Change order of initialiazation to match Linux kernel. Don't blow away control queue by doing reset when stopped. Calling dev_stop then dev_start would not work. Dev_stop was calling virtio reset and that would clear all queues and clear all feature negotiation. Resolved by only doing reset on device removal. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 58 ++++++++++++++++++++--------------- lib/librte_pmd_virtio/virtio_pci.c | 10 ++---- lib/librte_pmd_virtio/virtio_pci.h | 3 +- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0d41e7f..47dd33d 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -398,9 +398,14 @@ virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, static void virtio_dev_close(struct rte_eth_dev *dev) { + struct virtio_hw *hw = dev->data->dev_private; + PMD_INIT_LOG(DEBUG, "virtio_dev_close"); - virtio_dev_stop(dev); + /* reset the NIC */ + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + vtpci_reset(hw); + virtio_dev_free_mbufs(dev); } static void @@ -889,6 +894,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (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; @@ -899,9 +907,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -990,6 +995,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* Setup interrupt callback */ rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); + + virtio_dev_cq_start(eth_dev); + return 0; } @@ -1044,7 +1052,6 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; - int ret; PMD_INIT_LOG(DEBUG, "configure"); @@ -1055,11 +1062,12 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; - ret = vtpci_irq_config(hw, 0); - if (ret != 0) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } - return ret; + return 0; } @@ -1069,17 +1077,6 @@ 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); - /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { @@ -1096,8 +1093,16 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Initialize Link state */ virtio_dev_link_update(dev, 0); + /* On restart after stop do not touch queues */ + if (hw->started) + return 0; + vtpci_reinit_complete(hw); + /* Do final configuration before rx/tx engine starts */ + virtio_dev_rxtx_start(dev); + hw->started = 1; + /*Notify the backend *Otherwise the tap backend might already stop its queue due to fullness. *vhost backend will have no chance to be waked up @@ -1168,17 +1173,20 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) } /* - * Stop device: disable rx and tx functions to allow for reconfiguring. + * Stop device: disable interrupt and mark link down */ static void virtio_dev_stop(struct rte_eth_dev *dev) { - struct virtio_hw *hw = dev->data->dev_private; + struct rte_eth_link link; - /* reset the NIC */ - vtpci_irq_config(hw, 0); - vtpci_reset(hw); - virtio_dev_free_mbufs(dev); + PMD_INIT_LOG(DEBUG, "stop"); + + if (dev->data->dev_conf.intr_conf.lsc) + rte_intr_disable(&dev->pci_dev->intr_handle); + + memset(&link, 0, sizeof(link)); + virtio_dev_atomic_write_link_status(dev, &link); } static int diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index 6d51032..b099e4f 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -137,15 +137,9 @@ vtpci_isr(struct virtio_hw *hw) /* Enable one vector (0) for Link State Intrerrupt */ -int +uint16_t 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; + return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); } diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 6d93fac..0a4b578 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -170,6 +170,7 @@ struct virtio_hw { uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; + uint8_t started; uint8_t mac_addr[ETHER_ADDR_LEN]; }; @@ -266,6 +267,6 @@ void 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); +uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); #endif /* _VIRTIO_PCI_H_ */ -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 10/26] virtio: Make vtpci_get_status local 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (8 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 09/26] virtio: Fix how states are handled during initialization Ouyang Changchun @ 2015-02-09 1:13 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 11/26] virtio: Check for packet headroom at compile time Ouyang Changchun ` (16 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:13 UTC (permalink / raw) To: dev Make vtpci_get_status a local function as it is used in one file. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_pci.c | 4 +++- lib/librte_pmd_virtio/virtio_pci.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index b099e4f..2245bec 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -35,6 +35,8 @@ #include "virtio_pci.h" #include "virtio_logs.h" +static uint8_t vtpci_get_status(struct virtio_hw *); + void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) @@ -113,7 +115,7 @@ vtpci_reinit_complete(struct virtio_hw *hw) vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); } -uint8_t +static uint8_t vtpci_get_status(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 0a4b578..64d9c34 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -255,8 +255,6 @@ void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); -uint8_t vtpci_get_status(struct virtio_hw *); - void vtpci_set_status(struct virtio_hw *, uint8_t); uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 11/26] virtio: Check for packet headroom at compile time 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (9 preceding siblings ...) 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 10/26] virtio: Make vtpci_get_status local Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 12/26] virtio: Move allocation before initialization Ouyang Changchun ` (15 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Better to check at compile time than fail at runtime. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 47dd33d..9679c2f 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -882,11 +882,7 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; - if (RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)) { - PMD_INIT_LOG(ERR, - "MBUF HEADROOM should be enough to hold virtio net hdr\n"); - return -1; - } + RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); eth_dev->dev_ops = &virtio_eth_dev_ops; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 12/26] virtio: Move allocation before initialization 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (10 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 11/26] virtio: Check for packet headroom at compile time Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 13/26] virtio: Add support for vlan filtering Ouyang Changchun ` (14 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev If allocation fails, don't want to leave virtio device stuck in middle of initialization sequence. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 9679c2f..39b1fb4 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -890,6 +890,15 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, + "Failed to allocate %d bytes needed to store MAC addresses", + ETHER_ADDR_LEN); + return -ENOMEM; + } + /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); @@ -916,15 +925,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr); } - /* Allocate memory for storing MAC addresses */ - eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); - if (eth_dev->data->mac_addrs == NULL) { - PMD_INIT_LOG(ERR, - "Failed to allocate %d bytes needed to store MAC addresses", - ETHER_ADDR_LEN); - return -ENOMEM; - } - /* Copy the permanent MAC address to: virtio_hw */ virtio_get_hwaddr(hw); ether_addr_copy((struct ether_addr *) hw->mac_addr, -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 13/26] virtio: Add support for vlan filtering 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (11 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 12/26] virtio: Move allocation before initialization Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 14/26] virtio: Add suport for multiple mac addresses Ouyang Changchun ` (13 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Virtio supports vlan filtering. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 39b1fb4..591d692 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -84,6 +84,8 @@ static void virtio_dev_tx_queue_release(__rte_unused void *txq); 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); +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, + uint16_t vlan_id, int on); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -511,6 +513,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, + .vlan_filter_set = virtio_vlan_filter_set, }; static inline int @@ -640,14 +643,31 @@ virtio_get_hwaddr(struct virtio_hw *hw) } } +static int +virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtio_pmd_ctrl ctrl; + int len; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) + return -ENOTSUP; + + ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN; + ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; + memcpy(ctrl.data, &vlan_id, sizeof(vlan_id)); + len = sizeof(vlan_id); + + return virtio_send_command(hw->cvq, &ctrl, &len, 1); +} static void virtio_negotiate_features(struct virtio_hw *hw) { uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_VLAN; - mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; + /* checksum offload not implemented */ + mask = VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding * checksum offload feature is also negotiated. @@ -1058,6 +1078,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) hw->vlan_strip = rxmode->hw_vlan_strip; + if (rxmode->hw_vlan_filter + && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { + PMD_DRV_LOG(NOTICE, + "vlan filtering not available on this host"); + return -ENOTSUP; + } + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); return -EBUSY; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 14/26] virtio: Add suport for multiple mac addresses 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (12 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 13/26] virtio: Add support for vlan filtering Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 15/26] virtio: Add ability to set MAC address Ouyang Changchun ` (12 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Virtio support multiple MAC addresses. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 94 ++++++++++++++++++++++++++++++++++- lib/librte_pmd_virtio/virtio_ethdev.h | 3 +- lib/librte_pmd_virtio/virtqueue.h | 34 ++++++++++++- 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 591d692..0e74eea 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -86,6 +86,10 @@ static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); +static void virtio_mac_addr_add(struct rte_eth_dev *dev, + struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused); +static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -503,8 +507,6 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .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, /* meaningfull only to multiple queue */ .rx_queue_release = virtio_dev_rx_queue_release, @@ -514,6 +516,8 @@ static struct eth_dev_ops virtio_eth_dev_ops = { /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, .vlan_filter_set = virtio_vlan_filter_set, + .mac_addr_add = virtio_mac_addr_add, + .mac_addr_remove = virtio_mac_addr_remove, }; static inline int @@ -644,6 +648,92 @@ virtio_get_hwaddr(struct virtio_hw *hw) } static int +virtio_mac_table_set(struct virtio_hw *hw, + const struct virtio_net_ctrl_mac *uc, + const struct virtio_net_ctrl_mac *mc) +{ + struct virtio_pmd_ctrl ctrl; + int err, len[2]; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET; + + len[0] = uc->entries * ETHER_ADDR_LEN + sizeof(uc->entries); + memcpy(ctrl.data, uc, len[0]); + + len[1] = mc->entries * ETHER_ADDR_LEN + sizeof(mc->entries); + memcpy(ctrl.data + len[0], mc, len[1]); + + err = virtio_send_command(hw->cvq, &ctrl, len, 2); + if (err != 0) + PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err); + + return err; +} + +static void +virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq __rte_unused) +{ + struct virtio_hw *hw = dev->data->dev_private; + const struct ether_addr *addrs = dev->data->mac_addrs; + unsigned int i; + struct virtio_net_ctrl_mac *uc, *mc; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + const struct ether_addr *addr + = (i == index) ? mac_addr : addrs + i; + struct virtio_net_ctrl_mac *tbl + = is_multicast_ether_addr(addr) ? mc : uc; + + memcpy(&tbl->macs[tbl->entries++], addr, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static void +virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct ether_addr *addrs = dev->data->mac_addrs; + struct virtio_net_ctrl_mac *uc, *mc; + unsigned int i; + + if (index >= VIRTIO_MAX_MAC_ADDRS) { + PMD_DRV_LOG(ERR, "mac address index %u out of range", index); + return; + } + + uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); + uc->entries = 0; + mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); + mc->entries = 0; + + for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { + struct virtio_net_ctrl_mac *tbl; + + if (i == index || is_zero_ether_addr(addrs + i)) + continue; + + tbl = is_multicast_ether_addr(addrs + i) ? mc : uc; + memcpy(&tbl->macs[tbl->entries++], addrs + i, ETHER_ADDR_LEN); + } + + virtio_mac_table_set(hw, uc, mc); +} + +static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct virtio_hw *hw = dev->data->dev_private; diff --git a/lib/librte_pmd_virtio/virtio_ethdev.h b/lib/librte_pmd_virtio/virtio_ethdev.h index 55c9749..74ac7e0 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.h +++ b/lib/librte_pmd_virtio/virtio_ethdev.h @@ -51,7 +51,7 @@ #define VIRTIO_MAX_RX_QUEUES 128 #define VIRTIO_MAX_TX_QUEUES 128 -#define VIRTIO_MAX_MAC_ADDRS 1 +#define VIRTIO_MAX_MAC_ADDRS 64 #define VIRTIO_MIN_RX_BUFSIZE 64 #define VIRTIO_MAX_RX_PKTLEN 9728 @@ -60,6 +60,7 @@ (VIRTIO_NET_F_MAC | \ VIRTIO_NET_F_STATUS | \ VIRTIO_NET_F_MQ | \ + VIRTIO_NET_F_CTRL_MAC_ADDR | \ VIRTIO_NET_F_CTRL_VQ | \ VIRTIO_NET_F_CTRL_RX | \ VIRTIO_NET_F_CTRL_VLAN | \ diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 5b8a255..d210f4f 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -99,6 +99,34 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; #define VIRTIO_NET_CTRL_RX_NOBCAST 5 /** + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + uint32_t entries; + uint8_t macs[][ETHER_ADDR_LEN]; +} __attribute__((__packed__)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/** * Control VLAN filtering * * The VLAN filter table is controlled via a simple ADD/DEL interface. @@ -121,7 +149,7 @@ typedef uint8_t virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_MAX_CTRL_DATA 128 +#define VIRTIO_MAX_CTRL_DATA 2048 struct virtio_pmd_ctrl { struct virtio_net_ctrl_hdr hdr; @@ -180,6 +208,10 @@ struct virtqueue { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 #endif +#ifndef VIRTIO_NET_F_CTRL_MAC_ADDR +#define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 +#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 +#endif /** * This is the first element of the scatter-gather list. If you don't -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 15/26] virtio: Add ability to set MAC address 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (13 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 14/26] virtio: Add suport for multiple mac addresses Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 16/26] virtio: Free mbuf's with threshold Ouyang Changchun ` (11 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Need to have do special things to set default mac address. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ethdev.h | 5 +++++ lib/librte_pmd_virtio/virtio_ethdev.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 94d6b2b..5a54276 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1240,6 +1240,10 @@ typedef void (*eth_mac_addr_add_t)(struct rte_eth_dev *dev, uint32_t vmdq); /**< @internal Set a MAC address into Receive Address Address Register */ +typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); +/**< @internal Set a MAC address into Receive Address Address Register */ + typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint8_t on); @@ -1459,6 +1463,7 @@ struct eth_dev_ops { priority_flow_ctrl_set_t priority_flow_ctrl_set; /**< Setup priority flow control.*/ eth_mac_addr_remove_t mac_addr_remove; /**< Remove MAC address */ eth_mac_addr_add_t mac_addr_add; /**< Add a MAC address */ + eth_mac_addr_set_t mac_addr_set; /**< Set a MAC address */ eth_uc_hash_table_set_t uc_hash_table_set; /**< Set Unicast Table Array */ eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */ eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/ diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 0e74eea..b30ab2a 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -90,6 +90,8 @@ static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused); static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); +static void virtio_mac_addr_set(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, @@ -518,6 +520,7 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .vlan_filter_set = virtio_vlan_filter_set, .mac_addr_add = virtio_mac_addr_add, .mac_addr_remove = virtio_mac_addr_remove, + .mac_addr_set = virtio_mac_addr_set, }; static inline int @@ -733,6 +736,27 @@ virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) virtio_mac_table_set(hw, uc, mc); } +static void +virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) +{ + struct virtio_hw *hw = dev->data->dev_private; + + memcpy(hw->mac_addr, mac_addr, ETHER_ADDR_LEN); + + /* Use atomic update if available */ + if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { + struct virtio_pmd_ctrl ctrl; + int len = ETHER_ADDR_LEN; + + ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; + + memcpy(ctrl.data, mac_addr, ETHER_ADDR_LEN); + virtio_send_command(hw->cvq, &ctrl, &len, 1); + } else if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) + virtio_set_hwaddr(hw); +} + static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 16/26] virtio: Free mbuf's with threshold 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (14 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 15/26] virtio: Add ability to set MAC address Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource Ouyang Changchun ` (10 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev This makes virtio driver work like ixgbe. Transmit buffers are held until a transmit threshold is reached. The previous behavior was to hold mbuf's until the ring entry was reused which caused more memory usage than needed. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 7 ++-- lib/librte_pmd_virtio/virtio_rxtx.c | 75 +++++++++++++++++++++++++---------- lib/librte_pmd_virtio/virtqueue.h | 3 +- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index b30ab2a..8cd2d51 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -176,15 +176,16 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, virtqueue_notify(vq); - while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) + rte_rmb(); + while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { + rte_rmb(); usleep(100); + } while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; - virtio_rmb(); - used_idx = (uint32_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index b6d6832..580701a 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -129,17 +129,32 @@ virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, return i; } +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif + +/* Cleanup from completed transmits. */ static void -virtqueue_dequeue_pkt_tx(struct virtqueue *vq) +virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) { - struct vring_used_elem *uep; - uint16_t used_idx, desc_idx; + uint16_t i, used_idx, desc_idx; + for (i = 0; i < num; i++) { + struct vring_used_elem *uep; + struct vq_desc_extra *dxp; + + used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); + uep = &vq->vq_ring.used->ring[used_idx]; + dxp = &vq->vq_descx[used_idx]; + + desc_idx = (uint16_t) uep->id; + vq->vq_used_cons_idx++; + vq_ring_free_chain(vq, desc_idx); - used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); - uep = &vq->vq_ring.used->ring[used_idx]; - desc_idx = (uint16_t) uep->id; - vq->vq_used_cons_idx++; - vq_ring_free_chain(vq, desc_idx); + if (dxp->cookie != NULL) { + rte_pktmbuf_free(dxp->cookie); + dxp->cookie = NULL; + } + } } @@ -203,8 +218,6 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) idx = head_idx; dxp = &txvq->vq_descx[idx]; - if (dxp->cookie != NULL) - rte_pktmbuf_free(dxp->cookie); dxp->cookie = (void *)cookie; dxp->ndescs = needed; @@ -404,6 +417,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; struct virtqueue *vq; + uint16_t tx_free_thresh; int ret; PMD_INIT_FUNC_TRACE(); @@ -421,6 +435,22 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, return ret; } + tx_free_thresh = tx_conf->tx_free_thresh; + if (tx_free_thresh == 0) + tx_free_thresh = + RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH); + + if (tx_free_thresh >= (vq->vq_nentries - 3)) { + RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the " + "number of TX entries minus 3 (%u)." + " (tx_free_thresh=%u port=%u queue=%u)\n", + vq->vq_nentries - 3, + tx_free_thresh, dev->data->port_id, queue_idx); + return -EINVAL; + } + + vq->vq_free_thresh = tx_free_thresh; + dev->data->tx_queues[queue_idx] = vq; return 0; } @@ -688,11 +718,9 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; - uint16_t nb_used, nb_tx, num; + uint16_t nb_used, nb_tx; int error; - nb_tx = 0; - if (unlikely(nb_pkts < 1)) return nb_pkts; @@ -700,21 +728,26 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); + if (likely(nb_used > txvq->vq_free_thresh)) + virtio_xmit_cleanup(txvq, nb_used); - num = (uint16_t)(likely(nb_used < VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ); + nb_tx = 0; while (nb_tx < nb_pkts) { /* Need one more descriptor for virtio header. */ int need = tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; - int deq_cnt = RTE_MIN(need, (int)num); - num -= (deq_cnt > 0) ? deq_cnt : 0; - while (deq_cnt > 0) { - virtqueue_dequeue_pkt_tx(txvq); - deq_cnt--; + /*Positive value indicates it need free vring descriptors */ + if (unlikely(need > 0)) { + nb_used = VIRTQUEUE_NUSED(txvq); + virtio_rmb(); + need = RTE_MIN(need, (int)nb_used); + + virtio_xmit_cleanup(txvq, need); + need = (int)tx_pkts[nb_tx]->nb_segs - + txvq->vq_free_cnt + 1; } - need = (int)tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; /* * Zero or negative value indicates it has enough free * descriptors to use for transmitting. @@ -723,7 +756,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) txm = tx_pkts[nb_tx]; /* Do VLAN tag insertion */ - if (txm->ol_flags & PKT_TX_VLAN_PKT) { + if (unlikely(txm->ol_flags & PKT_TX_VLAN_PKT)) { error = rte_vlan_insert(&txm); if (unlikely(error)) { rte_pktmbuf_free(txm); diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index d210f4f..6c45c27 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -164,6 +164,7 @@ struct virtqueue { struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint8_t port_id; /**< Device port identifier. */ + uint16_t vq_queue_index; /**< PCI queue index */ void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; @@ -172,7 +173,7 @@ struct virtqueue { struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_nentries; /**< vring desc numbers */ - uint16_t vq_queue_index; /**< PCI queue index */ + uint16_t vq_free_thresh; /**< free threshold */ /** * Head of the free chain in the descriptor table. If * there are no free descriptors, this will be set to -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (15 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 16/26] virtio: Free mbuf's with threshold Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-11 4:32 ` Stephen Hemminger 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 18/26] virtio: Fix descriptor index issue Ouyang Changchun ` (9 subsequent siblings) 26 siblings, 1 reply; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- changes in v3: Remove macro RTE_EAL_PORT_IO; virtio pmd could support uio and ioports method to get the address; lib/librte_pmd_virtio/Makefile | 2 + lib/librte_pmd_virtio/virtio_ethdev.c | 136 +++++++++++++++++++++++++++++----- 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/lib/librte_pmd_virtio/Makefile b/lib/librte_pmd_virtio/Makefile index 456095b..08fa27a 100644 --- a/lib/librte_pmd_virtio/Makefile +++ b/lib/librte_pmd_virtio/Makefile @@ -54,4 +54,6 @@ DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_net lib/librte_malloc +CFLAGS_virtio_ethdev.o += -Wno-cast-qual + include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 8cd2d51..1163d42 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -38,6 +38,7 @@ #include <unistd.h> #ifdef RTE_EXEC_ENV_LINUXAPP #include <dirent.h> +#include <fcntl.h> #endif #include <rte_ethdev.h> @@ -408,11 +409,13 @@ static void virtio_dev_close(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "virtio_dev_close"); /* reset the NIC */ - vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); virtio_dev_free_mbufs(dev); } @@ -845,9 +848,9 @@ parse_sysfs_value(const char *filename, unsigned long *val) return 0; } -static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen) +static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen, + unsigned int *uio_num) { - unsigned int uio_num; struct dirent *e; DIR *dir; char dirname[PATH_MAX]; @@ -884,18 +887,18 @@ static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen) /* first try uio%d */ errno = 0; - uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); + *uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { - snprintf(buf, buflen, "%s/uio%u", dirname, uio_num); + snprintf(buf, buflen, "%s/uio%u", dirname, *uio_num); break; } /* then try uio:uio%d */ errno = 0; - uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); + *uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + longprefix_len)) { snprintf(buf, buflen, "%s/uio:uio%u", dirname, - uio_num); + *uio_num); break; } } @@ -928,13 +931,16 @@ virtio_has_msix(const struct rte_pci_addr *loc) } /* Extract I/O port numbers from sysfs */ -static int virtio_resource_init(struct rte_pci_device *pci_dev) +static int virtio_resource_init_by_uio(struct rte_pci_device *pci_dev) { char dirname[PATH_MAX]; char filename[PATH_MAX]; unsigned long start, size; + unsigned int uio_num; + struct rte_pci_driver *pci_drv = + (struct rte_pci_driver *)pci_dev->driver; - if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname)) < 0) + if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0) return -1; /* get portio size */ @@ -959,8 +965,100 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) PMD_INIT_LOG(DEBUG, "PCI Port IO found start=0x%lx with size=0x%lx", start, size); + + /* save fd */ + memset(dirname, 0, sizeof(dirname)); + snprintf(dirname, sizeof(dirname), "/dev/uio%u", uio_num); + pci_dev->intr_handle.fd = open(dirname, O_RDWR); + if (pci_dev->intr_handle.fd < 0) { + PMD_INIT_LOG(ERR, "Cannot open %s: %s\n", + devname, strerror(errno)); + return -1; + } + + pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; + pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC; + return 0; } + +/* Extract port I/O numbers from proc/ioports */ +static int virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + struct rte_pci_driver *pci_drv = + (struct rte_pci_driver *)pci_dev->driver; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start; + pci_dev->mem_resource[0].len = (uint64_t)size; + PMD_INIT_LOG(DEBUG, + "PCI Port IO found start=0x%x with size=0x%x", + start, size); + + /* can't support lsc interrupt without uio */ + pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; + + return 0; +} + +/* Extract I/O port numbers from sysfs */ +static int virtio_resource_init(struct rte_pci_device *pci_dev) +{ + if (virtio_resource_init_by_uio(pci_dev) == 0) + return 0; + else + return virtio_resource_init_by_ioports(pci_dev); +} + #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) @@ -969,7 +1067,7 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) return 0; } -static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) +static int virtio_resource_init(struct rte_pci_device *pci_dev) { /* no setup required */ return 0; @@ -1124,7 +1222,8 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev->id.device_id); /* Setup interrupt callback */ - rte_intr_callback_register(&pci_dev->intr_handle, + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); virtio_dev_cq_start(eth_dev); @@ -1136,7 +1235,6 @@ static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, - .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_hw), @@ -1183,6 +1281,7 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "configure"); @@ -1200,10 +1299,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return -ENOTSUP; } - if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { - PMD_DRV_LOG(ERR, "failed to set config vector"); - return -EBUSY; - } + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { + PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } return 0; } @@ -1214,9 +1314,11 @@ virtio_dev_start(struct rte_eth_dev *dev) { uint16_t nb_queues, i; struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; /* check if lsc interrupt feature is enabled */ - if (dev->data->dev_conf.intr_conf.lsc) { + if ((dev->data->dev_conf.intr_conf.lsc) && + (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { PMD_DRV_LOG(ERR, "link status not supported by host"); return -ENOTSUP; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-02-11 4:32 ` Stephen Hemminger 2015-02-11 4:50 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-02-11 4:32 UTC (permalink / raw) To: Ouyang Changchun; +Cc: dev On Mon, 9 Feb 2015 09:14:06 +0800 Ouyang Changchun <changchun.ouyang@intel.com> wrote: > Make virtio not require UIO for some security reasons, this is to match 6Wind's virtio-net-pmd. > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> This breaks applications that use link state interrupt. If the non-UIO mode is used link state interrupt fd is not available. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-11 4:32 ` Stephen Hemminger @ 2015-02-11 4:50 ` Ouyang, Changchun 2015-02-11 7:29 ` Vincent JARDIN 0 siblings, 1 reply; 132+ messages in thread From: Ouyang, Changchun @ 2015-02-11 4:50 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Sent: Wednesday, February 11, 2015 12:33 PM > To: Ouyang, Changchun > Cc: dev@dpdk.org; Xie, Huawei; Cao, Waterman; Xu, Qian Q > Subject: Re: [PATCH v4 17/26] virtio: Use port IO to get PCI resource. > > On Mon, 9 Feb 2015 09:14:06 +0800 > Ouyang Changchun <changchun.ouyang@intel.com> wrote: > > > Make virtio not require UIO for some security reasons, this is to match > 6Wind's virtio-net-pmd. > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> > > This breaks applications that use link state interrupt. > > If the non-UIO mode is used link state interrupt fd is not available. If application use link state interrupt, then let it work in uio mode rather than proc/ioports mode, As we know proc/ioports hasn't interrupt, 6wind implementation also don't introduce interrupt in it. Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-11 4:50 ` Ouyang, Changchun @ 2015-02-11 7:29 ` Vincent JARDIN 2015-02-11 13:50 ` Stephen Hemminger 0 siblings, 1 reply; 132+ messages in thread From: Vincent JARDIN @ 2015-02-11 7:29 UTC (permalink / raw) To: Ouyang, Changchun, Stephen Hemminger; +Cc: dev On 11/02/2015 05:50, Ouyang, Changchun wrote: > As we know proc/ioports hasn't interrupt, 6wind implementation also don't introduce interrupt in it. correct, it is running without interrupt, they are not mandatory. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-11 7:29 ` Vincent JARDIN @ 2015-02-11 13:50 ` Stephen Hemminger 2015-02-11 14:16 ` Thomas Monjalon 0 siblings, 1 reply; 132+ messages in thread From: Stephen Hemminger @ 2015-02-11 13:50 UTC (permalink / raw) To: Vincent JARDIN; +Cc: dev But driver needs to tell application via driver flags ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-11 13:50 ` Stephen Hemminger @ 2015-02-11 14:16 ` Thomas Monjalon 2015-02-12 0:52 ` Ouyang, Changchun 0 siblings, 1 reply; 132+ messages in thread From: Thomas Monjalon @ 2015-02-11 14:16 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev 2015-02-11 05:50, Stephen Hemminger: > But driver needs to tell application via driver flags I think it's done: > + pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; > + pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC; In my understanding, Changchun chose to use ioports as a fallback if uio is not available. Seems OK. ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource. 2015-02-11 14:16 ` Thomas Monjalon @ 2015-02-12 0:52 ` Ouyang, Changchun 0 siblings, 0 replies; 132+ messages in thread From: Ouyang, Changchun @ 2015-02-12 0:52 UTC (permalink / raw) To: Thomas Monjalon, Stephen Hemminger; +Cc: dev > -----Original Message----- > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > Sent: Wednesday, February 11, 2015 10:16 PM > To: Stephen Hemminger > Cc: dev@dpdk.org; Vincent JARDIN; Ouyang, Changchun > Subject: Re: [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI > resource. > > 2015-02-11 05:50, Stephen Hemminger: > > But driver needs to tell application via driver flags > > I think it's done: > > + pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; > > + pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC; > > In my understanding, Changchun chose to use ioports as a fallback if uio is > not available. Seems OK. Thomas is absolutely correct! :-) And on the other hand, without uio, disable the interrupt in driver flag: + /* can't support lsc interrupt without uio */ + pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; Thanks Changchun ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 18/26] virtio: Fix descriptor index issue 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (16 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 19/26] ether: Fix vlan strip/insert issue Ouyang Changchun ` (8 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev It should use vring descriptor index instead of used_ring index to index vq_descx. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 580701a..a82e8eb 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -144,9 +144,9 @@ virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; - dxp = &vq->vq_descx[used_idx]; desc_idx = (uint16_t) uep->id; + dxp = &vq->vq_descx[desc_idx]; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 19/26] ether: Fix vlan strip/insert issue 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (17 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 18/26] virtio: Fix descriptor index issue Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 20/26] example/vhost: Avoid inserting vlan twice Ouyang Changchun ` (7 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Need swap the data from cpu to BE(big endian) for vlan-type. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_ether/rte_ether.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h index 74f71c2..0797908 100644 --- a/lib/librte_ether/rte_ether.h +++ b/lib/librte_ether/rte_ether.h @@ -351,7 +351,7 @@ 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) + if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) return -1; struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); @@ -401,7 +401,7 @@ static inline int rte_vlan_insert(struct rte_mbuf **m) return -ENOSPC; memmove(nh, oh, 2 * ETHER_ADDR_LEN); - nh->ether_type = ETHER_TYPE_VLAN; + nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vh = (struct vlan_hdr *) (nh + 1); vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 20/26] example/vhost: Avoid inserting vlan twice 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (18 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 19/26] ether: Fix vlan strip/insert issue Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 21/26] example/vhost: Add vlan-strip cmd line option Ouyang Changchun ` (6 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Check if it has already been vlan-tagged packet, if true, avoid inserting a duplicated vlan tag into it. This is a possible case when guest has the capability of inserting vlan tag. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 04f0118..6af7874 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -1115,6 +1115,7 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) unsigned len, ret, offset = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; + struct ether_hdr *nh; /*check if destination is local VM*/ if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) { @@ -1135,28 +1136,38 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; - m->ol_flags = PKT_TX_VLAN_PKT; + nh = rte_pktmbuf_mtod(m, struct ether_hdr *); + if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) { + /* Guest has inserted the vlan tag. */ + struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1); + uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag); + if ((vm2vm_mode == VM2VM_HARDWARE) && + (vh->vlan_tci != vlan_tag_be)) + vh->vlan_tci = vlan_tag_be; + } else { + m->ol_flags = PKT_TX_VLAN_PKT; - /* - * Find the right seg to adjust the data len when offset is - * bigger than tail room size. - */ - if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { - if (likely(offset <= rte_pktmbuf_tailroom(m))) - m->data_len += offset; - else { - struct rte_mbuf *seg = m; + /* + * Find the right seg to adjust the data len when offset is + * bigger than tail room size. + */ + if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { + if (likely(offset <= rte_pktmbuf_tailroom(m))) + m->data_len += offset; + else { + struct rte_mbuf *seg = m; - while ((seg->next != NULL) && - (offset > rte_pktmbuf_tailroom(seg))) - seg = seg->next; + while ((seg->next != NULL) && + (offset > rte_pktmbuf_tailroom(seg))) + seg = seg->next; - seg->data_len += offset; + seg->data_len += offset; + } + m->pkt_len += offset; } - m->pkt_len += offset; - } - m->vlan_tci = vlan_tag; + m->vlan_tci = vlan_tag; + } tx_q->m_table[len] = m; len++; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 21/26] example/vhost: Add vlan-strip cmd line option 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (19 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 20/26] example/vhost: Avoid inserting vlan twice Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 22/26] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun ` (5 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Support turn on/off RX VLAN strip on host, this let guest get the chance of using its software VALN strip functionality. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- examples/vhost/main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 6af7874..1876c8e 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -159,6 +159,9 @@ static uint32_t num_devices; static uint32_t zero_copy; static int mergeable; +/* Do vlan strip on host, enabled on default */ +static uint32_t vlan_strip = 1; + /* number of descriptors to apply*/ static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP; static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP; @@ -564,6 +567,7 @@ us_vhost_usage(const char *prgname) " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n" " --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n" + " --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n" " --zero-copy [0|1]: disable(default)/enable rx/tx " @@ -591,6 +595,7 @@ us_vhost_parse_args(int argc, char **argv) {"rx-retry-delay", required_argument, NULL, 0}, {"rx-retry-num", required_argument, NULL, 0}, {"mergeable", required_argument, NULL, 0}, + {"vlan-strip", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {"dev-basename", required_argument, NULL, 0}, {"zero-copy", required_argument, NULL, 0}, @@ -691,6 +696,22 @@ us_vhost_parse_args(int argc, char **argv) } } + /* Enable/disable RX VLAN strip on host. */ + if (!strncmp(long_option[option_index].name, + "vlan-strip", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, + "Invalid argument for VLAN strip [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else { + vlan_strip = !!ret; + vmdq_conf_default.rxmode.hw_vlan_strip = + vlan_strip; + } + } + /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); @@ -950,7 +971,9 @@ link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m) dev->device_fh); /* Enable stripping of the vlan tag as we handle routing. */ - rte_eth_dev_set_vlan_strip_on_queue(ports[0], (uint16_t)vdev->vmdq_rx_q, 1); + if (vlan_strip) + rte_eth_dev_set_vlan_strip_on_queue(ports[0], + (uint16_t)vdev->vmdq_rx_q, 1); /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 22/26] virtio: Use soft vlan strip in mergeable Rx path 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (20 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 21/26] example/vhost: Add vlan-strip cmd line option Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 23/26] virtio: Fix zero copy break issue Ouyang Changchun ` (4 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev To keep the consistent logic with normal Rx path, the mergeable Rx path also needs software vlan strip/decap if it is enabled. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index a82e8eb..c6d9ae7 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -568,6 +568,7 @@ virtio_recv_mergeable_pkts(void *rx_queue, 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]; @@ -674,6 +675,9 @@ virtio_recv_mergeable_pkts(void *rx_queue, seg_res -= rcv_cnt; } + if (hw->vlan_strip) + rte_vlan_strip(rx_pkts[nb_rx]); + VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], rx_pkts[nb_rx]->data_len); -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 23/26] virtio: Fix zero copy break issue 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (21 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 22/26] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 24/26] virtio: Remove hotspots Ouyang Changchun ` (3 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev vHOST zero copy need get vring descriptor and its buffer address to set the DMA address of HW ring, it is done in new_device when ioctl set_backend is called. This requies virtio_dev_rxtx_start is called before vtpci_reinit_complete, which makes sure the vring descriptro and its buffer is ready before its using. this patch also fixes one set status issue, according to virtio spec, VIRTIO_CONFIG_STATUS_ACK should be set after virtio hw reset. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_ethdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 1163d42..9eb0217 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -417,6 +417,7 @@ virtio_dev_close(struct rte_eth_dev *dev) if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); + hw->started = 0; virtio_dev_free_mbufs(dev); } @@ -1132,9 +1133,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return -ENOMEM; } - /* 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; @@ -1145,6 +1143,9 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, /* 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); @@ -1337,10 +1338,10 @@ virtio_dev_start(struct rte_eth_dev *dev) if (hw->started) return 0; - vtpci_reinit_complete(hw); - /* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start(dev); + vtpci_reinit_complete(hw); + hw->started = 1; /*Notify the backend -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 24/26] virtio: Remove hotspots 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (22 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 23/26] virtio: Fix zero copy break issue Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 25/26] virtio: Fix wmb issue Ouyang Changchun ` (2 subsequent siblings) 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Remove those hotspots which is unnecessary when early returning occurs; Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index c6d9ae7..0225cc9 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -476,13 +476,13 @@ 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 virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; int error; - uint32_t i, nb_enqueued = 0; + uint32_t i, nb_enqueued; const uint32_t hdr_size = sizeof(struct virtio_net_hdr); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -499,6 +499,11 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, num); PMD_RX_LOG(DEBUG, "used:%d dequeue:%d", nb_used, num); + + hw = rxvq->hw; + nb_rx = 0; + nb_enqueued = 0; + for (i = 0; i < num ; i++) { rxm = rcv_pkts[i]; @@ -568,17 +573,17 @@ virtio_recv_mergeable_pkts(void *rx_queue, uint16_t nb_pkts) { struct virtqueue *rxvq = rx_queue; - struct virtio_hw *hw = rxvq->hw; + struct virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; - uint16_t nb_used, num, nb_rx = 0; + uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *prev; int error; - uint32_t i = 0, nb_enqueued = 0; - uint32_t seg_num = 0; - uint16_t extra_idx = 0; - uint32_t seg_res = 0; + uint32_t i, nb_enqueued; + uint32_t seg_num; + uint16_t extra_idx; + uint32_t seg_res; const uint32_t hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); nb_used = VIRTQUEUE_NUSED(rxvq); @@ -590,6 +595,14 @@ virtio_recv_mergeable_pkts(void *rx_queue, PMD_RX_LOG(DEBUG, "used:%d\n", nb_used); + hw = rxvq->hw; + nb_rx = 0; + i = 0; + nb_enqueued = 0; + seg_num = 0; + extra_idx = 0; + seg_res = 0; + while (i < nb_used) { struct virtio_net_hdr_mrg_rxbuf *header; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 25/26] virtio: Fix wmb issue 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (23 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 24/26] virtio: Remove hotspots Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 26/26] virtio: Fix updating vring descriptor index issue Ouyang Changchun 2015-02-17 6:04 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Xie, Huawei 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev It needs use virtio_wmb instead of virtio_rmb for store memory barrier. Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_pmd_virtio/virtqueue.h b/lib/librte_pmd_virtio/virtqueue.h index 6c45c27..41dda50 100644 --- a/lib/librte_pmd_virtio/virtqueue.h +++ b/lib/librte_pmd_virtio/virtqueue.h @@ -266,7 +266,7 @@ virtqueue_full(const struct virtqueue *vq) static inline void vq_update_avail_idx(struct virtqueue *vq) { - virtio_rmb(); + virtio_wmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* [dpdk-dev] [PATCH v4 26/26] virtio: Fix updating vring descriptor index issue 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (24 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 25/26] virtio: Fix wmb issue Ouyang Changchun @ 2015-02-09 1:14 ` Ouyang Changchun 2015-02-17 6:04 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Xie, Huawei 26 siblings, 0 replies; 132+ messages in thread From: Ouyang Changchun @ 2015-02-09 1:14 UTC (permalink / raw) To: dev Updating the vring descriptor index should be done before notifying host; Remove 2 duplicated store memory barriers in both Rx and Tx path because there is store memory barrier in vq_update_avail_idx function; Notify the host only if packets actually transmitted(nb_tx > 0). Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com> --- lib/librte_pmd_virtio/virtio_rxtx.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_rxtx.c b/lib/librte_pmd_virtio/virtio_rxtx.c index 0225cc9..1d74b34 100644 --- a/lib/librte_pmd_virtio/virtio_rxtx.c +++ b/lib/librte_pmd_virtio/virtio_rxtx.c @@ -555,15 +555,14 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } if (likely(nb_enqueued)) { - virtio_wmb(); + vq_update_avail_idx(rxvq); + if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); } } - vq_update_avail_idx(rxvq); - return nb_rx; } @@ -719,14 +718,14 @@ virtio_recv_mergeable_pkts(void *rx_queue, } if (likely(nb_enqueued)) { + vq_update_avail_idx(rxvq); + if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified"); } } - vq_update_avail_idx(rxvq); - return nb_rx; } @@ -800,14 +799,16 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) break; } } - vq_update_avail_idx(txvq); - virtio_wmb(); txvq->packets += nb_tx; - if (unlikely(virtqueue_kick_prepare(txvq))) { - virtqueue_notify(txvq); - PMD_TX_LOG(DEBUG, "Notified backend after xmit"); + if (likely(nb_tx)) { + vq_update_avail_idx(txvq); + + if (unlikely(virtqueue_kick_prepare(txvq))) { + virtqueue_notify(txvq); + PMD_TX_LOG(DEBUG, "Notified backend after xmit"); + } } return nb_tx; -- 1.8.4.2 ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 00/26] Single virtio implementation 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun ` (25 preceding siblings ...) 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 26/26] virtio: Fix updating vring descriptor index issue Ouyang Changchun @ 2015-02-17 6:04 ` Xie, Huawei 2015-02-20 18:06 ` Thomas Monjalon 26 siblings, 1 reply; 132+ messages in thread From: Xie, Huawei @ 2015-02-17 6:04 UTC (permalink / raw) To: Ouyang, Changchun, dev Acked-by Huawei Xie <huawei.xie@intel.com> On 2/9/2015 9:14 AM, Ouyang, Changchun wrote: > This is the patch set for single virtio implementation. > > Why we need single virtio? > ============================ > As we know currently there are at least 3 virtio PMD driver implementations: > A) lib/librte_pmd_virtio(refer as virtio A); > B) virtio_net_pmd by 6wind(refer as virtio B); > C) virtio by Brocade/vyatta(refer as virtio C); > > Integrating 3 implementations into one could reduce the maintaining cost and time, > in other hand, user don't need practice their application on 3 variant one by one to see > which one is the best for them; > > What's the status? > ==================== > Currently virtio A has covered most features of virtio B except for using port io to get pci resource, > so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between > virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. > This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] > Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. > This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some > issues in original codes. > > What this patch set contains: > =============================== > 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; > 2) virtio: Use weaker barriers, as 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 may help performance a bit; > 3) virtio: Allow starting with link down, other driver has similar behavior; > 4) virtio: Add support for Link State interrupt; > 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; > 6) virtio: Use software vlan stripping; > 7) virtio: Remove unnecessary adapter structure; > 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; > 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; > 10) virtio: Make vtpci_get_status a local function as it is used in one file; > 11) virtio: Check for packet headroom at compile time; > 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; > 13) virtio: Add support for vlan filtering; > 14) virtio: Add support for multiple mac addresses; > 15) virtio: Add ability to set MAC address; > 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; > 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; > 18) virtio: Fix descriptor index issue; > 19) ether: Fix vlan strip/insert issue; > 20) example/vhost: Avoid inserting vlan twice and guest and host; > 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; > 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic > with the normal Rx path. > > Changes in v2: > 23) virtio: Fix zero copy break issue, the vring should be ready before virtio PMD set > the status of DRIVER_OK; > 24) virtio: Remove unnecessary hotspots in data path. > > Changes in v3: > 25) virtio: Fix wmb issue; > 26) Fix one minor issue in patch 20, also fix its idention. > > Changes in v4: > 27) Fix updating vring descriptor index issue and memory barrier issue; > 28) Reslove comments for patch 17. > > Changchun Ouyang (10): > virtio: Use port IO to get PCI resource. > virtio: Fix descriptor index issue > ether: Fix vlan strip/insert issue > example/vhost: Avoid inserting vlan twice > example/vhost: Add vlan-strip cmd line option > virtio: Use soft vlan strip in mergeable Rx path > virtio: Fix zero copy break issue > virtio: Remove hotspots > virtio: Fix wmb issue > virtio: Fix updating vring descriptor index issue > > Stephen Hemminger (16): > virtio: Rearrange resource initialization > virtio: Use weaker barriers > virtio: Allow starting with link down > virtio: Add support for Link State interrupt > ether: Add soft vlan encap/decap functions > virtio: Use software vlan stripping > virtio: Remove unnecessary adapter structure > virtio: Remove redundant vq_alignment > virtio: Fix how states are handled during initialization > virtio: Make vtpci_get_status local > virtio: Check for packet headroom at compile time > virtio: Move allocation before initialization > virtio: Add support for vlan filtering > virtio: Add suport for multiple mac addresses > virtio: Add ability to set MAC address > virtio: Free mbuf's with threshold > > examples/vhost/main.c | 70 +++-- > lib/librte_ether/rte_ethdev.h | 8 + > lib/librte_ether/rte_ether.h | 76 +++++ > lib/librte_pmd_virtio/Makefile | 2 + > lib/librte_pmd_virtio/virtio_ethdev.c | 519 ++++++++++++++++++++++++++-------- > lib/librte_pmd_virtio/virtio_ethdev.h | 12 +- > lib/librte_pmd_virtio/virtio_pci.c | 20 +- > lib/librte_pmd_virtio/virtio_pci.h | 8 +- > lib/librte_pmd_virtio/virtio_rxtx.c | 154 +++++++--- > lib/librte_pmd_virtio/virtqueue.h | 59 +++- > 10 files changed, 729 insertions(+), 199 deletions(-) > ^ permalink raw reply [flat|nested] 132+ messages in thread
* Re: [dpdk-dev] [PATCH v4 00/26] Single virtio implementation 2015-02-17 6:04 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Xie, Huawei @ 2015-02-20 18:06 ` Thomas Monjalon 0 siblings, 0 replies; 132+ messages in thread From: Thomas Monjalon @ 2015-02-20 18:06 UTC (permalink / raw) To: Ouyang, Changchun, Stephen Hemminger; +Cc: dev > On 2/9/2015 9:14 AM, Ouyang, Changchun wrote: > > This is the patch set for single virtio implementation. > > > > Why we need single virtio? > > ============================ > > As we know currently there are at least 3 virtio PMD driver implementations: > > A) lib/librte_pmd_virtio(refer as virtio A); > > B) virtio_net_pmd by 6wind(refer as virtio B); > > C) virtio by Brocade/vyatta(refer as virtio C); > > > > Integrating 3 implementations into one could reduce the maintaining cost and time, > > in other hand, user don't need practice their application on 3 variant one by one to see > > which one is the best for them; > > > > What's the status? > > ==================== > > Currently virtio A has covered most features of virtio B except for using port io to get pci resource, > > so there is a patch(17/22) to resolve it. But on the other hand there are a few differences between > > virtio A and virtio C, it needs integrate features/codes of virtio C into virtio A. > > This patch set bases on two original RFC patch sets from Stephen Hemminger[stephen@networkplumber.org] > > Refer to [http://dpdk.org/ml/archives/dev/2014-August/004845.html ] for the original one. > > This patch set also resolves some conflict with latest codes, removed duplicated codes, fix some > > issues in original codes. > > > > What this patch set contains: > > =============================== > > 1) virtio: Rearrange resource initialization, it extracts a function to setup PCI resources; > > 2) virtio: Use weaker barriers, as 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 may help performance a bit; > > 3) virtio: Allow starting with link down, other driver has similar behavior; > > 4) virtio: Add support for Link State interrupt; > > 5) ether: Add soft vlan encap/decap functions, it helps if HW don't support vlan strip; > > 6) virtio: Use software vlan stripping; > > 7) virtio: Remove unnecessary adapter structure; > > 8) virtio: Remove redundant vq_alignment, as vq alignment is always 4K, so use constant when needed; > > 9) virtio: Fix how states are handled during initialization, this is to match Linux kernel; > > 10) virtio: Make vtpci_get_status a local function as it is used in one file; > > 11) virtio: Check for packet headroom at compile time; > > 12) virtio: Move allocation before initialization to avoid being stuck in middle of virtio init; > > 13) virtio: Add support for vlan filtering; > > 14) virtio: Add support for multiple mac addresses; > > 15) virtio: Add ability to set MAC address; > > 16) virtio: Free mbuf's with threshold, this makes its behavior more like ixgbe; > > 17) virtio: Use port IO to get PCI resource for security reasons and match virtio-net-pmd; > > 18) virtio: Fix descriptor index issue; > > 19) ether: Fix vlan strip/insert issue; > > 20) example/vhost: Avoid inserting vlan twice and guest and host; > > 21) example/vhost: Add vlan-strip cmd line option to turn on/off vlan strip on host; > > 22) virtio: Use soft vlan strip in mergeable Rx path, this makes it has consistent logic > > with the normal Rx path. > > > > Changes in v2: > > 23) virtio: Fix zero copy break issue, the vring should be ready before virtio PMD set > > the status of DRIVER_OK; > > 24) virtio: Remove unnecessary hotspots in data path. > > > > Changes in v3: > > 25) virtio: Fix wmb issue; > > 26) Fix one minor issue in patch 20, also fix its idention. > > > > Changes in v4: > > 27) Fix updating vring descriptor index issue and memory barrier issue; > > 28) Reslove comments for patch 17. > > > > Changchun Ouyang (10): > > virtio: Use port IO to get PCI resource. > > virtio: Fix descriptor index issue > > ether: Fix vlan strip/insert issue > > example/vhost: Avoid inserting vlan twice > > example/vhost: Add vlan-strip cmd line option > > virtio: Use soft vlan strip in mergeable Rx path > > virtio: Fix zero copy break issue > > virtio: Remove hotspots > > virtio: Fix wmb issue > > virtio: Fix updating vring descriptor index issue > > > > Stephen Hemminger (16): > > virtio: Rearrange resource initialization > > virtio: Use weaker barriers > > virtio: Allow starting with link down > > virtio: Add support for Link State interrupt > > ether: Add soft vlan encap/decap functions > > virtio: Use software vlan stripping > > virtio: Remove unnecessary adapter structure > > virtio: Remove redundant vq_alignment > > virtio: Fix how states are handled during initialization > > virtio: Make vtpci_get_status local > > virtio: Check for packet headroom at compile time > > virtio: Move allocation before initialization > > virtio: Add support for vlan filtering > > virtio: Add suport for multiple mac addresses > > virtio: Add ability to set MAC address > > virtio: Free mbuf's with threshold > > Acked-by Huawei Xie <huawei.xie@intel.com> Applied, thanks. The patches which were fixing previous ones have been merged. The virtio-net-pmd extension (out of tree) should be deprecated now. ^ permalink raw reply [flat|nested] 132+ messages in thread
end of thread, other threads:[~2015-02-20 18:07 UTC | newest] Thread overview: 132+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-01-15 5:15 [dpdk-dev] [PATCH 00/22] Single virtio implementation Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 01/22] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 02/22] virtio: Use weaker barriers Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 03/22] virtio: Allow starting with link down Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 04/22] virtio: Add support for Link State interrupt Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 05/22] ether: Add soft vlan encap/decap functions Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 06/22] virtio: Use software vlan stripping Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 07/22] virtio: Remove unnecessary adapter structure Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 08/22] virtio: Remove redundant vq_alignment Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 09/22] virtio: Fix how states are handled during initialization Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 10/22] virtio: Make vtpci_get_status local Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 11/22] virtio: Check for packet headroom at compile time Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 12/22] virtio: Move allocation before initialization Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 13/22] virtio: Add support for vlan filtering Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 14/22] virtio: Add suport for multiple mac addresses Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 15/22] virtio: Add ability to set MAC address Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 16/22] virtio: Free mbuf's with threshold Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 17/22] virtio: Use port IO to get PCI resource Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 18/22] virtio: Fix descriptor index issue Ouyang Changchun 2015-01-15 16:54 ` Stephen Hemminger 2015-01-16 0:55 ` Ouyang, Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 19/22] ether: Fix vlan strip/insert issue Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 20/22] example/vhost: Avoid inserting vlan twice Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 21/22] example/vhost: Add vlan-strip cmd line option Ouyang Changchun 2015-01-15 5:15 ` [dpdk-dev] [PATCH 22/22] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun 2015-01-15 16:55 ` Stephen Hemminger 2015-01-16 0:56 ` Ouyang, Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 01/24] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 02/24] virtio: Use weaker barriers Ouyang Changchun 2015-01-27 7:03 ` Xie, Huawei 2015-01-27 9:58 ` Stephen Hemminger 2015-01-27 16:16 ` Xie, Huawei 2015-01-28 6:12 ` Ouyang, Changchun 2015-01-27 7:56 ` Xie, Huawei 2015-01-27 8:04 ` Ouyang, Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 03/24] virtio: Allow starting with link down Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 04/24] virtio: Add support for Link State interrupt Ouyang Changchun 2015-01-27 9:04 ` Xie, Huawei 2015-01-27 10:00 ` Stephen Hemminger 2015-01-28 3:03 ` Ouyang, Changchun 2015-01-28 15:11 ` Stephen Hemminger 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 05/24] ether: Add soft vlan encap/decap functions Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 06/24] virtio: Use software vlan stripping Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 07/24] virtio: Remove unnecessary adapter structure Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 08/24] virtio: Remove redundant vq_alignment Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 09/24] virtio: Fix how states are handled during initialization Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 10/24] virtio: Make vtpci_get_status local Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 11/24] virtio: Check for packet headroom at compile time Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 12/24] virtio: Move allocation before initialization Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 13/24] virtio: Add support for vlan filtering Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 14/24] virtio: Add suport for multiple mac addresses Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 15/24] virtio: Add ability to set MAC address Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 16/24] virtio: Free mbuf's with threshold Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 17/24] virtio: Use port IO to get PCI resource Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 18/24] virtio: Fix descriptor index issue Ouyang Changchun 2015-01-27 2:35 ` [dpdk-dev] [PATCH v2 19/24] ether: Fix vlan strip/insert issue Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 20/24] example/vhost: Avoid inserting vlan twice Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 21/24] example/vhost: Add vlan-strip cmd line option Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 22/24] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 23/24] virtio: Fix zero copy break issue Ouyang Changchun 2015-01-27 2:36 ` [dpdk-dev] [PATCH v2 24/24] virtio: Remove hotspots Ouyang Changchun 2015-01-27 3:06 ` [dpdk-dev] [PATCH v2 00/24] Single virtio implementation Matthew Hall 2015-01-27 3:42 ` Wiles, Keith 2015-01-27 9:41 ` Matthew Hall 2015-01-27 10:02 ` Stephen Hemminger 2015-01-27 18:59 ` Matthew Hall 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 00/25] " Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 01/25] virtio: Rearrange resource initialization Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 02/25] virtio: Use weaker barriers Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 03/25] virtio: Allow starting with link down Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 04/25] virtio: Add support for Link State interrupt Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 05/25] ether: Add soft vlan encap/decap functions Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 06/25] virtio: Use software vlan stripping Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 07/25] virtio: Remove unnecessary adapter structure Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 08/25] virtio: Remove redundant vq_alignment Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 09/25] virtio: Fix how states are handled during initialization Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 10/25] virtio: Make vtpci_get_status local Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 11/25] virtio: Check for packet headroom at compile time Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 12/25] virtio: Move allocation before initialization Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 13/25] virtio: Add support for vlan filtering Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 14/25] virtio: Add suport for multiple mac addresses Ouyang Changchun 2015-01-29 7:23 ` [dpdk-dev] [PATCH v3 15/25] virtio: Add ability to set MAC address Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 16/25] virtio: Free mbuf's with threshold Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 17/25] virtio: Use port IO to get PCI resource Ouyang Changchun 2015-01-29 23:14 ` Thomas Monjalon 2015-02-04 1:31 ` Ouyang, Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 18/25] virtio: Fix descriptor index issue Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 19/25] ether: Fix vlan strip/insert issue Ouyang Changchun 2015-02-04 10:54 ` Xie, Huawei 2015-02-05 0:54 ` Ouyang, Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 20/25] example/vhost: Avoid inserting vlan twice Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 21/25] example/vhost: Add vlan-strip cmd line option Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 22/25] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 23/25] virtio: Fix zero copy break issue Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 24/25] virtio: Remove hotspots Ouyang Changchun 2015-01-29 7:24 ` [dpdk-dev] [PATCH v3 25/25] virtio: Fix wmb issue Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 01/26] virtio: Rearrange resource initialization Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 02/26] virtio: Use weaker barriers Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 03/26] virtio: Allow starting with link down Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 04/26] virtio: Add support for Link State interrupt Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 05/26] ether: Add soft vlan encap/decap functions Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 06/26] virtio: Use software vlan stripping Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 07/26] virtio: Remove unnecessary adapter structure Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 08/26] virtio: Remove redundant vq_alignment Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 09/26] virtio: Fix how states are handled during initialization Ouyang Changchun 2015-02-09 1:13 ` [dpdk-dev] [PATCH v4 10/26] virtio: Make vtpci_get_status local Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 11/26] virtio: Check for packet headroom at compile time Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 12/26] virtio: Move allocation before initialization Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 13/26] virtio: Add support for vlan filtering Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 14/26] virtio: Add suport for multiple mac addresses Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 15/26] virtio: Add ability to set MAC address Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 16/26] virtio: Free mbuf's with threshold Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 17/26] virtio: Use port IO to get PCI resource Ouyang Changchun 2015-02-11 4:32 ` Stephen Hemminger 2015-02-11 4:50 ` Ouyang, Changchun 2015-02-11 7:29 ` Vincent JARDIN 2015-02-11 13:50 ` Stephen Hemminger 2015-02-11 14:16 ` Thomas Monjalon 2015-02-12 0:52 ` Ouyang, Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 18/26] virtio: Fix descriptor index issue Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 19/26] ether: Fix vlan strip/insert issue Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 20/26] example/vhost: Avoid inserting vlan twice Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 21/26] example/vhost: Add vlan-strip cmd line option Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 22/26] virtio: Use soft vlan strip in mergeable Rx path Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 23/26] virtio: Fix zero copy break issue Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 24/26] virtio: Remove hotspots Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 25/26] virtio: Fix wmb issue Ouyang Changchun 2015-02-09 1:14 ` [dpdk-dev] [PATCH v4 26/26] virtio: Fix updating vring descriptor index issue Ouyang Changchun 2015-02-17 6:04 ` [dpdk-dev] [PATCH v4 00/26] Single virtio implementation Xie, Huawei 2015-02-20 18:06 ` Thomas Monjalon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).