Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64bbca3c authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'udp_tunnel'



Tom Herbert says:

====================
udp: UDP tunnel enhancements

- Add udp_sock_create in new helper module udp_tunnel. Tunnel
  implementations call this function to create listener UDP ports.
- Make vxlan and l2tp call udp_sock_create.
- Move udp_tunnel_segment into udp_offload.c.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 39b1c29b 155e010e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ config VXLAN
       tristate "Virtual eXtensible Local Area Network (VXLAN)"
       depends on INET
       select NET_IP_TUNNEL
       select NET_UDP_TUNNEL
       ---help---
	  This allows one to create vxlan virtual interfaces that provide
	  Layer 2 Networks over Layer 3 Networks. VXLAN is often used
+24 −91
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <net/ip_tunnels.h>
#include <net/icmp.h>
#include <net/udp.h>
#include <net/udp_tunnel.h>
#include <net/rtnetlink.h>
#include <net/route.h>
#include <net/dsfield.h>
@@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work)
	kfree_rcu(vs, rcu);
}

#if IS_ENABLED(CONFIG_IPV6)
/* Create UDP socket for encapsulation receive. AF_INET6 socket
 * 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)
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
					__be16 port, u32 flags)
{
	struct sock *sk;
	struct socket *sock;
	struct sockaddr_in6 vxlan_addr = {
		.sin6_family = AF_INET6,
		.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
	struct udp_port_cfg udp_conf;
	int err;

static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
{
		return ERR_PTR(-EPFNOSUPPORT);
}
#endif
	memset(&udp_conf, 0, sizeof(udp_conf));

static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags)
{
	struct sock *sk;
	struct socket *sock;
	struct sockaddr_in vxlan_addr = {
		.sin_family = AF_INET,
		.sin_addr.s_addr = htonl(INADDR_ANY),
		.sin_port = port,
	};
	int rc;

	/* 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);
	if (ipv6) {
		udp_conf.family = AF_INET6;
		udp_conf.use_udp6_tx_checksums =
		    !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
		udp_conf.use_udp6_rx_checksums =
		    !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
	} else {
		udp_conf.family = AF_INET;
		udp_conf.local_ip.s_addr = INADDR_ANY;
		udp_conf.use_udp_checksums =
		    !!(flags & VXLAN_F_UDP_CSUM);
	}

	/* Put in proper namespace */
	sk = sock->sk;
	sk_change_net(sk, net);
	udp_conf.local_udp_port = port;

	rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr,
			 sizeof(vxlan_addr));
	if (rc < 0) {
		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 ERR_PTR(rc);
	}
	/* Open UDP socket */
	err = udp_sock_create(net, &udp_conf, &sock);
	if (err < 0)
		return ERR_PTR(err);

	/* Disable multicast loopback */
	inet_sk(sk)->mc_loop = 0;

	if (!(flags & VXLAN_F_UDP_CSUM))
		sock->sk->sk_no_check_tx = 1;
	inet_sk(sock->sk)->mc_loop = 0;

	return sock;
}
@@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,

	INIT_WORK(&vs->del_work, vxlan_del_work);

	if (ipv6)
		sock = create_v6_sock(net, port, flags);
	else
		sock = create_v4_sock(net, port, flags);
	sock = vxlan_create_sock(net, ipv6, port, flags);
	if (IS_ERR(sock)) {
		kfree(vs);
		return ERR_CAST(sock);
+32 −0
Original line number Diff line number Diff line
#ifndef __NET_UDP_TUNNEL_H
#define __NET_UDP_TUNNEL_H

struct udp_port_cfg {
	u8			family;

	/* Used only for kernel-created sockets */
	union {
		struct in_addr		local_ip;
#if IS_ENABLED(CONFIG_IPV6)
		struct in6_addr		local_ip6;
#endif
	};

	union {
		struct in_addr		peer_ip;
#if IS_ENABLED(CONFIG_IPV6)
		struct in6_addr		peer_ip6;
#endif
	};

	__be16			local_udp_port;
	__be16			peer_udp_port;
	unsigned int		use_udp_checksums:1,
				use_udp6_tx_checksums:1,
				use_udp6_rx_checksums:1;
};

int udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
		    struct socket **sockp);

#endif
+4 −0
Original line number Diff line number Diff line
@@ -307,6 +307,10 @@ config NET_IPVTI
	  the notion of a secure tunnel for IPSEC and then use routing protocol
	  on top.

config NET_UDP_TUNNEL
	tristate
	default n

config INET_AH
	tristate "IP: AH transformation"
	select XFRM_ALGO
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_IPIP) += ipip.o
gre-y := gre_demux.o
obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
obj-$(CONFIG_NET_IPGRE) += ip_gre.o
obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o
obj-$(CONFIG_NET_IPVTI) += ip_vti.o
obj-$(CONFIG_SYN_COOKIES) += syncookies.o
obj-$(CONFIG_INET_AH) += ah4.o
Loading