Implement standard virtio controls for enabling and disabling
promiscious and multicast.

Signed-off-by: Stephen Hemminger <shemming at brocade.com>

--- 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

Reply via email to