diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 100 |
1 files changed, 63 insertions, 37 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ed384fee76ac..481f85d604a4 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -916,17 +916,32 @@ static bool vxlan_snoop(struct net_device *dev, | |||
916 | } | 916 | } |
917 | 917 | ||
918 | /* See if multicast group is already in use by other ID */ | 918 | /* See if multicast group is already in use by other ID */ |
919 | static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip) | 919 | static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) |
920 | { | 920 | { |
921 | struct vxlan_dev *vxlan; | 921 | struct vxlan_dev *vxlan; |
922 | 922 | ||
923 | /* The vxlan_sock is only used by dev, leaving group has | ||
924 | * no effect on other vxlan devices. | ||
925 | */ | ||
926 | if (atomic_read(&dev->vn_sock->refcnt) == 1) | ||
927 | return false; | ||
928 | |||
923 | list_for_each_entry(vxlan, &vn->vxlan_list, next) { | 929 | list_for_each_entry(vxlan, &vn->vxlan_list, next) { |
924 | if (!netif_running(vxlan->dev)) | 930 | if (!netif_running(vxlan->dev) || vxlan == dev) |
925 | continue; | 931 | continue; |
926 | 932 | ||
927 | if (vxlan_addr_equal(&vxlan->default_dst.remote_ip, | 933 | if (vxlan->vn_sock != dev->vn_sock) |
928 | remote_ip)) | 934 | continue; |
929 | return true; | 935 | |
936 | if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip, | ||
937 | &dev->default_dst.remote_ip)) | ||
938 | continue; | ||
939 | |||
940 | if (vxlan->default_dst.remote_ifindex != | ||
941 | dev->default_dst.remote_ifindex) | ||
942 | continue; | ||
943 | |||
944 | return true; | ||
930 | } | 945 | } |
931 | 946 | ||
932 | return false; | 947 | return false; |
@@ -1066,7 +1081,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, | |||
1066 | struct iphdr *oip = NULL; | 1081 | struct iphdr *oip = NULL; |
1067 | struct ipv6hdr *oip6 = NULL; | 1082 | struct ipv6hdr *oip6 = NULL; |
1068 | struct vxlan_dev *vxlan; | 1083 | struct vxlan_dev *vxlan; |
1069 | struct pcpu_tstats *stats; | 1084 | struct pcpu_sw_netstats *stats; |
1070 | union vxlan_addr saddr; | 1085 | union vxlan_addr saddr; |
1071 | __u32 vni; | 1086 | __u32 vni; |
1072 | int err = 0; | 1087 | int err = 0; |
@@ -1366,20 +1381,6 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) | |||
1366 | return false; | 1381 | return false; |
1367 | } | 1382 | } |
1368 | 1383 | ||
1369 | static void vxlan_sock_put(struct sk_buff *skb) | ||
1370 | { | ||
1371 | sock_put(skb->sk); | ||
1372 | } | ||
1373 | |||
1374 | /* On transmit, associate with the tunnel socket */ | ||
1375 | static void vxlan_set_owner(struct sock *sk, struct sk_buff *skb) | ||
1376 | { | ||
1377 | skb_orphan(skb); | ||
1378 | sock_hold(sk); | ||
1379 | skb->sk = sk; | ||
1380 | skb->destructor = vxlan_sock_put; | ||
1381 | } | ||
1382 | |||
1383 | /* Compute source port for outgoing packet | 1384 | /* Compute source port for outgoing packet |
1384 | * first choice to use L4 flow hash since it will spread | 1385 | * first choice to use L4 flow hash since it will spread |
1385 | * better and maybe available from hardware | 1386 | * better and maybe available from hardware |
@@ -1390,7 +1391,7 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb) | |||
1390 | unsigned int range = (port_max - port_min) + 1; | 1391 | unsigned int range = (port_max - port_min) + 1; |
1391 | u32 hash; | 1392 | u32 hash; |
1392 | 1393 | ||
1393 | hash = skb_get_rxhash(skb); | 1394 | hash = skb_get_hash(skb); |
1394 | if (!hash) | 1395 | if (!hash) |
1395 | hash = jhash(skb->data, 2 * ETH_ALEN, | 1396 | hash = jhash(skb->data, 2 * ETH_ALEN, |
1396 | (__force u32) skb->protocol); | 1397 | (__force u32) skb->protocol); |
@@ -1499,8 +1500,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
1499 | ip6h->daddr = *daddr; | 1500 | ip6h->daddr = *daddr; |
1500 | ip6h->saddr = *saddr; | 1501 | ip6h->saddr = *saddr; |
1501 | 1502 | ||
1502 | vxlan_set_owner(vs->sock->sk, skb); | ||
1503 | |||
1504 | err = handle_offloads(skb); | 1503 | err = handle_offloads(skb); |
1505 | if (err) | 1504 | if (err) |
1506 | return err; | 1505 | return err; |
@@ -1557,8 +1556,6 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
1557 | uh->len = htons(skb->len); | 1556 | uh->len = htons(skb->len); |
1558 | uh->check = 0; | 1557 | uh->check = 0; |
1559 | 1558 | ||
1560 | vxlan_set_owner(vs->sock->sk, skb); | ||
1561 | |||
1562 | err = handle_offloads(skb); | 1559 | err = handle_offloads(skb); |
1563 | if (err) | 1560 | if (err) |
1564 | return err; | 1561 | return err; |
@@ -1572,11 +1569,12 @@ EXPORT_SYMBOL_GPL(vxlan_xmit_skb); | |||
1572 | static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, | 1569 | static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, |
1573 | struct vxlan_dev *dst_vxlan) | 1570 | struct vxlan_dev *dst_vxlan) |
1574 | { | 1571 | { |
1575 | struct pcpu_tstats *tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); | 1572 | struct pcpu_sw_netstats *tx_stats, *rx_stats; |
1576 | struct pcpu_tstats *rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); | ||
1577 | union vxlan_addr loopback; | 1573 | union vxlan_addr loopback; |
1578 | union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; | 1574 | union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; |
1579 | 1575 | ||
1576 | tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); | ||
1577 | rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); | ||
1580 | skb->pkt_type = PACKET_HOST; | 1578 | skb->pkt_type = PACKET_HOST; |
1581 | skb->encapsulation = 0; | 1579 | skb->encapsulation = 0; |
1582 | skb->dev = dst_vxlan->dev; | 1580 | skb->dev = dst_vxlan->dev; |
@@ -1770,7 +1768,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1770 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1768 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1771 | struct ethhdr *eth; | 1769 | struct ethhdr *eth; |
1772 | bool did_rsc = false; | 1770 | bool did_rsc = false; |
1773 | struct vxlan_rdst *rdst; | 1771 | struct vxlan_rdst *rdst, *fdst = NULL; |
1774 | struct vxlan_fdb *f; | 1772 | struct vxlan_fdb *f; |
1775 | 1773 | ||
1776 | skb_reset_mac_header(skb); | 1774 | skb_reset_mac_header(skb); |
@@ -1812,7 +1810,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1812 | vxlan_fdb_miss(vxlan, eth->h_dest); | 1810 | vxlan_fdb_miss(vxlan, eth->h_dest); |
1813 | 1811 | ||
1814 | dev->stats.tx_dropped++; | 1812 | dev->stats.tx_dropped++; |
1815 | dev_kfree_skb(skb); | 1813 | kfree_skb(skb); |
1816 | return NETDEV_TX_OK; | 1814 | return NETDEV_TX_OK; |
1817 | } | 1815 | } |
1818 | } | 1816 | } |
@@ -1820,12 +1818,19 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1820 | list_for_each_entry_rcu(rdst, &f->remotes, list) { | 1818 | list_for_each_entry_rcu(rdst, &f->remotes, list) { |
1821 | struct sk_buff *skb1; | 1819 | struct sk_buff *skb1; |
1822 | 1820 | ||
1821 | if (!fdst) { | ||
1822 | fdst = rdst; | ||
1823 | continue; | ||
1824 | } | ||
1823 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1825 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1824 | if (skb1) | 1826 | if (skb1) |
1825 | vxlan_xmit_one(skb1, dev, rdst, did_rsc); | 1827 | vxlan_xmit_one(skb1, dev, rdst, did_rsc); |
1826 | } | 1828 | } |
1827 | 1829 | ||
1828 | dev_kfree_skb(skb); | 1830 | if (fdst) |
1831 | vxlan_xmit_one(skb, dev, fdst, did_rsc); | ||
1832 | else | ||
1833 | kfree_skb(skb); | ||
1829 | return NETDEV_TX_OK; | 1834 | return NETDEV_TX_OK; |
1830 | } | 1835 | } |
1831 | 1836 | ||
@@ -1882,12 +1887,12 @@ static int vxlan_init(struct net_device *dev) | |||
1882 | struct vxlan_sock *vs; | 1887 | struct vxlan_sock *vs; |
1883 | int i; | 1888 | int i; |
1884 | 1889 | ||
1885 | dev->tstats = alloc_percpu(struct pcpu_tstats); | 1890 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); |
1886 | if (!dev->tstats) | 1891 | if (!dev->tstats) |
1887 | return -ENOMEM; | 1892 | return -ENOMEM; |
1888 | 1893 | ||
1889 | for_each_possible_cpu(i) { | 1894 | for_each_possible_cpu(i) { |
1890 | struct pcpu_tstats *vxlan_stats; | 1895 | struct pcpu_sw_netstats *vxlan_stats; |
1891 | vxlan_stats = per_cpu_ptr(dev->tstats, i); | 1896 | vxlan_stats = per_cpu_ptr(dev->tstats, i); |
1892 | u64_stats_init(&vxlan_stats->syncp); | 1897 | u64_stats_init(&vxlan_stats->syncp); |
1893 | } | 1898 | } |
@@ -1935,7 +1940,6 @@ static void vxlan_uninit(struct net_device *dev) | |||
1935 | /* Start ageing timer and join group when device is brought up */ | 1940 | /* Start ageing timer and join group when device is brought up */ |
1936 | static int vxlan_open(struct net_device *dev) | 1941 | static int vxlan_open(struct net_device *dev) |
1937 | { | 1942 | { |
1938 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); | ||
1939 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1943 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1940 | struct vxlan_sock *vs = vxlan->vn_sock; | 1944 | struct vxlan_sock *vs = vxlan->vn_sock; |
1941 | 1945 | ||
@@ -1943,8 +1947,7 @@ static int vxlan_open(struct net_device *dev) | |||
1943 | if (!vs) | 1947 | if (!vs) |
1944 | return -ENOTCONN; | 1948 | return -ENOTCONN; |
1945 | 1949 | ||
1946 | if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && | 1950 | if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { |
1947 | vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) { | ||
1948 | vxlan_sock_hold(vs); | 1951 | vxlan_sock_hold(vs); |
1949 | dev_hold(dev); | 1952 | dev_hold(dev); |
1950 | queue_work(vxlan_wq, &vxlan->igmp_join); | 1953 | queue_work(vxlan_wq, &vxlan->igmp_join); |
@@ -1983,7 +1986,7 @@ static int vxlan_stop(struct net_device *dev) | |||
1983 | struct vxlan_sock *vs = vxlan->vn_sock; | 1986 | struct vxlan_sock *vs = vxlan->vn_sock; |
1984 | 1987 | ||
1985 | if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && | 1988 | if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && |
1986 | ! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) { | 1989 | !vxlan_group_used(vn, vxlan)) { |
1987 | vxlan_sock_hold(vs); | 1990 | vxlan_sock_hold(vs); |
1988 | dev_hold(dev); | 1991 | dev_hold(dev); |
1989 | queue_work(vxlan_wq, &vxlan->igmp_leave); | 1992 | queue_work(vxlan_wq, &vxlan->igmp_leave); |
@@ -2001,6 +2004,29 @@ static void vxlan_set_multicast_list(struct net_device *dev) | |||
2001 | { | 2004 | { |
2002 | } | 2005 | } |
2003 | 2006 | ||
2007 | static int vxlan_change_mtu(struct net_device *dev, int new_mtu) | ||
2008 | { | ||
2009 | struct vxlan_dev *vxlan = netdev_priv(dev); | ||
2010 | struct vxlan_rdst *dst = &vxlan->default_dst; | ||
2011 | struct net_device *lowerdev; | ||
2012 | int max_mtu; | ||
2013 | |||
2014 | lowerdev = __dev_get_by_index(dev_net(dev), dst->remote_ifindex); | ||
2015 | if (lowerdev == NULL) | ||
2016 | return eth_change_mtu(dev, new_mtu); | ||
2017 | |||
2018 | if (dst->remote_ip.sa.sa_family == AF_INET6) | ||
2019 | max_mtu = lowerdev->mtu - VXLAN6_HEADROOM; | ||
2020 | else | ||
2021 | max_mtu = lowerdev->mtu - VXLAN_HEADROOM; | ||
2022 | |||
2023 | if (new_mtu < 68 || new_mtu > max_mtu) | ||
2024 | return -EINVAL; | ||
2025 | |||
2026 | dev->mtu = new_mtu; | ||
2027 | return 0; | ||
2028 | } | ||
2029 | |||
2004 | static const struct net_device_ops vxlan_netdev_ops = { | 2030 | static const struct net_device_ops vxlan_netdev_ops = { |
2005 | .ndo_init = vxlan_init, | 2031 | .ndo_init = vxlan_init, |
2006 | .ndo_uninit = vxlan_uninit, | 2032 | .ndo_uninit = vxlan_uninit, |
@@ -2009,7 +2035,7 @@ static const struct net_device_ops vxlan_netdev_ops = { | |||
2009 | .ndo_start_xmit = vxlan_xmit, | 2035 | .ndo_start_xmit = vxlan_xmit, |
2010 | .ndo_get_stats64 = ip_tunnel_get_stats64, | 2036 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
2011 | .ndo_set_rx_mode = vxlan_set_multicast_list, | 2037 | .ndo_set_rx_mode = vxlan_set_multicast_list, |
2012 | .ndo_change_mtu = eth_change_mtu, | 2038 | .ndo_change_mtu = vxlan_change_mtu, |
2013 | .ndo_validate_addr = eth_validate_addr, | 2039 | .ndo_validate_addr = eth_validate_addr, |
2014 | .ndo_set_mac_address = eth_mac_addr, | 2040 | .ndo_set_mac_address = eth_mac_addr, |
2015 | .ndo_fdb_add = vxlan_fdb_add, | 2041 | .ndo_fdb_add = vxlan_fdb_add, |