X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pmd_virtio%2Fvirtio_ethdev.c;h=c009f2ae15e091c9dc0af2d76e31d4621ae44d43;hb=98a1648109b8dbaa4e6b821c17d1f6bd86d33a9a;hp=5af71bdf72feb82861e5b93dffb32b2778217670;hpb=51c005546ad5c6b69844bec28a7fc45bebdd1229;p=dpdk.git diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 5af71bdf72..c009f2ae15 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -66,6 +66,10 @@ static int eth_virtio_dev_init(struct eth_driver *eth_drv, static int virtio_dev_configure(struct rte_eth_dev *dev); static int virtio_dev_start(struct rte_eth_dev *dev); static void virtio_dev_stop(struct rte_eth_dev *dev); +static void virtio_dev_promiscuous_enable(struct rte_eth_dev *dev); +static void virtio_dev_promiscuous_disable(struct rte_eth_dev *dev); +static void virtio_dev_allmulticast_enable(struct rte_eth_dev *dev); +static void virtio_dev_allmulticast_disable(struct rte_eth_dev *dev); static void virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int virtio_dev_link_update(struct rte_eth_dev *dev, @@ -271,20 +275,17 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, dev->data->port_id, queue_idx); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), CACHE_LINE_SIZE); - memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); } else if (queue_type == VTNET_TQ) { snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d", dev->data->port_id, queue_idx); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), CACHE_LINE_SIZE); - memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); } else if (queue_type == VTNET_CQ) { snprintf(vq_name, sizeof(vq_name), "port%d_cvq", dev->data->port_id); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), CACHE_LINE_SIZE); - memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); } if (vq == NULL) { PMD_INIT_LOG(ERR, "%s: Can not allocate virtqueue", __func__); @@ -340,7 +341,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d_hdrzone", dev->data->port_id, queue_idx); vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name, - vq_size * sizeof(struct virtio_net_hdr), + vq_size * hw->vtnet_hdr_size, socket_id, 0, CACHE_LINE_SIZE); if (vq->virtio_net_hdr_mz == NULL) { rte_free(vq); @@ -349,7 +350,7 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, vq->virtio_net_hdr_mem = vq->virtio_net_hdr_mz->phys_addr; memset(vq->virtio_net_hdr_mz->addr, 0, - vq_size * sizeof(struct virtio_net_hdr)); + vq_size * hw->vtnet_hdr_size); } else if (queue_type == VTNET_CQ) { /* Allocate a page for control vq command, data and status */ snprintf(vq_name, sizeof(vq_name), "port%d_cvq_hdrzone", @@ -406,6 +407,86 @@ virtio_dev_close(struct rte_eth_dev *dev) virtio_dev_stop(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_pmd_ctrl ctrl; + int dlen[1]; + int ret; + + ctrl.hdr.class = VIRTIO_NET_CTRL_RX; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC; + ctrl.data[0] = 1; + dlen[0] = 1; + + ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); + + if (ret) + PMD_INIT_LOG(ERR, "Failed to enable promisc"); +} + +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_pmd_ctrl ctrl; + int dlen[1]; + int ret; + + ctrl.hdr.class = VIRTIO_NET_CTRL_RX; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC; + ctrl.data[0] = 0; + dlen[0] = 1; + + ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); + + if (ret) + PMD_INIT_LOG(ERR, "Failed to disable promisc"); +} + +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_pmd_ctrl ctrl; + int dlen[1]; + int ret; + + ctrl.hdr.class = VIRTIO_NET_CTRL_RX; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI; + ctrl.data[0] = 1; + dlen[0] = 1; + + ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); + + if (ret) + PMD_INIT_LOG(ERR, "Failed to enable allmulticast"); +} + +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_pmd_ctrl ctrl; + int dlen[1]; + int ret; + + ctrl.hdr.class = VIRTIO_NET_CTRL_RX; + ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI; + ctrl.data[0] = 0; + dlen[0] = 1; + + ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); + + if (ret) + PMD_INIT_LOG(ERR, "Failed to disable allmulticast"); +} + /* * dev_ops for virtio, bare necessities for basic operation */ @@ -414,6 +495,10 @@ static struct eth_dev_ops virtio_eth_dev_ops = { .dev_start = virtio_dev_start, .dev_stop = virtio_dev_stop, .dev_close = virtio_dev_close, + .promiscuous_enable = virtio_dev_promiscuous_enable, + .promiscuous_disable = virtio_dev_promiscuous_disable, + .allmulticast_enable = virtio_dev_allmulticast_enable, + .allmulticast_disable = virtio_dev_allmulticast_disable, .dev_infos_get = virtio_dev_info_get, .stats_get = virtio_dev_stats_get, @@ -562,9 +647,9 @@ virtio_get_hwaddr(struct virtio_hw *hw) static void virtio_negotiate_features(struct virtio_hw *hw) { - uint32_t guest_features, mask; + uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_RX | VIRTIO_NET_F_CTRL_VLAN; + mask = VIRTIO_NET_F_CTRL_VLAN; mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding @@ -574,27 +659,24 @@ virtio_negotiate_features(struct virtio_hw *hw) mask |= VIRTIO_NET_F_GUEST_TSO4 | VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN; mask |= VTNET_LRO_FEATURES; - /* rx_mbuf should not be in multiple merged segments */ - mask |= VIRTIO_NET_F_MRG_RXBUF; - /* not negotiating INDIRECT descriptor table support */ mask |= VIRTIO_RING_F_INDIRECT_DESC; /* Prepare guest_features: feature that driver wants to support */ - guest_features = VTNET_FEATURES & ~mask; + hw->guest_features = VTNET_FEATURES & ~mask; PMD_INIT_LOG(DEBUG, "guest_features before negotiate = %x", - guest_features); + hw->guest_features); /* Read device(host) feature bits */ - hw->host_features = VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES); + host_features = VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES); PMD_INIT_LOG(DEBUG, "host_features before negotiate = %x", - hw->host_features); + host_features); /* * Negotiate features: Subset of device feature bits are written back * guest feature bits. */ - hw->guest_features = vtpci_negotiate_features(hw, guest_features); + hw->guest_features = vtpci_negotiate_features(hw, host_features); PMD_INIT_LOG(DEBUG, "features after negotiate = %x", hw->guest_features); } @@ -742,14 +824,7 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, return -1; } - if (!(rte_eal_get_configuration()->flags & EAL_FLG_HIGH_IOPL)) { - PMD_INIT_LOG(ERR, - "IOPL call failed in EAL init - cannot use virtio PMD driver\n"); - return -1; - } - eth_dev->dev_ops = &virtio_eth_dev_ops; - eth_dev->rx_pkt_burst = &virtio_recv_pkts; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; if (rte_eal_process_type() == RTE_PROC_SECONDARY) @@ -757,8 +832,6 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev = eth_dev->pci_dev; - hw->device_id = pci_dev->id.device_id; - hw->vendor_id = pci_dev->id.vendor_id; #ifdef RTE_EXEC_ENV_LINUXAPP { char dirname[PATH_MAX]; @@ -806,10 +879,13 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, virtio_negotiate_features(hw); /* Setting up rx_header size for the device */ - if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) + if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) { + eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts; hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); - else + } else { + eth_dev->rx_pkt_burst = &virtio_recv_pkts; 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); @@ -902,8 +978,14 @@ static struct eth_driver rte_virtio_pmd = { * Returns 0 on success. */ static int -rte_virtio_pmd_init(const char *name __rte_unused, const char *param __rte_unused) +rte_virtio_pmd_init(const char *name __rte_unused, + const char *param __rte_unused) { + if (rte_eal_iopl_init() != 0) { + PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD"); + return -1; + } + rte_eth_driver_register(&rte_virtio_pmd); return 0; } @@ -926,8 +1008,17 @@ virtio_dev_tx_queue_release(__rte_unused void *txq) * It returns 0 on success. */ static int -virtio_dev_configure(__rte_unused struct rte_eth_dev *dev) +virtio_dev_configure(struct rte_eth_dev *dev) { + const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + + PMD_INIT_LOG(DEBUG, "configure"); + + if (rxmode->hw_ip_checksum) { + PMD_DRV_LOG(ERR, "HW IP checksum not supported"); + return (-EINVAL); + } + return 0; } @@ -946,8 +1037,6 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Tell the host we've known how to drive the device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); - hw->adapter_stopped = 0; - virtio_dev_cq_start(dev); /* Do final configuration before rx/tx engine starts */ @@ -1007,7 +1096,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) while ((buf = (struct rte_mbuf *)virtqueue_detatch_unused( dev->data->rx_queues[i])) != NULL) { - rte_pktmbuf_free_seg(buf); + rte_pktmbuf_free(buf); mbuf_num++; } @@ -1026,7 +1115,8 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) mbuf_num = 0; while ((buf = (struct rte_mbuf *)virtqueue_detatch_unused( dev->data->tx_queues[i])) != NULL) { - rte_pktmbuf_free_seg(buf); + rte_pktmbuf_free(buf); + mbuf_num++; }