Update udp-socket-create to create ipv6 socket currectly. Partially backports commit fd384412e199b ("udp_tunnel: Seperate ipv6 functions into its own file.")
Signed-off-by: Pravin B Shelar <pshe...@ovn.org> --- acinclude.m4 | 2 + datapath/linux/Modules.mk | 1 + datapath/linux/compat/include/linux/udp.h | 22 +++++ datapath/linux/compat/include/net/udp.h | 1 - datapath/linux/compat/include/net/udp_tunnel.h | 30 +++++- datapath/linux/compat/udp_tunnel.c | 123 +++++++++++++++---------- 6 files changed, 125 insertions(+), 54 deletions(-) create mode 100644 datapath/linux/compat/include/linux/udp.h diff --git a/acinclude.m4 b/acinclude.m4 index 4d4341c..5d3e8b5 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -620,6 +620,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/uapi/linux/netdevice.h], [NET_NAME_UNKNOWN], [OVS_DEFINE([HAVE_NET_NAME_UNKNOWN])]) + OVS_GREP_IFELSE([$KSRC/include/net/sock.h], [sk_no_check_tx]) + OVS_GREP_IFELSE([$KSRC/include/linux/udp.h], [no_check6_tx]) OVS_GREP_IFELSE([$KSRC/include/linux/utsrelease.h], [el6], [OVS_DEFINE([HAVE_RHEL6_PER_CPU])]) diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index ae7c753..ef08083 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -67,6 +67,7 @@ openvswitch_headers += \ linux/compat/include/linux/stddef.h \ linux/compat/include/linux/types.h \ linux/compat/include/linux/u64_stats_sync.h \ + linux/compat/include/linux/udp.h \ linux/compat/include/linux/workqueue.h \ linux/compat/include/net/checksum.h \ linux/compat/include/net/dst.h \ diff --git a/datapath/linux/compat/include/linux/udp.h b/datapath/linux/compat/include/linux/udp.h new file mode 100644 index 0000000..65cb77c --- /dev/null +++ b/datapath/linux/compat/include/linux/udp.h @@ -0,0 +1,22 @@ +#ifndef __LINUX_UDP_WRAPPER_H +#define __LINUX_UDP_WRAPPER_H 1 + +#include_next <linux/udp.h> + +#ifndef HAVE_NO_CHECK6_TX +static inline void udp_set_no_check6_tx(struct sock *sk, bool val) +{ +#ifdef HAVE_SK_NO_CHECK_TX + sk->sk_no_check_tx = val; +#endif +} + +static inline void udp_set_no_check6_rx(struct sock *sk, bool val) +{ +#ifdef HAVE_SK_NO_CHECK_TX + sk->sk_no_check_rx = val; +#endif +} +#endif + +#endif diff --git a/datapath/linux/compat/include/net/udp.h b/datapath/linux/compat/include/net/udp.h index 41254aa..fa49fa5 100644 --- a/datapath/linux/compat/include/net/udp.h +++ b/datapath/linux/compat/include/net/udp.h @@ -59,5 +59,4 @@ static inline __sum16 udp_v4_check(int len, __be32 saddr, void rpl_udp_set_csum(bool nocheck, struct sk_buff *skb, __be32 saddr, __be32 daddr, int len); #endif - #endif diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h index 3132a53..7befd2d 100644 --- a/datapath/linux/compat/include/net/udp_tunnel.h +++ b/datapath/linux/compat/include/net/udp_tunnel.h @@ -41,9 +41,35 @@ struct udp_port_cfg { ipv6_v6only:1; }; +#define udp_sock_create4 rpl_udp_sock_create4 +int rpl_udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp); + +#define udp_sock_create6 rpl_udp_sock_create6 +#if IS_ENABLED(CONFIG_IPV6) +int rpl_udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp); +#else +static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp) +{ + return 0; +} +#endif + #define udp_sock_create rpl_udp_sock_create -int rpl_udp_sock_create(struct net *net, struct udp_port_cfg *cfg, - struct socket **sockp); +static inline int udp_sock_create(struct net *net, + struct udp_port_cfg *cfg, + struct socket **sockp) +{ + if (cfg->family == AF_INET) + return udp_sock_create4(net, cfg, sockp); + + if (cfg->family == AF_INET6) + return udp_sock_create6(net, cfg, sockp); + + return -EPFNOSUPPORT; +} typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb); typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk); diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c index b4d345b..daa3fa1 100644 --- a/datapath/linux/compat/udp_tunnel.c +++ b/datapath/linux/compat/udp_tunnel.c @@ -16,74 +16,95 @@ #include <net/ip6_tunnel.h> -int rpl_udp_sock_create(struct net *net, struct udp_port_cfg *cfg, - struct socket **sockp) +int rpl_udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp) { int err; struct socket *sock = NULL; + struct sockaddr_in udp_addr; -#if IS_ENABLED(CONFIG_IPV6) - if (cfg->family == AF_INET6) { - struct sockaddr_in6 udp6_addr; + err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock); + if (err < 0) + goto error; - err = sock_create_kern(net, AF_INET6, SOCK_DGRAM, 0, &sock); - if (err < 0) - goto error; + 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; - 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 (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 + } +#ifdef HAVE_SK_NO_CHECK_TX + sock->sk->sk_no_check_tx = !cfg->use_udp_checksums; #endif - if (cfg->family == AF_INET) { - struct sockaddr_in udp_addr; + *sockp = sock; + return 0; - err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock); - if (err < 0) - goto error; +error: + if (sock) { + kernel_sock_shutdown(sock, SHUT_RDWR); + sock_release(sock); + } + *sockp = NULL; + return err; +} +EXPORT_SYMBOL(rpl_udp_sock_create4); - 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)); +int rpl_udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, + struct socket **sockp) +{ + struct sockaddr_in6 udp6_addr; + int err; + struct socket *sock = NULL; + + err = sock_create_kern(net, AF_INET6, SOCK_DGRAM, 0, &sock); + if (err < 0) + goto error; + + if (cfg->ipv6_v6only) { + int val = 1; + + err = kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &val, sizeof(val)); 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; + 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; + udp_set_no_check6_tx(sock->sk, !cfg->use_udp6_tx_checksums); + udp_set_no_check6_rx(sock->sk, !cfg->use_udp6_rx_checksums); *sockp = sock; - return 0; error: @@ -94,7 +115,7 @@ error: *sockp = NULL; return err; } -EXPORT_SYMBOL_GPL(rpl_udp_sock_create); +EXPORT_SYMBOL_GPL(rpl_udp_sock_create6); void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock, struct udp_tunnel_sock_cfg *cfg) -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev