Message ID | 1467937435-73122-1-git-send-email-pshelar@ovn.org |
---|---|
State | Superseded |
Headers | show |
On Thu, Jul 7, 2016 at 5:23 PM, Pravin B Shelar <pshelar@ovn.org> wrote: > diff --git a/datapath/linux/compat/include/linux/udp.h b/datapath/linux/compat/include/linux/udp.h > new file mode 100644 > index 0000000..31ae022 > --- /dev/null > +++ b/datapath/linux/compat/include/linux/udp.h > @@ -0,0 +1,33 @@ > +#ifndef __LINUX_UDP_WRAPPER_H > +#define __LINUX_UDP_WRAPPER_H 1 > + > +#include_next <linux/udp.h> > +#include <linux/ipv6.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; > +#else > + /* since netwroking stack is not checking for zero UDP checksum > + * check it in OVS module. */ > + #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM > +#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 I guess it probably makes more sense to #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM in udp_set_no_check6_rx() since it is receive side issue, though functionally it doesn't make a difference. > diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c > index d45125d..3776990 100644 > --- a/datapath/linux/compat/vxlan.c > +++ b/datapath/linux/compat/vxlan.c > @@ -850,6 +850,13 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, > oip6 = ipv6_hdr(skb); > saddr.sin6.sin6_addr = oip6->saddr; > saddr.sa.sa_family = AF_INET6; > +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM > + if (!udp_hdr(skb)->check && > + !(vs->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { > + udp6_csum_zero_error(skb); > + goto drop; > + } > +#endif > #endif Do we need a version of this for Geneve as well?
On Thu, Jul 7, 2016 at 7:13 PM, Jesse Gross <jesse@kernel.org> wrote: > On Thu, Jul 7, 2016 at 5:23 PM, Pravin B Shelar <pshelar@ovn.org> wrote: >> diff --git a/datapath/linux/compat/include/linux/udp.h b/datapath/linux/compat/include/linux/udp.h >> new file mode 100644 >> index 0000000..31ae022 >> --- /dev/null >> +++ b/datapath/linux/compat/include/linux/udp.h >> @@ -0,0 +1,33 @@ >> +#ifndef __LINUX_UDP_WRAPPER_H >> +#define __LINUX_UDP_WRAPPER_H 1 >> + >> +#include_next <linux/udp.h> >> +#include <linux/ipv6.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; >> +#else >> + /* since netwroking stack is not checking for zero UDP checksum >> + * check it in OVS module. */ >> + #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >> +#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 > > I guess it probably makes more sense to #define > OVS_CHECK_UDP_TUNNEL_ZERO_CSUM in udp_set_no_check6_rx() since it is > receive side issue, though functionally it doesn't make a difference. > >> diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c >> index d45125d..3776990 100644 >> --- a/datapath/linux/compat/vxlan.c >> +++ b/datapath/linux/compat/vxlan.c >> @@ -850,6 +850,13 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, >> oip6 = ipv6_hdr(skb); >> saddr.sin6.sin6_addr = oip6->saddr; >> saddr.sa.sa_family = AF_INET6; >> +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >> + if (!udp_hdr(skb)->check && >> + !(vs->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { >> + udp6_csum_zero_error(skb); >> + goto drop; >> + } >> +#endif >> #endif > > Do we need a version of this for Geneve as well? OK - I see that it actually came in later in the big resync patch.
On Thu, Jul 7, 2016 at 7:16 PM, Jesse Gross <jesse@kernel.org> wrote: > On Thu, Jul 7, 2016 at 7:13 PM, Jesse Gross <jesse@kernel.org> wrote: >> On Thu, Jul 7, 2016 at 5:23 PM, Pravin B Shelar <pshelar@ovn.org> wrote: >>> diff --git a/datapath/linux/compat/include/linux/udp.h b/datapath/linux/compat/include/linux/udp.h >>> new file mode 100644 >>> index 0000000..31ae022 >>> --- /dev/null >>> +++ b/datapath/linux/compat/include/linux/udp.h >>> @@ -0,0 +1,33 @@ >>> +#ifndef __LINUX_UDP_WRAPPER_H >>> +#define __LINUX_UDP_WRAPPER_H 1 >>> + >>> +#include_next <linux/udp.h> >>> +#include <linux/ipv6.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; >>> +#else >>> + /* since netwroking stack is not checking for zero UDP checksum >>> + * check it in OVS module. */ >>> + #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >>> +#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 >> >> I guess it probably makes more sense to #define >> OVS_CHECK_UDP_TUNNEL_ZERO_CSUM in udp_set_no_check6_rx() since it is >> receive side issue, though functionally it doesn't make a difference. >> >>> diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c >>> index d45125d..3776990 100644 >>> --- a/datapath/linux/compat/vxlan.c >>> +++ b/datapath/linux/compat/vxlan.c >>> @@ -850,6 +850,13 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, >>> oip6 = ipv6_hdr(skb); >>> saddr.sin6.sin6_addr = oip6->saddr; >>> saddr.sa.sa_family = AF_INET6; >>> +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >>> + if (!udp_hdr(skb)->check && >>> + !(vs->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { >>> + udp6_csum_zero_error(skb); >>> + goto drop; >>> + } >>> +#endif >>> #endif >> >> Do we need a version of this for Geneve as well? > > OK - I see that it actually came in later in the big resync patch. Yes, Geneve does not support ipv6 tunnels at this point.
On Thu, Jul 7, 2016 at 7:17 PM, pravin shelar <pshelar@ovn.org> wrote: > On Thu, Jul 7, 2016 at 7:16 PM, Jesse Gross <jesse@kernel.org> wrote: >> On Thu, Jul 7, 2016 at 7:13 PM, Jesse Gross <jesse@kernel.org> wrote: >>> On Thu, Jul 7, 2016 at 5:23 PM, Pravin B Shelar <pshelar@ovn.org> wrote: >>>> diff --git a/datapath/linux/compat/include/linux/udp.h b/datapath/linux/compat/include/linux/udp.h >>>> new file mode 100644 >>>> index 0000000..31ae022 >>>> --- /dev/null >>>> +++ b/datapath/linux/compat/include/linux/udp.h >>>> @@ -0,0 +1,33 @@ >>>> +#ifndef __LINUX_UDP_WRAPPER_H >>>> +#define __LINUX_UDP_WRAPPER_H 1 >>>> + >>>> +#include_next <linux/udp.h> >>>> +#include <linux/ipv6.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; >>>> +#else >>>> + /* since netwroking stack is not checking for zero UDP checksum >>>> + * check it in OVS module. */ >>>> + #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >>>> +#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 >>> >>> I guess it probably makes more sense to #define >>> OVS_CHECK_UDP_TUNNEL_ZERO_CSUM in udp_set_no_check6_rx() since it is >>> receive side issue, though functionally it doesn't make a difference. >>> >>>> diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c >>>> index d45125d..3776990 100644 >>>> --- a/datapath/linux/compat/vxlan.c >>>> +++ b/datapath/linux/compat/vxlan.c >>>> @@ -850,6 +850,13 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, >>>> oip6 = ipv6_hdr(skb); >>>> saddr.sin6.sin6_addr = oip6->saddr; >>>> saddr.sa.sa_family = AF_INET6; >>>> +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM >>>> + if (!udp_hdr(skb)->check && >>>> + !(vs->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { >>>> + udp6_csum_zero_error(skb); >>>> + goto drop; >>>> + } >>>> +#endif >>>> #endif >>> >>> Do we need a version of this for Geneve as well? >> >> OK - I see that it actually came in later in the big resync patch. > > Yes, Geneve does not support ipv6 tunnels at this point. In that case (with the minor adjustment noted above): Acked-by: Jesse Gross <jesse@kernel.org>
diff --git a/acinclude.m4 b/acinclude.m4 index 4bb65c7..003ba72 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -619,6 +619,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..31ae022 --- /dev/null +++ b/datapath/linux/compat/include/linux/udp.h @@ -0,0 +1,33 @@ +#ifndef __LINUX_UDP_WRAPPER_H +#define __LINUX_UDP_WRAPPER_H 1 + +#include_next <linux/udp.h> +#include <linux/ipv6.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; +#else + /* since netwroking stack is not checking for zero UDP checksum + * check it in OVS module. */ + #define OVS_CHECK_UDP_TUNNEL_ZERO_CSUM +#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 + +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM +#define udp6_csum_zero_error rpl_udp6_csum_zero_error + +void rpl_udp6_csum_zero_error(struct sk_buff *skb); +#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 605fe63..d953e09 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 -EPFNOSUPPORT; +} +#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.c b/datapath/linux/compat/udp.c index 487d317..f0362b6 100644 --- a/datapath/linux/compat/udp.c +++ b/datapath/linux/compat/udp.c @@ -42,3 +42,15 @@ void rpl_udp_set_csum(bool nocheck, struct sk_buff *skb, EXPORT_SYMBOL_GPL(rpl_udp_set_csum); #endif /* Linux version < 3.16 */ + +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM +void rpl_udp6_csum_zero_error(struct sk_buff *skb) +{ + /* RFC 2460 section 8.1 says that we SHOULD log + * this error. Well, it is reasonable. + */ + net_dbg_ratelimited("IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u\n", + &ipv6_hdr(skb)->saddr, ntohs(udp_hdr(skb)->source), + &ipv6_hdr(skb)->daddr, ntohs(udp_hdr(skb)->dest)); +} +#endif 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) diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index d45125d..3776990 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -850,6 +850,13 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, oip6 = ipv6_hdr(skb); saddr.sin6.sin6_addr = oip6->saddr; saddr.sa.sa_family = AF_INET6; +#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM + if (!udp_hdr(skb)->check && + !(vs->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { + udp6_csum_zero_error(skb); + goto drop; + } +#endif #endif }
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 <pshelar@ovn.org> --- acinclude.m4 | 2 + datapath/linux/Modules.mk | 1 + datapath/linux/compat/include/linux/udp.h | 33 +++++++ datapath/linux/compat/include/net/udp.h | 1 - datapath/linux/compat/include/net/udp_tunnel.h | 30 +++++- datapath/linux/compat/udp.c | 12 +++ datapath/linux/compat/udp_tunnel.c | 123 +++++++++++++++---------- datapath/linux/compat/vxlan.c | 7 ++ 8 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 datapath/linux/compat/include/linux/udp.h