]> Pileus Git - ~andy/linux/blobdiff - drivers/net/vxlan.c
qlcnic: fix ping resumption to a VM after a live migration
[~andy/linux] / drivers / net / vxlan.c
index 3b3fdf648ea741267800a2b49eee87d835d2370a..9d70421cf3a04e5eace7f079e38ad75c36709713 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/hash.h>
+#include <linux/ethtool.h>
 #include <net/arp.h>
 #include <net/ndisc.h>
 #include <net/ip.h>
@@ -392,7 +393,8 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 }
 
 /* Delete entry (via netlink) */
-static int vxlan_fdb_delete(struct ndmsg *ndm, struct net_device *dev,
+static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
+                           struct net_device *dev,
                            const unsigned char *addr)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -505,7 +507,8 @@ static int vxlan_join_group(struct net_device *dev)
        struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct sock *sk = vn->sock->sk;
        struct ip_mreqn mreq = {
-               .imr_multiaddr.s_addr = vxlan->gaddr,
+               .imr_multiaddr.s_addr   = vxlan->gaddr,
+               .imr_ifindex            = vxlan->link,
        };
        int err;
 
@@ -532,7 +535,8 @@ static int vxlan_leave_group(struct net_device *dev)
        int err = 0;
        struct sock *sk = vn->sock->sk;
        struct ip_mreqn mreq = {
-               .imr_multiaddr.s_addr = vxlan->gaddr,
+               .imr_multiaddr.s_addr   = vxlan->gaddr,
+               .imr_ifindex            = vxlan->link,
        };
 
        /* Only leave group when last vxlan is done. */
@@ -1189,6 +1193,7 @@ static void vxlan_setup(struct net_device *dev)
 
        dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
        spin_lock_init(&vxlan->hash_lock);
 
@@ -1268,6 +1273,18 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
        return 0;
 }
 
+static void vxlan_get_drvinfo(struct net_device *netdev,
+                             struct ethtool_drvinfo *drvinfo)
+{
+       strlcpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version));
+       strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
+}
+
+static const struct ethtool_ops vxlan_ethtool_ops = {
+       .get_drvinfo    = vxlan_get_drvinfo,
+       .get_link       = ethtool_op_get_link,
+};
+
 static int vxlan_newlink(struct net *net, struct net_device *dev,
                         struct nlattr *tb[], struct nlattr *data[])
 {
@@ -1345,6 +1362,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                vxlan->port_max = ntohs(p->high);
        }
 
+       SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops);
+
        err = register_netdevice(dev);
        if (!err)
                hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni));