mbuf: fix data room size calculation in pool init
[dpdk.git] / examples / vhost / main.c
index d2c1852..fc73d1e 100644 (file)
 /* Number of descriptors per cacheline. */
 #define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc))
 
+#define MBUF_EXT_MEM(mb)   (RTE_MBUF_FROM_BADDR((mb)->buf_addr) != (mb))
+
 /* mask of enabled ports */
 static uint32_t enabled_port_mask = 0;
 
@@ -159,6 +161,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;
@@ -390,6 +395,9 @@ port_init(uint8_t port)
        txconf = &dev_info.default_txconf;
        rxconf->rx_drop_en = 1;
 
+       /* Enable vlan offload */
+       txconf->txq_flags &= ~ETH_TXQ_FLAGS_NOVLANOFFL;
+
        /*
         * Zero copy defers queue RX/TX start to the time when guest
         * finishes its startup and packet buffers from that guest are
@@ -561,6 +569,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 "
@@ -588,6 +597,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},
@@ -688,6 +698,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);
@@ -721,19 +747,6 @@ us_vhost_parse_args(int argc, char **argv)
                                        return -1;
                                } else
                                        zero_copy = ret;
-
-                               if (zero_copy) {
-#ifdef RTE_MBUF_REFCNT
-                                       RTE_LOG(ERR, VHOST_CONFIG, "Before running "
-                                       "zero copy vhost APP, please "
-                                       "disable RTE_MBUF_REFCNT\n"
-                                       "in config file and then rebuild DPDK "
-                                       "core lib!\n"
-                                       "Otherwise please disable zero copy "
-                                       "flag in command line!\n");
-                                       return -1;
-#endif
-                               }
                        }
 
                        /* Specify the descriptor number on RX. */
@@ -947,7 +960,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;
@@ -1112,6 +1127,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)) {
@@ -1119,9 +1135,8 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag)
                return;
        }
 
-       if (vm2vm_mode == VM2VM_HARDWARE) {
-               if (find_local_dest(dev, m, &offset, &vlan_tag) != 0 ||
-                       offset > rte_pktmbuf_tailroom(m)) {
+       if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) {
+               if (unlikely(find_local_dest(dev, m, &offset, &vlan_tag) != 0)) {
                        rte_pktmbuf_free(m);
                        return;
                }
@@ -1133,12 +1148,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;
+
+                               while ((seg->next != NULL) &&
+                                       (offset > rte_pktmbuf_tailroom(seg)))
+                                       seg = seg->next;
 
-       m->data_len += offset;
-       m->pkt_len += offset;
+                               seg->data_len += offset;
+                       }
+                       m->pkt_len += offset;
+               }
 
-       m->vlan_tci = vlan_tag;
+               m->vlan_tci = vlan_tag;
+       }
 
        tx_q->m_table[len] = m;
        len++;
@@ -1290,8 +1331,8 @@ switch_worker(__attribute__((unused)) void *arg)
                                /* If this is the first received packet we need to learn the MAC and setup VMDQ */
                                if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && tx_count) {
                                        if (vdev->remove || (link_vmdq(vdev, pkts_burst[0]) == -1)) {
-                                               while (tx_count--)
-                                                       rte_pktmbuf_free(pkts_burst[tx_count]);
+                                               while (tx_count)
+                                                       rte_pktmbuf_free(pkts_burst[--tx_count]);
                                        }
                                }
                                while (tx_count)
@@ -1393,7 +1434,7 @@ put_desc_to_used_list_zcp(struct vhost_virtqueue *vq, uint16_t desc_idx)
 
        /* Kick the guest if necessary. */
        if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
-               eventfd_write((int)vq->kickfd, 1);
+               eventfd_write((int)vq->callfd, 1);
 }
 
 /*
@@ -1549,7 +1590,7 @@ txmbuf_clean_zcp(struct virtio_net *dev, struct vpool *vpool)
 
        for (index = 0; index < mbuf_count; index++) {
                mbuf = __rte_mbuf_raw_alloc(vpool->pool);
-               if (likely(RTE_MBUF_INDIRECT(mbuf)))
+               if (likely(MBUF_EXT_MEM(mbuf)))
                        pktmbuf_detach_zcp(mbuf);
                rte_ring_sp_enqueue(vpool->ring, mbuf);
 
@@ -1586,7 +1627,7 @@ txmbuf_clean_zcp(struct virtio_net *dev, struct vpool *vpool)
 
        /* Kick guest if required. */
        if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
-               eventfd_write((int)vq->kickfd, 1);
+               eventfd_write((int)vq->callfd, 1);
 
        return 0;
 }
@@ -1612,7 +1653,7 @@ static void mbuf_destroy_zcp(struct vpool *vpool)
        for (index = 0; index < mbuf_count; index++) {
                mbuf = __rte_mbuf_raw_alloc(vpool->pool);
                if (likely(mbuf != NULL)) {
-                       if (likely(RTE_MBUF_INDIRECT(mbuf)))
+                       if (likely(MBUF_EXT_MEM(mbuf)))
                                pktmbuf_detach_zcp(mbuf);
                        rte_ring_sp_enqueue(vpool->ring, (void *)mbuf);
                }
@@ -1734,7 +1775,7 @@ virtio_dev_rx_zcp(struct virtio_net *dev, struct rte_mbuf **pkts,
 
        /* Kick the guest if necessary. */
        if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
-               eventfd_write((int)vq->kickfd, 1);
+               eventfd_write((int)vq->callfd, 1);
 
        return count;
 }
@@ -2574,9 +2615,10 @@ new_device (struct virtio_net *dev)
 
                }
 
-               vdev->regions_hpa = (struct virtio_memory_regions_hpa *) rte_zmalloc("vhost hpa region",
-                       sizeof(struct virtio_memory_regions_hpa) * vdev->nregions_hpa,
-                       RTE_CACHE_LINE_SIZE);
+               vdev->regions_hpa = rte_calloc("vhost hpa region",
+                                              vdev->nregions_hpa,
+                                              sizeof(struct virtio_memory_regions_hpa),
+                                              RTE_CACHE_LINE_SIZE);
                if (vdev->regions_hpa == NULL) {
                        RTE_LOG(ERR, VHOST_CONFIG, "Cannot allocate memory for hpa region\n");
                        rte_free(vdev);
@@ -2705,8 +2747,7 @@ new_device (struct virtio_net *dev)
                RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh);
                vdev->ready = DEVICE_SAFE_REMOVE;
                destroy_device(dev);
-               if (vdev->regions_hpa)
-                       rte_free(vdev->regions_hpa);
+               rte_free(vdev->regions_hpa);
                rte_free(vdev);
                return -1;
        }
@@ -2803,11 +2844,10 @@ static void
 setup_mempool_tbl(int socket, uint32_t index, char *pool_name,
        char *ring_name, uint32_t nb_mbuf)
 {
-       uint16_t roomsize = VIRTIO_DESCRIPTOR_LEN_ZCP + RTE_PKTMBUF_HEADROOM;
        vpool_array[index].pool
                = rte_mempool_create(pool_name, nb_mbuf, MBUF_SIZE_ZCP,
                MBUF_CACHE_SIZE_ZCP, sizeof(struct rte_pktmbuf_pool_private),
-               rte_pktmbuf_pool_init, (void *)(uintptr_t)roomsize,
+               rte_pktmbuf_pool_init, NULL,
                rte_pktmbuf_init, NULL, socket, 0);
        if (vpool_array[index].pool != NULL) {
                vpool_array[index].ring
@@ -2829,7 +2869,7 @@ setup_mempool_tbl(int socket, uint32_t index, char *pool_name,
                }
 
                /* Need consider head room. */
-               vpool_array[index].buf_size = roomsize - RTE_PKTMBUF_HEADROOM;
+               vpool_array[index].buf_size = VIRTIO_DESCRIPTOR_LEN_ZCP;
        } else {
                rte_exit(EXIT_FAILURE, "mempool_create(%s) failed", pool_name);
        }