Implement standard virtio controls for enabling and disabling promiscious and multicast. Signed-off-by: Stephen Hemminger --- a/lib/librte_pmd_virtio/virtio_ethdev.c 2014-08-25 19:00:16.754586819 -0700 +++ b/lib/librte_pmd_virtio/virtio_ethdev.c 2014-08-25 19:02:48.019397658 -0700 @@ -77,6 +77,11 @@ static void virtio_get_hwaddr(struct vir static void virtio_dev_rx_queue_release(__rte_unused void *rxq); static void virtio_dev_tx_queue_release(__rte_unused void *txq); +static void virtio_promiscuous_enable(struct rte_eth_dev *dev); +static void virtio_promiscuous_disable(struct rte_eth_dev *dev); +static void virtio_allmulticast_enable(struct rte_eth_dev *dev); +static void virtio_allmulticast_disable(struct rte_eth_dev *dev); + static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); @@ -405,23 +410,27 @@ virtio_dev_close(struct rte_eth_dev *dev * dev_ops for virtio, bare necessities for basic operation */ static struct eth_dev_ops virtio_eth_dev_ops = { - .dev_configure = virtio_dev_configure, - .dev_start = virtio_dev_start, - .dev_stop = virtio_dev_stop, - .dev_close = virtio_dev_close, - - .dev_infos_get = virtio_dev_info_get, - .stats_get = virtio_dev_stats_get, - .stats_reset = virtio_dev_stats_reset, - .link_update = virtio_dev_link_update, - .mac_addr_add = NULL, - .mac_addr_remove = NULL, - .rx_queue_setup = virtio_dev_rx_queue_setup, + .dev_configure = virtio_dev_configure, + .dev_start = virtio_dev_start, + .dev_stop = virtio_dev_stop, + .dev_close = virtio_dev_close, + + .dev_infos_get = virtio_dev_info_get, + .stats_get = virtio_dev_stats_get, + .stats_reset = virtio_dev_stats_reset, + .link_update = virtio_dev_link_update, + .promiscuous_enable = virtio_promiscuous_enable, + .promiscuous_disable = virtio_promiscuous_disable, + .allmulticast_enable = virtio_allmulticast_enable, + .allmulticast_disable = virtio_allmulticast_disable, + .mac_addr_add = NULL, + .mac_addr_remove = NULL, + .rx_queue_setup = virtio_dev_rx_queue_setup, /* meaningfull only to multiple queue */ - .rx_queue_release = virtio_dev_rx_queue_release, - .tx_queue_setup = virtio_dev_tx_queue_setup, + .rx_queue_release = virtio_dev_rx_queue_release, + .tx_queue_setup = virtio_dev_tx_queue_setup, /* meaningfull only to multiple queue */ - .tx_queue_release = virtio_dev_tx_queue_release, + .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, }; @@ -466,6 +475,63 @@ virtio_dev_atomic_write_link_status(stru return 0; } +/* Control receive processing (ie multicast, promiscious, mac address). */ +static int virtio_ctrl_rx(struct virtio_hw *hw, uint8_t cmd, uint8_t onoff) +{ + struct virtio_pmd_ctrl ctrl; + int len, ret; + + if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) + return -ENOTSUP; + + ctrl.hdr.class = VIRTIO_NET_CTRL_RX; + ctrl.hdr.cmd = cmd; + memcpy(ctrl.data, &onoff, sizeof(uint8_t)); + + len = sizeof(uint8_t); + ret = virtio_send_command(hw->cvq, &ctrl, &len, 1); + if (ret != 0) + PMD_DRV_LOG(NOTICE, "ctrl_rx %u failed: %d\n", cmd, ret); + + return ret; +} + +static void +virtio_promiscuous_enable(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + PMD_INIT_LOG(DEBUG, "promiscious enable"); + virtio_ctrl_rx(hw, VIRTIO_NET_CTRL_RX_PROMISC, 1); +} + +static void +virtio_promiscuous_disable(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + PMD_INIT_LOG(DEBUG, "promiscious disable"); + virtio_ctrl_rx(hw, VIRTIO_NET_CTRL_RX_PROMISC, 0); +} + +static void +virtio_allmulticast_enable(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + PMD_INIT_LOG(DEBUG, "allmulticast enable"); + virtio_ctrl_rx(hw, VIRTIO_NET_CTRL_RX_ALLMULTI, 1); +} + +static void +virtio_allmulticast_disable(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + PMD_INIT_LOG(DEBUG, "allmulticast disable"); + virtio_ctrl_rx(hw, VIRTIO_NET_CTRL_RX_ALLMULTI, 0); +} + static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { @@ -559,7 +625,7 @@ virtio_negotiate_features(struct virtio_ { uint32_t host_features, mask; - mask = VIRTIO_NET_F_CTRL_RX | VIRTIO_NET_F_CTRL_VLAN; + mask = VIRTIO_NET_F_CTRL_VLAN; mask |= VIRTIO_NET_F_CSUM | VIRTIO_NET_F_GUEST_CSUM; /* TSO and LRO are only available when their corresponding