aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-07-13 22:49:42 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-14 19:12:15 -0400
commit3ee64f39bebe1a181a1af3e4b641a9b0aae1799a (patch)
treebc714ecbf56f9fe25c77833be02912f08ca9a1d0 /drivers/net
parent8024e02879ddd5042be02c70557f74cdc70b44b4 (diff)
vxlan: Call udp_sock_create
In vxlan driver call common function udp_sock_create to create the listener UDP port. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/vxlan.c115
2 files changed, 25 insertions, 91 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 89402c3b64f8..c6f6f69f8961 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -148,6 +148,7 @@ config VXLAN
148 tristate "Virtual eXtensible Local Area Network (VXLAN)" 148 tristate "Virtual eXtensible Local Area Network (VXLAN)"
149 depends on INET 149 depends on INET
150 select NET_IP_TUNNEL 150 select NET_IP_TUNNEL
151 select NET_UDP_TUNNEL
151 ---help--- 152 ---help---
152 This allows one to create vxlan virtual interfaces that provide 153 This allows one to create vxlan virtual interfaces that provide
153 Layer 2 Networks over Layer 3 Networks. VXLAN is often used 154 Layer 2 Networks over Layer 3 Networks. VXLAN is often used
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index e6808f7e4e32..d3f3e5d21874 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -33,6 +33,7 @@
33#include <net/ip_tunnels.h> 33#include <net/ip_tunnels.h>
34#include <net/icmp.h> 34#include <net/icmp.h>
35#include <net/udp.h> 35#include <net/udp.h>
36#include <net/udp_tunnel.h>
36#include <net/rtnetlink.h> 37#include <net/rtnetlink.h>
37#include <net/route.h> 38#include <net/route.h>
38#include <net/dsfield.h> 39#include <net/dsfield.h>
@@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work)
2339 kfree_rcu(vs, rcu); 2340 kfree_rcu(vs, rcu);
2340} 2341}
2341 2342
2342#if IS_ENABLED(CONFIG_IPV6) 2343static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
2343/* Create UDP socket for encapsulation receive. AF_INET6 socket 2344 __be16 port, u32 flags)
2344 * could be used for both IPv4 and IPv6 communications, but
2345 * users may set bindv6only=1.
2346 */
2347static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
2348{ 2345{
2349 struct sock *sk;
2350 struct socket *sock; 2346 struct socket *sock;
2351 struct sockaddr_in6 vxlan_addr = { 2347 struct udp_port_cfg udp_conf;
2352 .sin6_family = AF_INET6, 2348 int err;
2353 .sin6_port = port,
2354 };
2355 int rc, val = 1;
2356
2357 rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
2358 if (rc < 0) {
2359 pr_debug("UDPv6 socket create failed\n");
2360 return ERR_PTR(rc);
2361 }
2362
2363 /* Put in proper namespace */
2364 sk = sock->sk;
2365 sk_change_net(sk, net);
2366
2367 kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
2368 (char *)&val, sizeof(val));
2369 rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr,
2370 sizeof(struct sockaddr_in6));
2371 if (rc < 0) {
2372 pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n",
2373 &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc);
2374 sk_release_kernel(sk);
2375 return ERR_PTR(rc);
2376 }
2377 /* At this point, IPv6 module should have been loaded in
2378 * sock_create_kern().
2379 */
2380 BUG_ON(!ipv6_stub);
2381
2382 /* Disable multicast loopback */
2383 inet_sk(sk)->mc_loop = 0;
2384
2385 if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX)
2386 udp_set_no_check6_tx(sk, true);
2387
2388 if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX)
2389 udp_set_no_check6_rx(sk, true);
2390
2391 return sock;
2392}
2393
2394#else
2395 2349
2396static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) 2350 memset(&udp_conf, 0, sizeof(udp_conf));
2397{
2398 return ERR_PTR(-EPFNOSUPPORT);
2399}
2400#endif
2401 2351
2402static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) 2352 if (ipv6) {
2403{ 2353 udp_conf.family = AF_INET6;
2404 struct sock *sk; 2354 udp_conf.use_udp6_tx_checksums =
2405 struct socket *sock; 2355 !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
2406 struct sockaddr_in vxlan_addr = { 2356 udp_conf.use_udp6_rx_checksums =
2407 .sin_family = AF_INET, 2357 !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
2408 .sin_addr.s_addr = htonl(INADDR_ANY), 2358 } else {
2409 .sin_port = port, 2359 udp_conf.family = AF_INET;
2410 }; 2360 udp_conf.local_ip.s_addr = INADDR_ANY;
2411 int rc; 2361 udp_conf.use_udp_checksums =
2412 2362 !!(flags & VXLAN_F_UDP_CSUM);
2413 /* Create UDP socket for encapsulation receive. */
2414 rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
2415 if (rc < 0) {
2416 pr_debug("UDP socket create failed\n");
2417 return ERR_PTR(rc);
2418 } 2363 }
2419 2364
2420 /* Put in proper namespace */ 2365 udp_conf.local_udp_port = port;
2421 sk = sock->sk;
2422 sk_change_net(sk, net);
2423 2366
2424 rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr, 2367 /* Open UDP socket */
2425 sizeof(vxlan_addr)); 2368 err = udp_sock_create(net, &udp_conf, &sock);
2426 if (rc < 0) { 2369 if (err < 0)
2427 pr_debug("bind for UDP socket %pI4:%u (%d)\n", 2370 return ERR_PTR(err);
2428 &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
2429 sk_release_kernel(sk);
2430 return ERR_PTR(rc);
2431 }
2432 2371
2433 /* Disable multicast loopback */ 2372 /* Disable multicast loopback */
2434 inet_sk(sk)->mc_loop = 0; 2373 inet_sk(sock->sk)->mc_loop = 0;
2435
2436 if (!(flags & VXLAN_F_UDP_CSUM))
2437 sock->sk->sk_no_check_tx = 1;
2438 2374
2439 return sock; 2375 return sock;
2440} 2376}
@@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
2460 2396
2461 INIT_WORK(&vs->del_work, vxlan_del_work); 2397 INIT_WORK(&vs->del_work, vxlan_del_work);
2462 2398
2463 if (ipv6) 2399 sock = vxlan_create_sock(net, ipv6, port, flags);
2464 sock = create_v6_sock(net, port, flags);
2465 else
2466 sock = create_v4_sock(net, port, flags);
2467 if (IS_ERR(sock)) { 2400 if (IS_ERR(sock)) {
2468 kfree(vs); 2401 kfree(vs);
2469 return ERR_CAST(sock); 2402 return ERR_CAST(sock);