Upstream commit: udp: Add udp_sock_create for UDP tunnels to open listener socket
Added udp_tunnel.c which can contain some common functions for UDP tunnels. The first function in this is udp_sock_create which is used to open the listener port for a UDP tunnel. Signed-off-by: Tom Herbert <therb...@google.com> Signed-off-by: David S. Miller <da...@davemloft.net> Upstream: 8024e028 ("udp: Add udp_sock_create for UDP tunnels to open listener socket") Signed-off-by: Jesse Gross <je...@nicira.com> --- datapath/linux/.gitignore | 1 + datapath/linux/Modules.mk | 2 + datapath/linux/compat/include/net/udp_tunnel.h | 40 +++++++++++ datapath/linux/compat/udp_tunnel.c | 98 ++++++++++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 datapath/linux/compat/include/net/udp_tunnel.h create mode 100644 datapath/linux/compat/udp_tunnel.c diff --git a/datapath/linux/.gitignore b/datapath/linux/.gitignore index be233fc..fb19d78 100644 --- a/datapath/linux/.gitignore +++ b/datapath/linux/.gitignore @@ -38,6 +38,7 @@ /time.c /tmp /tunnel.c +/udp_tunnel.c /utils.c /vlan.c /vport-generic.c diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index a463331..945f859 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -11,6 +11,7 @@ openvswitch_sources += \ linux/compat/net_namespace.c \ linux/compat/reciprocal_div.c \ linux/compat/skbuff-openvswitch.c \ + linux/compat/udp_tunnel.c \ linux/compat/vxlan.c \ linux/compat/utils.c openvswitch_headers += \ @@ -71,6 +72,7 @@ openvswitch_headers += \ linux/compat/include/net/net_namespace.h \ linux/compat/include/net/netlink.h \ linux/compat/include/net/udp.h \ + linux/compat/include/net/udp_tunnel.h \ linux/compat/include/net/sock.h \ linux/compat/include/net/vxlan.h \ linux/compat/include/net/sctp/checksum.h diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h new file mode 100644 index 0000000..f25023f --- /dev/null +++ b/datapath/linux/compat/include/net/udp_tunnel.h @@ -0,0 +1,40 @@ +#ifndef __NET_UDP_TUNNEL_WRAPPER_H +#define __NET_UDP_TUNNEL_WRAPPER_H + +#include <linux/version.h> +#include <linux/kconfig.h> + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#include_next <net/udp_tunnel.h> +#else + +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 /* Linux version < 3.17 */ +#endif diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c new file mode 100644 index 0000000..e5fd224 --- /dev/null +++ b/datapath/linux/compat/udp_tunnel.c @@ -0,0 +1,98 @@ +#include <linux/version.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/socket.h> +#include <linux/udp.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <net/udp.h> +#include <net/udp_tunnel.h> +#include <net/net_namespace.h> + +int udp_sock_create(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp) +{ + int err = -EINVAL; + struct socket *sock = NULL; + +#if IS_ENABLED(CONFIG_IPV6) + if (cfg->family == AF_INET6) { + struct sockaddr_in6 udp6_addr; + + err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock); + if (err < 0) + goto error; + + sk_change_net(sock->sk, net); + + udp6_addr.sin6_family = AF_INET6; + memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6, + sizeof(udp6_addr.sin6_addr)); + udp6_addr.sin6_port = cfg->local_udp_port; + err = kernel_bind(sock, (struct sockaddr *)&udp6_addr, + sizeof(udp6_addr)); + if (err < 0) + goto error; + + if (cfg->peer_udp_port) { + udp6_addr.sin6_family = AF_INET6; + memcpy(&udp6_addr.sin6_addr, &cfg->peer_ip6, + sizeof(udp6_addr.sin6_addr)); + udp6_addr.sin6_port = cfg->peer_udp_port; + err = kernel_connect(sock, + (struct sockaddr *)&udp6_addr, + sizeof(udp6_addr), 0); + } + if (err < 0) + goto error; + } else +#endif + if (cfg->family == AF_INET) { + struct sockaddr_in udp_addr; + + err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock); + if (err < 0) + goto error; + + sk_change_net(sock->sk, net); + + udp_addr.sin_family = AF_INET; + udp_addr.sin_addr = cfg->local_ip; + udp_addr.sin_port = cfg->local_udp_port; + err = kernel_bind(sock, (struct sockaddr *)&udp_addr, + sizeof(udp_addr)); + if (err < 0) + goto error; + + if (cfg->peer_udp_port) { + udp_addr.sin_family = AF_INET; + udp_addr.sin_addr = cfg->peer_ip; + udp_addr.sin_port = cfg->peer_udp_port; + err = kernel_connect(sock, + (struct sockaddr *)&udp_addr, + sizeof(udp_addr), 0); + if (err < 0) + goto error; + } + } else { + return -EPFNOSUPPORT; + } + + + *sockp = sock; + + return 0; + +error: + if (sock) { + kernel_sock_shutdown(sock, SHUT_RDWR); + sk_release_kernel(sock->sk); + } + *sockp = NULL; + return err; +} + +#endif /* Linux version < 3.17 */ -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev