net: atl1: slight optimization of addr compare
[firefly-linux-kernel-4.4.55.git] / drivers / net / vxlan.c
index 0358c07f7669142034e089660425a8fdb88236e2..aef44aa44fe3dd4b29a257e4019d461bcb3dbe78 100644 (file)
@@ -916,17 +916,32 @@ static bool vxlan_snoop(struct net_device *dev,
 }
 
 /* See if multicast group is already in use by other ID */
-static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip)
+static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
 {
        struct vxlan_dev *vxlan;
 
+       /* The vxlan_sock is only used by dev, leaving group has
+        * no effect on other vxlan devices.
+        */
+       if (atomic_read(&dev->vn_sock->refcnt) == 1)
+               return false;
+
        list_for_each_entry(vxlan, &vn->vxlan_list, next) {
-               if (!netif_running(vxlan->dev))
+               if (!netif_running(vxlan->dev) || vxlan == dev)
                        continue;
 
-               if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
-                                    remote_ip))
-                       return true;
+               if (vxlan->vn_sock != dev->vn_sock)
+                       continue;
+
+               if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip,
+                                     &dev->default_dst.remote_ip))
+                       continue;
+
+               if (vxlan->default_dst.remote_ifindex !=
+                   dev->default_dst.remote_ifindex)
+                       continue;
+
+               return true;
        }
 
        return false;
@@ -1390,7 +1405,7 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
        unsigned int range = (port_max - port_min) + 1;
        u32 hash;
 
-       hash = skb_get_rxhash(skb);
+       hash = skb_get_hash(skb);
        if (!hash)
                hash = jhash(skb->data, 2 * ETH_ALEN,
                             (__force u32) skb->protocol);
@@ -1668,7 +1683,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        netdev_dbg(dev, "circular route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
                        dev->stats.collisions++;
-                       goto tx_error;
+                       goto rt_tx_error;
                }
 
                /* Bypass encapsulation if the destination is local */
@@ -1935,7 +1950,6 @@ static void vxlan_uninit(struct net_device *dev)
 /* Start ageing timer and join group when device is brought up */
 static int vxlan_open(struct net_device *dev)
 {
-       struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_sock *vs = vxlan->vn_sock;
 
@@ -1943,8 +1957,7 @@ static int vxlan_open(struct net_device *dev)
        if (!vs)
                return -ENOTCONN;
 
-       if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
-           vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
+       if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_join);
@@ -1983,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev)
        struct vxlan_sock *vs = vxlan->vn_sock;
 
        if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
-           ! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
+           !vxlan_group_used(vn, vxlan)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_leave);
@@ -2001,6 +2014,29 @@ static void vxlan_set_multicast_list(struct net_device *dev)
 {
 }
 
+static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_rdst *dst = &vxlan->default_dst;
+       struct net_device *lowerdev;
+       int max_mtu;
+
+       lowerdev = __dev_get_by_index(dev_net(dev), dst->remote_ifindex);
+       if (lowerdev == NULL)
+               return eth_change_mtu(dev, new_mtu);
+
+       if (dst->remote_ip.sa.sa_family == AF_INET6)
+               max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
+       else
+               max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+       if (new_mtu < 68 || new_mtu > max_mtu)
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_init               = vxlan_init,
        .ndo_uninit             = vxlan_uninit,
@@ -2009,7 +2045,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_start_xmit         = vxlan_xmit,
        .ndo_get_stats64        = ip_tunnel_get_stats64,
        .ndo_set_rx_mode        = vxlan_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_change_mtu         = vxlan_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_fdb_add            = vxlan_fdb_add,