Commit 3ee64f39 authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller

vxlan: Call udp_sock_create

In vxlan driver call common function udp_sock_create to create the
listener UDP port.
Signed-off-by: default avatarTom Herbert <therbert@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8024e028
...@@ -148,6 +148,7 @@ config VXLAN ...@@ -148,6 +148,7 @@ config VXLAN
tristate "Virtual eXtensible Local Area Network (VXLAN)" tristate "Virtual eXtensible Local Area Network (VXLAN)"
depends on INET depends on INET
select NET_IP_TUNNEL select NET_IP_TUNNEL
select NET_UDP_TUNNEL
---help--- ---help---
This allows one to create vxlan virtual interfaces that provide This allows one to create vxlan virtual interfaces that provide
Layer 2 Networks over Layer 3 Networks. VXLAN is often used Layer 2 Networks over Layer 3 Networks. VXLAN is often used
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <net/ip_tunnels.h> #include <net/ip_tunnels.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/udp_tunnel.h>
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
#include <net/route.h> #include <net/route.h>
#include <net/dsfield.h> #include <net/dsfield.h>
...@@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work) ...@@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work)
kfree_rcu(vs, rcu); kfree_rcu(vs, rcu);
} }
#if IS_ENABLED(CONFIG_IPV6) static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
/* Create UDP socket for encapsulation receive. AF_INET6 socket __be16 port, u32 flags)
* could be used for both IPv4 and IPv6 communications, but
* users may set bindv6only=1.
*/
static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
{ {
struct sock *sk;
struct socket *sock; struct socket *sock;
struct sockaddr_in6 vxlan_addr = { struct udp_port_cfg udp_conf;
.sin6_family = AF_INET6, int err;
.sin6_port = port,
};
int rc, val = 1;
rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (rc < 0) {
pr_debug("UDPv6 socket create failed\n");
return ERR_PTR(rc);
}
/* Put in proper namespace */
sk = sock->sk;
sk_change_net(sk, net);
kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
(char *)&val, sizeof(val));
rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr,
sizeof(struct sockaddr_in6));
if (rc < 0) {
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 ERR_PTR(rc);
}
/* At this point, IPv6 module should have been loaded in
* sock_create_kern().
*/
BUG_ON(!ipv6_stub);
/* Disable multicast loopback */
inet_sk(sk)->mc_loop = 0;
if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX)
udp_set_no_check6_tx(sk, true);
if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX)
udp_set_no_check6_rx(sk, true);
return sock;
}
#else
static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) memset(&udp_conf, 0, sizeof(udp_conf));
{
return ERR_PTR(-EPFNOSUPPORT);
}
#endif
static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) if (ipv6) {
{ udp_conf.family = AF_INET6;
struct sock *sk; udp_conf.use_udp6_tx_checksums =
struct socket *sock; !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
struct sockaddr_in vxlan_addr = { udp_conf.use_udp6_rx_checksums =
.sin_family = AF_INET, !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
.sin_addr.s_addr = htonl(INADDR_ANY), } else {
.sin_port = port, udp_conf.family = AF_INET;
}; udp_conf.local_ip.s_addr = INADDR_ANY;
int rc; udp_conf.use_udp_checksums =
!!(flags & VXLAN_F_UDP_CSUM);
/* Create UDP socket for encapsulation receive. */
rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (rc < 0) {
pr_debug("UDP socket create failed\n");
return ERR_PTR(rc);
} }
/* Put in proper namespace */ udp_conf.local_udp_port = port;
sk = sock->sk;
sk_change_net(sk, net);
rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr, /* Open UDP socket */
sizeof(vxlan_addr)); err = udp_sock_create(net, &udp_conf, &sock);
if (rc < 0) { if (err < 0)
pr_debug("bind for UDP socket %pI4:%u (%d)\n", return ERR_PTR(err);
&vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
sk_release_kernel(sk);
return ERR_PTR(rc);
}
/* Disable multicast loopback */ /* Disable multicast loopback */
inet_sk(sk)->mc_loop = 0; inet_sk(sock->sk)->mc_loop = 0;
if (!(flags & VXLAN_F_UDP_CSUM))
sock->sk->sk_no_check_tx = 1;
return sock; return sock;
} }
...@@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, ...@@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
INIT_WORK(&vs->del_work, vxlan_del_work); INIT_WORK(&vs->del_work, vxlan_del_work);
if (ipv6) sock = vxlan_create_sock(net, ipv6, port, flags);
sock = create_v6_sock(net, port, flags);
else
sock = create_v4_sock(net, port, flags);
if (IS_ERR(sock)) { if (IS_ERR(sock)) {
kfree(vs); kfree(vs);
return ERR_CAST(sock); return ERR_CAST(sock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment