virtio_net: Add MAC fitler table support

Signed-off-by: Alex Williamson <alex.william...@hp.com>
---

 drivers/net/virtio_net.c   |   52 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/virtio_net.h |    6 ++++-
 2 files changed, 54 insertions(+), 4 deletions(-)


diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f502edd..d751711 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -505,6 +505,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        struct virtnet_info *vi = netdev_priv(dev);
        struct virtio_device *vdev = vi->vdev;
        u16 status = vi->status.raw;
+       struct dev_addr_list *uc_ptr, *mc_ptr;
+       int i;
 
        if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
                return;
@@ -519,11 +521,55 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        else
                status &= ~VIRTIO_NET_S_ALLMULTI;
                
-       if (dev->uc_count)
+       if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_MAC_TABLE)) {
+               if (dev->uc_count)
+                       status |= VIRTIO_NET_S_PROMISC;
+               if (dev->mc_count)
+                       status |= VIRTIO_NET_S_ALLMULTI;
+               if (status != vi->status.raw) {
+                       vi->status.raw = status;
+                       vdev->config->set(vdev,
+                                         offsetof(struct virtio_net_config,
+                                         status), &vi->status,
+                                         sizeof(vi->status));
+               }
+               return;
+       }
+
+       if (dev->uc_count > 16) {
                status |= VIRTIO_NET_S_PROMISC;
-       if (dev->mc_count)
+               if (dev->mc_count > 16)
+                       status |= VIRTIO_NET_S_ALLMULTI;
+       } else if (dev->uc_count + dev->mc_count > 16)
                status |= VIRTIO_NET_S_ALLMULTI;
 
+       if ((dev->uc_count && !(status & VIRTIO_NET_S_PROMISC)) ||
+           (dev->mc_count && !(status & VIRTIO_NET_S_ALLMULTI)))
+               status |= VIRTIO_NET_S_MAC_TABLE;
+       else
+               status &= ~VIRTIO_NET_S_MAC_TABLE;
+
+       uc_ptr = dev->uc_list;
+       mc_ptr = dev->mc_list;
+
+       for (i = 0; i < 16; i++) {
+               uint8_t entry[8] = { 0 };
+
+               if (uc_ptr && !(status & VIRTIO_NET_S_PROMISC)) {
+                       memcpy(entry, uc_ptr->da_addr, 6);
+                       entry[7] = 1;
+                       uc_ptr = uc_ptr->next;
+               } else if (mc_ptr && !(status & VIRTIO_NET_S_ALLMULTI)) {
+                       memcpy(entry, mc_ptr->da_addr, 6);
+                       entry[7] = 1;
+                       mc_ptr = mc_ptr->next;
+               }
+
+               vdev->config->set(vdev, offsetof(struct virtio_net_config,
+                                 mac_table) + (sizeof(entry) * i),
+                                 &entry, sizeof(entry));
+       }
+
        if (status != vi->status.raw) {
                vi->status.raw = status;
                vdev->config->set(vdev, offsetof(struct virtio_net_config,
@@ -744,7 +790,7 @@ static unsigned int features[] = {
        VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
        VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
        VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
-       VIRTIO_NET_F_STATUS,
+       VIRTIO_NET_F_STATUS, VIRTIO_NET_F_MAC_TABLE,
        VIRTIO_F_NOTIFY_ON_EMPTY,
 };
 
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 5a70edb..905319b 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -21,10 +21,12 @@
 #define VIRTIO_NET_F_HOST_ECN  13      /* Host can handle TSO[6] w/ ECN in. */
 #define VIRTIO_NET_F_HOST_UFO  14      /* Host can handle UFO in. */
 #define VIRTIO_NET_F_STATUS    16      /* virtio_net_config.status available */
+#define VIRTIO_NET_F_MAC_TABLE 17      /* Additional MAC addresses */
 
 #define VIRTIO_NET_S_LINK_UP   1       /* Link is up */
 #define VIRTIO_NET_S_PROMISC   2       /* Promiscuous mode */
 #define VIRTIO_NET_S_ALLMULTI  4       /* All-multicast mode */
+#define VIRTIO_NET_S_MAC_TABLE 8       /* Enable MAC filter table */
 
 struct virtio_net_config
 {
@@ -38,8 +40,10 @@ struct virtio_net_config
                        __u16 link:1;
                        __u16 promisc:1;
                        __u16 allmulti:1;
+                       __u16 mac_table:1;
                } bits;
-       } status;
+       } status;
+       __u64 mac_table[16];
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to