Message ID | alpine.DEB.2.02.1407162058200.2128@tomh.mtv.corp.google.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
From: Tom Herbert <therbert@google.com> Date: Wed, 16 Jul 2014 21:14:30 -0700 (PDT) > +static inline struct gue *gue_from_sock(struct sock *sk) > +{ > + return (struct gue *)sk->sk_user_data; > +} Casting a void pointer like this is never appropriate. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Jul 17, 2014 at 7:14 AM, Tom Herbert <therbert@google.com> wrote: > This patch provides a Generic UDP Encapsulation receive path > using the XFRM framework (udp_encap_rcv). > > This adds support for both direct encapsulation of IP protocols over > UDP. The bound destination port is used to map to an IP protocol. > This should support GRE over UDP encapsulation, see > http://tools.ietf.org/html/draft-yong-tsvwg-gre-in-udp-encap-02, > as will as the other IP tunneling protocols (IPIP, SIT). > > Signed-off-by: Tom Herbert <therbert@google.com> > --- > include/net/gue.h | 49 +++++++++++++++++ > net/ipv4/Kconfig | 10 ++++ > net/ipv4/Makefile | 1 + > net/ipv4/gue.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 219 insertions(+) > create mode 100644 include/net/gue.h > create mode 100644 net/ipv4/gue.c > > diff --git a/include/net/gue.h b/include/net/gue.h > new file mode 100644 > index 0000000..86b91bc > --- /dev/null > +++ b/include/net/gue.h > @@ -0,0 +1,49 @@ > +#ifndef __NET_GUE_H > +#define __NET_GUE_H > + > +#if defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) > + > +#include <net/udp_tunnel.h> > + > +struct gue_port_cfg { > + u8 protocol; > + struct udp_port_cfg udp_config; > +}; > + > +int gue_port_create(struct net *net, struct gue_port_cfg *cfg, > + struct socket **sockp); > +int gue_open_direct_port(unsigned short port, unsigned char proto, > + struct socket **sockp); > +void gue_close_port(struct socket *sock); > + > +/* Tunnel protocols can use GUE_TUNNEL_PARMS to set up per module static > + * variables that are used with the common GUE functions (open_gue_port, > + * close_gue_port). > + */ > +#define GUE_TUNNEL_PARMS(name, default_port) \ > +static int gue_udp_port = default_port; \ > +module_param(gue_udp_port, int, 0); \ > +MODULE_PARM_DESC(gue_udp_port, name "/UDP port"); \ > +static struct socket *gue_sock; > + > +#define open_gue_port(proto) \ > + (gue_udp_port ? \ > + gue_open_direct_port(gue_udp_port, proto, &gue_sock) : \ > + 0) > + > +#define close_gue_port() do { \ > + if (gue_sock) { \ > + gue_close_port(gue_sock); \ > + gue_sock = NULL; \ > + } \ > +} while (0) > + Hi Tom, So this is probably a similar feedback to the ioctls vs netlink comment from Dave... I guess we agree that module params should be avoided when possible, right? so this even goes further to a template in a header file used by the caller modules to define their own module param... should be (a non academic, I read your other comment) alternative here, I hope. Or. > +#else /* defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) */ > + > +#define GUE_TUNNEL_PARMS(name, default_port) > +#define open_gue_port(proto) (0) > +#define close_gue_port() > + > +#endif > + > +#endif -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, 16 Jul 2014 21:14:30 -0700 (PDT) Tom Herbert <therbert@google.com> wrote: > + > +#define open_gue_port(proto) \ > + (gue_udp_port ? \ > + gue_open_direct_port(gue_udp_port, proto, &gue_sock) : \ > + 0) > + > +#define close_gue_port() do { \ > + if (gue_sock) { \ > + gue_close_port(gue_sock); \ > + gue_sock = NULL; \ > + } \ > +} while (0) Macro;s are evil and unnecessary for this. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Jul 24, 2014 at 12:07 AM, Or Gerlitz <or.gerlitz@gmail.com> wrote: > > On Thu, Jul 17, 2014 at 7:14 AM, Tom Herbert <therbert@google.com> wrote: > > This patch provides a Generic UDP Encapsulation receive path > > using the XFRM framework (udp_encap_rcv). > > > > This adds support for both direct encapsulation of IP protocols over > > UDP. The bound destination port is used to map to an IP protocol. > > This should support GRE over UDP encapsulation, see > > http://tools.ietf.org/html/draft-yong-tsvwg-gre-in-udp-encap-02, > > as will as the other IP tunneling protocols (IPIP, SIT). > > > > Signed-off-by: Tom Herbert <therbert@google.com> > > --- > > include/net/gue.h | 49 +++++++++++++++++ > > net/ipv4/Kconfig | 10 ++++ > > net/ipv4/Makefile | 1 + > > net/ipv4/gue.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 219 insertions(+) > > create mode 100644 include/net/gue.h > > create mode 100644 net/ipv4/gue.c > > > > diff --git a/include/net/gue.h b/include/net/gue.h > > new file mode 100644 > > index 0000000..86b91bc > > --- /dev/null > > +++ b/include/net/gue.h > > @@ -0,0 +1,49 @@ > > +#ifndef __NET_GUE_H > > +#define __NET_GUE_H > > + > > +#if defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) > > + > > +#include <net/udp_tunnel.h> > > + > > +struct gue_port_cfg { > > + u8 protocol; > > + struct udp_port_cfg udp_config; > > +}; > > + > > +int gue_port_create(struct net *net, struct gue_port_cfg *cfg, > > + struct socket **sockp); > > +int gue_open_direct_port(unsigned short port, unsigned char proto, > > + struct socket **sockp); > > +void gue_close_port(struct socket *sock); > > + > > +/* Tunnel protocols can use GUE_TUNNEL_PARMS to set up per module static > > + * variables that are used with the common GUE functions (open_gue_port, > > + * close_gue_port). > > + */ > > +#define GUE_TUNNEL_PARMS(name, default_port) \ > > +static int gue_udp_port = default_port; \ > > +module_param(gue_udp_port, int, 0); \ > > +MODULE_PARM_DESC(gue_udp_port, name "/UDP port"); \ > > +static struct socket *gue_sock; > > + > > +#define open_gue_port(proto) \ > > + (gue_udp_port ? \ > > + gue_open_direct_port(gue_udp_port, proto, &gue_sock) : \ > > + 0) > > + > > +#define close_gue_port() do { \ > > + if (gue_sock) { \ > > + gue_close_port(gue_sock); \ > > + gue_sock = NULL; \ > > + } \ > > +} while (0) > > + > > Hi Tom, > > So this is probably a similar feedback to the ioctls vs netlink > comment from Dave... > > I guess we agree that module params should be avoided when possible, right? so > this even goes further to a template in a header file used by the > caller modules to define > their own module param... should be (a non academic, I read your other comment) > alternative here, I hope. > I'm not sure. The gue_port is a global property of the module and not link or device specific. My precedence is vxlan driver which has udp_port module parameter. > Or. > > > +#else /* defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) */ > > + > > +#define GUE_TUNNEL_PARMS(name, default_port) > > +#define open_gue_port(proto) (0) > > +#define close_gue_port() > > + > > +#endif > > + > > +#endif -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Jul 24, 2014 at 8:28 PM, Tom Herbert <therbert@google.com> wrote: > On Thu, Jul 24, 2014 at 12:07 AM, Or Gerlitz <or.gerlitz@gmail.com> wrote: >> >> On Thu, Jul 17, 2014 at 7:14 AM, Tom Herbert <therbert@google.com> wrote: >> > This patch provides a Generic UDP Encapsulation receive path >> > using the XFRM framework (udp_encap_rcv). >> > >> > This adds support for both direct encapsulation of IP protocols over >> > UDP. The bound destination port is used to map to an IP protocol. >> > This should support GRE over UDP encapsulation, see >> > http://tools.ietf.org/html/draft-yong-tsvwg-gre-in-udp-encap-02, >> > as will as the other IP tunneling protocols (IPIP, SIT). >> > +++ b/include/net/gue.h >> > @@ -0,0 +1,49 @@ >> > +#ifndef __NET_GUE_H >> > +#define __NET_GUE_H >> > + >> > +#if defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) >> > + >> > +#include <net/udp_tunnel.h> >> > + >> > +struct gue_port_cfg { >> > + u8 protocol; >> > + struct udp_port_cfg udp_config; >> > +}; >> > + >> > +int gue_port_create(struct net *net, struct gue_port_cfg *cfg, >> > + struct socket **sockp); >> > +int gue_open_direct_port(unsigned short port, unsigned char proto, >> > + struct socket **sockp); >> > +void gue_close_port(struct socket *sock); >> > + >> > +/* Tunnel protocols can use GUE_TUNNEL_PARMS to set up per module static >> > + * variables that are used with the common GUE functions (open_gue_port, >> > + * close_gue_port). >> > + */ >> > +#define GUE_TUNNEL_PARMS(name, default_port) \ >> > +static int gue_udp_port = default_port; \ >> > +module_param(gue_udp_port, int, 0); \ >> > +MODULE_PARM_DESC(gue_udp_port, name "/UDP port"); \ >> > +static struct socket *gue_sock; >> > + >> > +#define open_gue_port(proto) \ >> > + (gue_udp_port ? \ >> > + gue_open_direct_port(gue_udp_port, proto, &gue_sock) : \ >> > + 0) >> > + >> > +#define close_gue_port() do { \ >> > + if (gue_sock) { \ >> > + gue_close_port(gue_sock); \ >> > + gue_sock = NULL; \ >> > + } \ >> > +} while (0) >> > + >> So this is probably a similar feedback to the ioctls vs netlink >> comment from Dave... >> I guess we agree that module params should be avoided when possible, right? so >> this even goes further to a template in a header file used by the >> caller modules to define >> their own module param... should be (a non academic, I read your other comment) >> alternative here, I hope. > I'm not sure. The gue_port is a global property of the module and not > link or device specific. I wonder what makes the GUE port a global property eg. vs. VXLAN where people expressed thier will and AFAIK showed some valid use cases where multiple ports could be used? > My precedence is vxlan driver which has udp_port module parameter. You can now perfectly set the udp port for vxlan through netlink for both the bridge and OVS schemes. The fact that initially it was set through a module param doesn't justify to repeat this habbit again... -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/net/gue.h b/include/net/gue.h new file mode 100644 index 0000000..86b91bc --- /dev/null +++ b/include/net/gue.h @@ -0,0 +1,49 @@ +#ifndef __NET_GUE_H +#define __NET_GUE_H + +#if defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) + +#include <net/udp_tunnel.h> + +struct gue_port_cfg { + u8 protocol; + struct udp_port_cfg udp_config; +}; + +int gue_port_create(struct net *net, struct gue_port_cfg *cfg, + struct socket **sockp); +int gue_open_direct_port(unsigned short port, unsigned char proto, + struct socket **sockp); +void gue_close_port(struct socket *sock); + +/* Tunnel protocols can use GUE_TUNNEL_PARMS to set up per module static + * variables that are used with the common GUE functions (open_gue_port, + * close_gue_port). + */ +#define GUE_TUNNEL_PARMS(name, default_port) \ +static int gue_udp_port = default_port; \ +module_param(gue_udp_port, int, 0); \ +MODULE_PARM_DESC(gue_udp_port, name "/UDP port"); \ +static struct socket *gue_sock; + +#define open_gue_port(proto) \ + (gue_udp_port ? \ + gue_open_direct_port(gue_udp_port, proto, &gue_sock) : \ + 0) + +#define close_gue_port() do { \ + if (gue_sock) { \ + gue_close_port(gue_sock); \ + gue_sock = NULL; \ + } \ +} while (0) + +#else /* defined(CONFIG_NET_GUE) || defined(CONFIG_NET_GUE_MODULE) */ + +#define GUE_TUNNEL_PARMS(name, default_port) +#define open_gue_port(proto) (0) +#define close_gue_port() + +#endif + +#endif diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index dbc10d8..0551acb 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -311,6 +311,16 @@ config NET_UDP_TUNNEL tristate default n +config NET_GUE + tristate "IP: Generic UDP Encapsulation" + select XFRM + select NET_UDP_TUNNEL + ---help--- + Generic UDP Encapsulation is a method to encapsulate IP + tunnels (IPIP, GRE, SIT) over UDP. By encapsulating in UDP + network mechanisms and optimizations for UDP (such as ECMP + and RSS) can be leveraged to provide better service. + config INET_AH tristate "IP: AH transformation" select XFRM_ALGO diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 8ee1cd4..2044a14 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o obj-$(CONFIG_IP_MROUTE) += ipmr.o obj-$(CONFIG_NET_IPIP) += ipip.o gre-y := gre_demux.o +obj-$(CONFIG_NET_GUE) += gue.o obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o obj-$(CONFIG_NET_IPGRE) += ip_gre.o obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o diff --git a/net/ipv4/gue.c b/net/ipv4/gue.c new file mode 100644 index 0000000..17265bc --- /dev/null +++ b/net/ipv4/gue.c @@ -0,0 +1,159 @@ +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/socket.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <linux/udp.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <net/ip.h> +#include <net/udp.h> +#include <net/gue.h> +#include <net/xfrm.h> + +struct gue { + struct sock *sock; + u8 protocol; + void (*old_sk_destruct)(struct sock *sk); +}; + +static inline struct gue *gue_from_sock(struct sock *sk) +{ + return (struct gue *)sk->sk_user_data; +} + +static int gue_udp_encap_recv_deliver(struct sk_buff *skb, + u8 protocol, size_t len) +{ + struct iphdr *iph = ip_hdr(skb); + + /* Remove 'len' bytes from the packet (UDP header and + * GUE header if present), modify the protocol to the one + * we found, and then call rcv_encap. + */ + iph->tot_len = htons(ntohs(iph->tot_len) - len); + __skb_pull(skb, len); + skb_reset_transport_header(skb); + + return -protocol; +} + +int gue_udp_direct_recv(struct sock *sk, struct sk_buff *skb) +{ + struct gue *gue = gue_from_sock(sk); + + if (!gue) + return 1; + + return gue_udp_encap_recv_deliver(skb, gue->protocol, + sizeof(struct udphdr)); +} + +void gue_sock_destruct(struct sock *sk) +{ + struct gue *gue = gue_from_sock(sk); + + if (!gue) + return; + + /* Remove hooks into tunnel socket */ + sk->sk_destruct = gue->old_sk_destruct; + sk->sk_user_data = NULL; + gue->sock = NULL; + + if (sk->sk_destruct) + sk->sk_destruct(sk); + + kfree(gue); +} + +int +gue_port_create(struct net *net, struct gue_port_cfg *cfg, + struct socket **sockp) +{ + struct gue *gue = NULL; + int err; + struct socket *sock = NULL; + struct sock *sk; + + /* Open UDP socket */ + err = udp_sock_create(net, &cfg->udp_config, &sock); + if (err < 0) + goto error; + + sk = sock->sk; + + /* Allocate GUE port structure */ + gue = kzalloc(sizeof(*gue), GFP_KERNEL); + if (!gue) { + err = -ENOMEM; + goto error; + } + + /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ + gue->protocol = cfg->protocol; + udp_sk(sk)->encap_rcv = gue_udp_direct_recv; + + udp_sk(sk)->encap_type = 1; + udp_encap_enable(); + + sk->sk_user_data = gue; + gue->sock = sk; + + sk->sk_allocation = GFP_ATOMIC; + + /* Hook on the gue_port socket destructor so that we can cleanup + * if the tunnel socket goes away. + */ + sk->sk_destruct = &gue_sock_destruct; + gue->old_sk_destruct = sk->sk_destruct; + + if (sockp) + *sockp = sock; + + return 0; + +error: + kfree(gue); + if (sock) + sock_release(sock); + + return err; +} +EXPORT_SYMBOL_GPL(gue_port_create); + +int gue_open_direct_port(unsigned short port, u8 proto, + struct socket **sockp) +{ + struct gue_port_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.udp_config.family = AF_INET; + cfg.udp_config.local_ip.s_addr = INADDR_ANY; + cfg.udp_config.local_udp_port = htons(port); + cfg.protocol = proto; + + return gue_port_create(&init_net, &cfg, sockp); +} +EXPORT_SYMBOL_GPL(gue_open_direct_port); + +void gue_close_port(struct socket *sock) +{ + sock_release(sock); +} +EXPORT_SYMBOL_GPL(gue_close_port); + +static int __init gue_init(void) +{ + return 0; +} + +static void __exit gue_fini(void) +{ +} + +module_init(gue_init); +module_exit(gue_fini); +MODULE_AUTHOR("Tom Herbert <therbert@google.com>"); +MODULE_LICENSE("GPL");
This patch provides a Generic UDP Encapsulation receive path using the XFRM framework (udp_encap_rcv). This adds support for both direct encapsulation of IP protocols over UDP. The bound destination port is used to map to an IP protocol. This should support GRE over UDP encapsulation, see http://tools.ietf.org/html/draft-yong-tsvwg-gre-in-udp-encap-02, as will as the other IP tunneling protocols (IPIP, SIT). Signed-off-by: Tom Herbert <therbert@google.com> --- include/net/gue.h | 49 +++++++++++++++++ net/ipv4/Kconfig | 10 ++++ net/ipv4/Makefile | 1 + net/ipv4/gue.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 include/net/gue.h create mode 100644 net/ipv4/gue.c