X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Flinux%2Fcompat%2Fvxlan.c;h=b8b8fa762d76548bcc33ec231222954952de6235;hb=e2f3178f0582eda302bdc5629189b6a56d9fbcdd;hp=db14f2f557e0202952baaca40a86ba53b382a491;hpb=13beaf6242986435200e545ce636446b12df8022;p=sliver-openvswitch.git diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index db14f2f55..b8b8fa762 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -18,6 +18,9 @@ * This code is derived from kernel vxlan module. */ +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0) + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -52,14 +55,10 @@ #include #include "compat.h" +#include "datapath.h" #include "gso.h" #include "vlan.h" -#define PORT_HASH_BITS 8 -#define PORT_HASH_SIZE (1<sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; -} - -/* Find VXLAN socket based on network namespace and UDP port */ - -static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port) -{ - struct vxlan_sock *vs; - - hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { - if (inet_sport(vs->sock->sk) == port) - return vs; - } - return NULL; -} - /* Callback from net/ipv4/udp.c to receive packets */ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) { @@ -124,7 +91,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB))) goto drop; - vs = vxlan_find_sock(sock_net(sk), inet_sport(sk)); + vs = rcu_dereference_sk_user_data(sk); if (!vs) goto drop; @@ -165,7 +132,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); @@ -219,8 +186,6 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, int min_headroom; int err; - skb_reset_inner_headers(skb); - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + VXLAN_HLEN + sizeof(struct iphdr) + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); @@ -239,6 +204,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, vlan_set_tci(skb, 0); } + skb_reset_inner_headers(skb); + vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_FLAGS); vxh->vx_vni = vni; @@ -259,7 +226,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, if (err) return err; - return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df); + return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, false); } static void rcu_free_vs(struct rcu_head *rcu) @@ -275,13 +242,11 @@ static void vxlan_del_work(struct work_struct *work) sk_release_kernel(vs->sock->sk); call_rcu(&vs->rcu, rcu_free_vs); - vxlan_cleanup_module(); } static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, vxlan_rcv_t *rcv, void *data) { - struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_sock *vs; struct sock *sk; struct sockaddr_in vxlan_addr = { @@ -325,9 +290,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; - spin_lock(&vn->sock_lock); - hlist_add_head_rcu(&vs->hlist, vs_head(net, port)); - spin_unlock(&vn->sock_lock); + rcu_assign_sk_user_data(vs->sock->sk, vs); /* Mark socket as an encapsulation socket. */ udp_sk(sk)->encap_type = 1; @@ -338,77 +301,17 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, vxlan_rcv_t *rcv, void *data, - bool no_share) + bool no_share, bool ipv6) { - struct vxlan_net *vn; - struct vxlan_sock *vs; - int err; - - err = vxlan_init_module(); - if (err) - return ERR_PTR(err); - - vn = net_generic(net, vxlan_net_id); - vs = vxlan_socket_create(net, port, rcv, data); - return vs; + return vxlan_socket_create(net, port, rcv, data); } void vxlan_sock_release(struct vxlan_sock *vs) { - struct vxlan_net *vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id); - - spin_lock(&vn->sock_lock); - hlist_del_rcu(&vs->hlist); - spin_unlock(&vn->sock_lock); + ASSERT_OVSL(); + rcu_assign_sk_user_data(vs->sock->sk, NULL); - queue_work(&vs->del_work); + queue_work(system_wq, &vs->del_work); } -static int vxlan_init_net(struct net *net) -{ - struct vxlan_net *vn = net_generic(net, vxlan_net_id); - unsigned int h; - - spin_lock_init(&vn->sock_lock); - - for (h = 0; h < PORT_HASH_SIZE; ++h) - INIT_HLIST_HEAD(&vn->sock_list[h]); - - return 0; -} - -static struct pernet_operations vxlan_net_ops = { - .init = vxlan_init_net, - .id = &vxlan_net_id, - .size = sizeof(struct vxlan_net), -}; - -static int refcnt; -static DEFINE_MUTEX(init_lock); -DEFINE_COMPAT_PNET_REG_FUNC(device); - -static int vxlan_init_module(void) -{ - int err = 0; - - mutex_lock(&init_lock); - if (refcnt) - goto out; - err = register_pernet_device(&vxlan_net_ops); -out: - if (!err) - refcnt++; - mutex_unlock(&init_lock); - return err; -} - -static void vxlan_cleanup_module(void) -{ - mutex_lock(&init_lock); - refcnt--; - if (refcnt) - goto out; - unregister_pernet_device(&vxlan_net_ops); -out: - mutex_unlock(&init_lock); -} +#endif /* 3.12 */