diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d1292fe746b..249e01c5600 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -60,10 +60,6 @@ #define VXLAN_N_VID (1u << 24) #define VXLAN_VID_MASK (VXLAN_N_VID - 1) -/* IP header + UDP + VXLAN + Ethernet header */ -#define VXLAN_HEADROOM (20 + 8 + 8 + 14) -/* IPv6 header + UDP + VXLAN + Ethernet header */ -#define VXLAN6_HEADROOM (40 + 8 + 8 + 14) #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ @@ -952,8 +948,7 @@ void vxlan_sock_release(struct vxlan_sock *vs) spin_lock(&vn->sock_lock); hlist_del_rcu(&vs->hlist); - smp_wmb(); - vs->sock->sk->sk_user_data = NULL; + rcu_assign_sk_user_data(vs->sock->sk, NULL); vxlan_notify_del_rx_port(sk); spin_unlock(&vn->sock_lock); @@ -1048,8 +1043,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) port = inet_sk(sk)->inet_sport; - smp_read_barrier_depends(); - vs = (struct vxlan_sock *)sk->sk_user_data; + vs = rcu_dereference_sk_user_data(sk); if (!vs) goto drop; @@ -1674,7 +1668,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 */ @@ -1886,11 +1880,19 @@ static int vxlan_init(struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs; + int i; dev->tstats = alloc_percpu(struct pcpu_tstats); if (!dev->tstats) return -ENOMEM; + for_each_possible_cpu(i) { + struct pcpu_tstats *vxlan_stats; + vxlan_stats = per_cpu_ptr(dev->tstats, i); + u64_stats_init(&vxlan_stats->syncp); + } + + spin_lock(&vn->sock_lock); vs = vxlan_find_sock(dev_net(dev), vxlan->dst_port); if (vs) { @@ -2089,7 +2091,7 @@ static void vxlan_setup(struct net_device *dev) vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.data = (unsigned long) vxlan; - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(dev_net(dev), &low, &high); vxlan->port_min = low; vxlan->port_max = high; vxlan->dst_port = htons(vxlan_port); @@ -2182,7 +2184,7 @@ static void vxlan_del_work(struct work_struct *work) * could be used for both IPv4 and IPv6 communications, but * users may set bindv6only=1. */ -static int create_v6_sock(struct net *net, __be16 port, struct socket **psock) +static struct socket *create_v6_sock(struct net *net, __be16 port) { struct sock *sk; struct socket *sock; @@ -2195,7 +2197,7 @@ static int create_v6_sock(struct net *net, __be16 port, struct socket **psock) rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDPv6 socket create failed\n"); - return rc; + return ERR_PTR(rc); } /* Put in proper namespace */ @@ -2210,28 +2212,27 @@ static int create_v6_sock(struct net *net, __be16 port, struct socket **psock) pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n", &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc); sk_release_kernel(sk); - return rc; + return ERR_PTR(rc); } /* At this point, IPv6 module should have been loaded in * sock_create_kern(). */ BUG_ON(!ipv6_stub); - *psock = sock; /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; - return 0; + return sock; } #else -static int create_v6_sock(struct net *net, __be16 port, struct socket **psock) +static struct socket *create_v6_sock(struct net *net, __be16 port) { - return -EPFNOSUPPORT; + return ERR_PTR(-EPFNOSUPPORT); } #endif -static int create_v4_sock(struct net *net, __be16 port, struct socket **psock) +static struct socket *create_v4_sock(struct net *net, __be16 port) { struct sock *sk; struct socket *sock; @@ -2246,7 +2247,7 @@ static int create_v4_sock(struct net *net, __be16 port, struct socket **psock) rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDP socket create failed\n"); - return rc; + return ERR_PTR(rc); } /* Put in proper namespace */ @@ -2259,13 +2260,12 @@ static int create_v4_sock(struct net *net, __be16 port, struct socket **psock) pr_debug("bind for UDP socket %pI4:%u (%d)\n", &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); sk_release_kernel(sk); - return rc; + return ERR_PTR(rc); } - *psock = sock; /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; - return 0; + return sock; } /* Create new listen socket if needed */ @@ -2276,7 +2276,6 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, struct vxlan_sock *vs; struct socket *sock; struct sock *sk; - int rc = 0; unsigned int h; vs = kmalloc(sizeof(*vs), GFP_KERNEL); @@ -2289,12 +2288,12 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, INIT_WORK(&vs->del_work, vxlan_del_work); if (ipv6) - rc = create_v6_sock(net, port, &sock); + sock = create_v6_sock(net, port); else - rc = create_v4_sock(net, port, &sock); - if (rc < 0) { + sock = create_v4_sock(net, port); + if (IS_ERR(sock)) { kfree(vs); - return ERR_PTR(rc); + return ERR_CAST(sock); } vs->sock = sock; @@ -2302,8 +2301,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, atomic_set(&vs->refcnt, 1); vs->rcv = rcv; vs->data = data; - smp_wmb(); - vs->sock->sk->sk_user_data = vs; + rcu_assign_sk_user_data(vs->sock->sk, vs); spin_lock(&vn->sock_lock); hlist_add_head_rcu(&vs->hlist, vs_head(net, port)); |