diff options
author | Tom Herbert <therbert@google.com> | 2014-07-13 22:49:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-14 19:12:15 -0400 |
commit | 3ee64f39bebe1a181a1af3e4b641a9b0aae1799a (patch) | |
tree | bc714ecbf56f9fe25c77833be02912f08ca9a1d0 /drivers/net/vxlan.c | |
parent | 8024e02879ddd5042be02c70557f74cdc70b44b4 (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/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 115 |
1 files changed, 24 insertions, 91 deletions
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) | 2343 | static 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 | */ | ||
2347 | static 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 | ||
2396 | static 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 | ||
2402 | static 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); |