[PATCH net v2] vxlan: don't allow overwrite of config src addr
When using IPv6 transport and a default dst, a pointer to the configured source address is passed into the route lookup. If no source address is configured, then the value is overwritten. IPv6 route lookup ignores egress ifindex match if the source address is set, so if egress ifindex match is desired, the source address must be passed as any. The overwrite breaks this for subsequent lookups. Avoid this by copying the configured address to an existing stack variable and pass a pointer to that instead. Fixes: 272d96a5ab10 ("net: vxlan: lwt: Use source ip address during route lookup.") Signed-off-by: Brian Russell Acked-by: Jiri Benc --- drivers/net/vxlan.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 556953f..2e05129 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2035,7 +2035,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, const struct iphdr *old_iph = ip_hdr(skb); union vxlan_addr *dst; union vxlan_addr remote_ip, local_ip; - union vxlan_addr *src; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; __be16 src_port = 0, dst_port; @@ -2062,7 +2061,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = (rdst->remote_vni) ? : default_vni; - src = &vxlan->cfg.saddr; + local_ip = vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; md->gbp = skb->mark; ttl = vxlan->cfg.ttl; @@ -2095,7 +2094,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst = &remote_ip; dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = tunnel_id_to_key32(info->key.tun_id); - src = &local_ip; dst_cache = &info->dst_cache; if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2115,7 +2113,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, rt = vxlan_get_route(vxlan, dev, sock4, skb, rdst ? rdst->remote_ifindex : 0, tos, dst->sin.sin_addr.s_addr, -&src->sin.sin_addr.s_addr, +&local_ip.sin.sin_addr.s_addr, dst_port, src_port, dst_cache, info); if (IS_ERR(rt)) { @@ -2142,7 +2140,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (err < 0) goto tx_error; - udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, src->sin.sin_addr.s_addr, + udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, local_ip.sin.sin_addr.s_addr, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, xnet, !udp_sum); #if IS_ENABLED(CONFIG_IPV6) @@ -2152,7 +2150,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ndst = vxlan6_get_route(vxlan, dev, sock6, skb, rdst ? rdst->remote_ifindex : 0, tos, label, &dst->sin6.sin6_addr, - &src->sin6.sin6_addr, + &local_ip.sin6.sin6_addr, dst_port, src_port, dst_cache, info); if (IS_ERR(ndst)) { @@ -2180,7 +2178,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev, -&src->sin6.sin6_addr, +&local_ip.sin6.sin6_addr, &dst->sin6.sin6_addr, tos, ttl, label, src_port, dst_port, !udp_sum); #endif -- 2.1.4
[PATCH net] vxlan: don't allow overwrite of config src addr
When using IPv6 transport and a default dst, a pointer to the configured source address is passed into the route lookup. If no source address is configured, then the value is overwritten. IPv6 route lookup ignores egress ifindex match if the source adress is set, so if egress ifindex match is desired, the source address must be passed as any. The overwrite breaks this for subsequent lookups. Avoid this by copying the configured address to an existing stack variable and pass a pointer to that instead. Signed-off-by: Brian Russell --- drivers/net/vxlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 30b04cf..3cca908 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2019,7 +2019,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = rdst->remote_vni; - src = &vxlan->cfg.saddr; + local_ip = vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; md->gbp = skb->mark; ttl = vxlan->cfg.ttl; @@ -2052,7 +2052,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst = &remote_ip; dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = tunnel_id_to_key32(info->key.tun_id); - src = &local_ip; dst_cache = &info->dst_cache; if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2061,6 +2060,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, label = info->key.label; udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); } + src = &local_ip; src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, vxlan->cfg.port_max, true); -- 2.1.4
[PATCH net] Don't allow overwrite of config src addr
When using IPv6 transport and a default dst, a pointer to the configured source address is passed into the route lookup. If no source address is configured, then the value is overwritten. IPv6 route lookup ignores egress ifindex match if the source adress is set, so if egress ifindex match is desired, the source address must be passed as any. The overwrite breaks this for subsequent lookups. Avoid this by copying the configured address to an existing stack variable and pass a pointer to that instead. Signed-off-by: Brian Russell --- drivers/net/vxlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 30b04cf..3cca908 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2019,7 +2019,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = rdst->remote_vni; - src = &vxlan->cfg.saddr; + local_ip = vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; md->gbp = skb->mark; ttl = vxlan->cfg.ttl; @@ -2052,7 +2052,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst = &remote_ip; dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = tunnel_id_to_key32(info->key.tun_id); - src = &local_ip; dst_cache = &info->dst_cache; if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2061,6 +2060,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, label = info->key.label; udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); } + src = &local_ip; src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, vxlan->cfg.port_max, true); -- 2.1.4
Re: [PATCH net-next v3 2/3] nsh: logging module
On 01/03/16 18:25, Joe Perches wrote: > On Tue, 2016-03-01 at 11:11 +0000, Brian Russell wrote: >> Module can register for Type 1 or specified classes of Type 2 metadata >> and will then log incoming matching packets. > > This logging mechanism seems like a way to fill/DoS logs. > > Maybe use pr_info_ratelimit? > Maybe use the trace_events mechanisms instead? > Thanks, will do. Brian >> Signed-off-by: Brian Russell >> --- >> net/ipv4/Kconfig | 8 >> net/ipv4/Makefile | 1 + >> net/ipv4/nsh_log.c | 135 >> + >> 3 files changed, 144 insertions(+) >> create mode 100644 net/ipv4/nsh_log.c >> >> diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig >> index df14c59..87b6dde 100644 >> --- a/net/ipv4/Kconfig >> +++ b/net/ipv4/Kconfig >> @@ -223,6 +223,14 @@ config NET_NSH >> >>To compile it as a module, choose M here. If unsure, say N. >> >> +config NET_NSH_LOG >> +tristate 'NSH Metadata Logger' >> +depends on NET_NSH >> +help >> + Log packets with incoming NSH metadata. >> + >> + To compile it as a module, choose M here. If unsure, say N. >> + >> config IP_MROUTE >> bool "IP: multicast routing" >> depends on IP_MULTICAST >> diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile >> index 14b7995..69377fb 100644 >> --- a/net/ipv4/Makefile >> +++ b/net/ipv4/Makefile >> @@ -25,6 +25,7 @@ obj-$(CONFIG_NET_FOU) += fou.o >> obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o >> obj-$(CONFIG_NET_IPGRE) += ip_gre.o >> obj-$(CONFIG_NET_NSH) += nsh.o >> +obj-$(CONFIG_NET_NSH_LOG) += nsh_log.o >> obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o >> obj-$(CONFIG_NET_IPVTI) += ip_vti.o >> obj-$(CONFIG_SYN_COOKIES) += syncookies.o >> diff --git a/net/ipv4/nsh_log.c b/net/ipv4/nsh_log.c >> new file mode 100644 >> index 000..3d774ed >> --- /dev/null >> +++ b/net/ipv4/nsh_log.c >> @@ -0,0 +1,135 @@ >> +/* >> + * Network Service Header (NSH) logging module. >> + * >> + * Copyright (c) 2016 by Brocade Communications Systems, Inc. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> +#include >> +#include >> +#include >> + >> +static bool t1_enabled = false; >> +module_param(t1_enabled, bool, 0444); >> +MODULE_PARM_DESC(t1_enabled, "Type 1 Metadata log enabled"); >> + >> +#define MAX_T2_CLASSES 10 >> +static unsigned int t2_classes[MAX_T2_CLASSES]; >> +static int num_t2 = 0; >> +module_param_array(t2_classes, uint, &num_t2, 0444); >> +MODULE_PARM_DESC(t2_classes, "Type 2 Metadata classes log enabled"); >> + >> +static const char *nsh_next_proto(u8 next_proto) >> +{ >> +switch (next_proto) { >> +case NSH_NEXT_PROTO_IPv4: >> +return "IPv4"; >> +case NSH_NEXT_PROTO_IPv6: >> +return "IPv6"; >> +case NSH_NEXT_PROTO_ETH: >> +return "Eth"; >> +default: >> +return "Unknown"; >> +} >> +} >> + >> +/* Type 1 metadata has fixed length, 4 x 32-bit words */ >> +static int nsh_log_t1(struct sk_buff *skb, u32 service_path_id, >> + u8 service_index, u8 next_proto, >> + struct nsh_metadata *ctx_hdr, unsigned int num_ctx_hdrs) >> +{ >> +u32 *data; >> + >> +if ((ctx_hdr->class != NSH_MD_CLASS_TYPE_1) || >> +(ctx_hdr->type != NSH_MD_TYPE_TYPE_1) || >> +(ctx_hdr->len != NSH_MD_LEN_TYPE_1) || >> +(num_ctx_hdrs != 1)) >> +return -EINVAL; >> + >> +data = ctx_hdr->data; >> +pr_info("NSH T1 Rx(%s): SPI=%u SI=%u Next=%s" >> +" MD 0x%08x 0x%08x 0x%08x 0x%08x\n", skb->dev->name, >> +service_path_id, service_index, nsh_next_proto(next_proto), >> +data[0], data[1], data[2], data[3]); >> + >> +return 0; >> +} >> + >> +/* Type 2 metadata consists of a variable number of TLVs */ >> +#define T2_BUFSIZE 512 >> +static int nsh_log_t2(struct sk_buff *skb, u32 service_path_id, >> + u8 service_index, u8 next_proto, >> + struct nsh_metadata *ctx_h
Re: [PATCH net-next v3 0/3] NSH and VxLAN-GPE
On 01/03/16 18:12, Alexei Starovoitov wrote: > On Tue, Mar 01, 2016 at 11:11:46AM +0000, Brian Russell wrote: >> These patches add a new module to support encap/decap of Network >> Service Header (NSH) as defined in: >> >> https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Dietf-2Dsfc-2Dnsh-2D01&d=CwIBAg&c=IL_XqQWOjubgfqINi2jTzg&r=Doie302MT-sezztwQymkPQ3_4X5Q3a0mKbiZzzoNm-0&m=GXnpiqS7PmfkgZFQ49KQrVhoa7H-hyPyPstkZdCi7hQ&s=Ncdq5xpzX-AAUeSDXaoU_zxqfXSdoI_qvgFZVyUclV0&e= >> >> >> Both NSH Type 1 and Type 2 metadata are supported with a simple registration >> hook to allow listeners to register to see packets with Type 1 or a specific >> class of Type 2 metadata. NSH could be added to packets sent over a variety >> of link types, eg. VxLAN, GRE, ethernet. >> >> v2 - fix copyright notices and tidy up use of types >> >> v3 - fix various style issues in nsh module >> remove VxLAN-GPE changes >> add nsh logging module as example >> add nsh netfilter encap target as example > > two fake examples are trying to justify EXPORT_SYMBOL(nsh_register_listener) > ?! > what's the real meaning of this patch set? > As far as I can see in-tree users cannot do anything useful with it. > I don't see what you're getting at. I thought the "real meaning" was obvious? The NSH draft says: " Optional Variable Length Metadata ... TLV Class: describes the scope of the "Type" field. In some cases, the TLV Class will identify a specific vendor, in others, the TLV Class will identify specific standards body allocated types. A new IANA registry will be created for TLV Class type. Type: the specific type of information being carried, within the scope of a given TLV Class. Value allocation is the responsibility of the TLV Class owner." So it seems reasonable to have a hook to hang metadata interpretation on? Thanks and regards, Brian
[PATCH net-next v3 1/3] nsh: encapsulation module
Support encap/decap of Network Service Header (NSH) as defined in https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Includes support for Type 1 and Type 2 metadata and a simple registration for listeners to see decapsulated packets based on the Type/Class. Signed-off-by: Brian Russell --- include/net/nsh.h | 147 ++ include/uapi/linux/if_ether.h | 1 + net/ipv4/Kconfig | 10 ++ net/ipv4/Makefile | 1 + net/ipv4/nsh.c| 335 ++ 5 files changed, 494 insertions(+) create mode 100644 include/net/nsh.h create mode 100644 net/ipv4/nsh.c diff --git a/include/net/nsh.h b/include/net/nsh.h new file mode 100644 index 000..57b29b8 --- /dev/null +++ b/include/net/nsh.h @@ -0,0 +1,147 @@ +/* + * Network Service Header (NSH) inserted onto encapsulated packets + * or frames to realize service function paths. + * NSH also provides a mechanism for metadata exchange along the + * instantiated service path. + * + * https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 + * + * Copyright (c) 2016 by Brocade Communications Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __NET_NSH_H +#define __NET_NSH_H + +#include +#include + +/* + * NSH Base Header + Service Path Header + * + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *|Ver|O|C|R|R|R|R|R|R| Length |MD Type| Next Protocol | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *| Service Path ID | Service Index | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Ver - Version, set to 0 + * O - Indicates payload is OAM. + * C - Indicates critical metadata TLV is present (must be 0 for MD type 1). + * Length - total header length in 4-byte words. + * MD Type - Metadata type + * Type 1 - 4 mandatory 4 byte context headers. + * Type 2 - 0 or more var length context headers. + * Next Protocol - protocol type of original packet. + * Service Path ID (SPI) - identifies a service path. Participating nodes + * MUST use this identifier for Service Function + * Path selection. + * Service Index (SI) - provides location within the SFP. + */ +#define NSH_BF_VER0 0 +#define NSH_BF_VER_MASK 0xc0 +#define NSH_BF_OAM BIT(5) +#define NSH_BF_CRIT BIT(4) +#define NSH_N_SPI (1u << 24) +#define NSH_SPI_MASK((NSH_N_SPI-1) << 8) +#define NSH_N_SI(1u << 8) +#define NSH_SI_MASK (NSH_N_SI-1) + +#define NSH_MD_TYPE_1 1 +#define NSH_MD_TYPE_2 2 + +#define NSH_NEXT_PROTO_IPv4 1 +#define NSH_NEXT_PROTO_IPv6 2 +#define NSH_NEXT_PROTO_ETH 3 + +#define NSH_LEN_TYPE_1 6 +#define NSH_LEN_TYPE_2_MIN 2 + +struct nsh_base { + u8 base_flags; + u8 length; + u8 md_type; + u8 next_proto; +}; + +struct nsh_header { + struct nsh_base base; + __be32 sp_header; +}; + +/* + * When the Base Header specifies MD Type 1, four 4-byte Context Headers + * MUST be added immediately following the Service Path Header. Thus length + * in the base header is set to 6. + * Context Headers that carry no metadata MUST be set to zero. + */ +#define NSH_MD_TYPE_1_NUM_HDRS 4 + +struct nsh_md_type_1 { + __be32 ctx_hdr1; + __be32 ctx_hdr2; + __be32 ctx_hdr3; + __be32 ctx_hdr4; +}; + +/* + * When the Base Header specifies MD Type 2, zero or more variable + * length Context Headers follow the Service Path Header. + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TLV Class|C|Type |R|R|R| Len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Metadata| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * TLV Class - Scope of class (e.g. may be vendor or standards body). + * Type - Specific type of information within the scope of given class. + *C bit (MSB) indicates criticality. When set, receiver must process. + * Len - Length of variable metadata in 4-byte words. + */ +#define NSH_TYPE_CRIT BIT(7) + +struct nsh_md_type_2 { + __be16 tlv_class; + u8 tlv_type; + u8 length; +}; + +/* Context header for encap/decap. */ +#define NSH_MD_CLASS_TYPE_1 USHRT_MAX +#define NSH_MD_TYPE_TYPE_1 U8_MAX +#define NSH_MD_LEN_TYPE_1 4 + +struct nsh_metadata { + u16 class; + u8 crit; + u8 type; + u8 len; /* 4 byte words */ + void *data; +}; + +/* Parse NSH header and notify registered listeners about any metadata.*/ +int nsh_decap(struct sk_buff *skb, u32 *spi, u8 *si, u8 *np); + +/* Add NSH header. */ +int nsh_encap(s
[PATCH net-next v3 3/3] nsh: netfilter target
Add an NSH netfilter target, to add NSH encap'd metadata to outgoing packets. Signed-off-by: Brian Russell --- include/uapi/linux/netfilter/xt_NSH.h | 25 + net/netfilter/Kconfig | 9 net/netfilter/Makefile| 1 + net/netfilter/xt_NSH.c| 95 +++ 4 files changed, 130 insertions(+) create mode 100644 include/uapi/linux/netfilter/xt_NSH.h create mode 100644 net/netfilter/xt_NSH.c diff --git a/include/uapi/linux/netfilter/xt_NSH.h b/include/uapi/linux/netfilter/xt_NSH.h new file mode 100644 index 000..82b76f6 --- /dev/null +++ b/include/uapi/linux/netfilter/xt_NSH.h @@ -0,0 +1,25 @@ +/* Header file for NSH target extension for xtables. + * + * Copyright (c) 2016 by Brocade Communications Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _XT_NSH_H +#define _XT_NSH_H + +struct xt_nsh_info { + __u32 service_path_id; + __u8 service_index; + __u8 metadata_type; + __u16 t2_class; + __u8 t2_type; + __u8 t2_len; + __u32 value1; + __u32 value2; + __u32 value3; + __u32 value4; +}; + +#endif /* _XT_NSH_H */ diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 95e757c..6349d56 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -863,6 +863,15 @@ config NETFILTER_XT_TARGET_NOTRACK depends on NETFILTER_ADVANCED select NETFILTER_XT_TARGET_CT +config NETFILTER_XT_TARGET_NSH + tristate '"NSH" target support' + depends on NETFILTER_ADVANCED + help + This options adds a `NSH' target, which allows to add NSH metadata +to outgoing packets. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_TARGET_RATEEST tristate '"RATEEST" target support' depends on NETFILTER_ADVANCED diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 6913454..59ea6f6 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -120,6 +120,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NSH) += xt_NSH.o obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o obj-$(CONFIG_NETFILTER_XT_TARGET_REDIRECT) += xt_REDIRECT.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o diff --git a/net/netfilter/xt_NSH.c b/net/netfilter/xt_NSH.c new file mode 100644 index 000..b1c930c --- /dev/null +++ b/net/netfilter/xt_NSH.c @@ -0,0 +1,95 @@ +/* Network Service Header (NSH) target extension for xtables. + * + * Copyright (c) 2016 by Brocade Communications Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nsh_tg(struct sk_buff *skb, + const struct xt_action_param *par) +{ + const struct xt_nsh_info *info = par->targinfo; + struct nsh_metadata ctx_hdr; + u32 data[4]; + int err; + + skb->protocol = htons(ETH_P_NSH); + + if (info->metadata_type == NSH_MD_TYPE_1) { + ctx_hdr.class = NSH_MD_CLASS_TYPE_1; + ctx_hdr.type = NSH_MD_TYPE_TYPE_1; + ctx_hdr.len = NSH_MD_LEN_TYPE_1; + } else { + ctx_hdr.class = info->t2_class; + ctx_hdr.type = info->t2_type; + ctx_hdr.len = info->t2_len; + } + + data[0] = info->value1; + data[1] = info->value2; + data[2] = info->value3; + data[3] = info->value4; + + ctx_hdr.data = &data; + ctx_hdr.crit = 1; + + err = nsh_encap(skb, info->service_path_id, info->service_index, + NSH_NEXT_PROTO_IPv4, 1, &ctx_hdr); + if (err < 0) + return NF_DROP; + + return NF_ACCEPT; +} + +static int nsh_tg_check(const struct xt_tgchk_param *par) +{ + struct xt_nsh_info *info = par->targinfo; + + if (info->metadata_type != NSH_MD_TYPE_1 && + info->metadata_type != NSH_MD_TYPE_2) + return -EINVAL; + if (info->service_path_id >= NSH_N_SPI) + return -EINVAL; + if (info->metadata_type == NSH_MD_TYPE_2 && + (info->t2_len > 4 || info->t2_class == NSH_MD_CLASS_TYPE_1)) + return -EINVAL; + return 0; +} + +static struct xt_target nsh_tg_
[PATCH net-next v3 0/3] NSH and VxLAN-GPE
These patches add a new module to support encap/decap of Network Service Header (NSH) as defined in: https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Both NSH Type 1 and Type 2 metadata are supported with a simple registration hook to allow listeners to register to see packets with Type 1 or a specific class of Type 2 metadata. NSH could be added to packets sent over a variety of link types, eg. VxLAN, GRE, ethernet. v2 - fix copyright notices and tidy up use of types v3 - fix various style issues in nsh module remove VxLAN-GPE changes add nsh logging module as example add nsh netfilter encap target as example The previous version included mods to allow NSH over VxLAN-GPE but I've withdrawn this as VxLAN-GPE is currently being added in a much more complete patchset. My intention would be to add NSH support on top of that once it's applied. I've added the NSH logging module to illustrate the use of the simple mechanism to register for incoming decap'd NSH metadata. I've added the NSH netfilter target to illustrate metadata being NSH encap'd. Brian Russell (3): nsh: encapsulation module nsh: logging module nsh: netfilter target include/net/nsh.h | 147 +++ include/uapi/linux/if_ether.h | 1 + include/uapi/linux/netfilter/xt_NSH.h | 25 +++ net/ipv4/Kconfig | 18 ++ net/ipv4/Makefile | 2 + net/ipv4/nsh.c| 335 ++ net/ipv4/nsh_log.c| 135 ++ net/netfilter/Kconfig | 9 + net/netfilter/Makefile| 1 + net/netfilter/xt_NSH.c| 95 ++ 10 files changed, 768 insertions(+) create mode 100644 include/net/nsh.h create mode 100644 include/uapi/linux/netfilter/xt_NSH.h create mode 100644 net/ipv4/nsh.c create mode 100644 net/ipv4/nsh_log.c create mode 100644 net/netfilter/xt_NSH.c -- 2.1.4
[PATCH net-next v3 2/3] nsh: logging module
Module can register for Type 1 or specified classes of Type 2 metadata and will then log incoming matching packets. Signed-off-by: Brian Russell --- net/ipv4/Kconfig | 8 net/ipv4/Makefile | 1 + net/ipv4/nsh_log.c | 135 + 3 files changed, 144 insertions(+) create mode 100644 net/ipv4/nsh_log.c diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index df14c59..87b6dde 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -223,6 +223,14 @@ config NET_NSH To compile it as a module, choose M here. If unsure, say N. +config NET_NSH_LOG +tristate 'NSH Metadata Logger' + depends on NET_NSH + help + Log packets with incoming NSH metadata. + + To compile it as a module, choose M here. If unsure, say N. + config IP_MROUTE bool "IP: multicast routing" depends on IP_MULTICAST diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 14b7995..69377fb 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_NET_FOU) += fou.o obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o obj-$(CONFIG_NET_IPGRE) += ip_gre.o obj-$(CONFIG_NET_NSH) += nsh.o +obj-$(CONFIG_NET_NSH_LOG) += nsh_log.o obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o obj-$(CONFIG_NET_IPVTI) += ip_vti.o obj-$(CONFIG_SYN_COOKIES) += syncookies.o diff --git a/net/ipv4/nsh_log.c b/net/ipv4/nsh_log.c new file mode 100644 index 000..3d774ed --- /dev/null +++ b/net/ipv4/nsh_log.c @@ -0,0 +1,135 @@ +/* + * Network Service Header (NSH) logging module. + * + * Copyright (c) 2016 by Brocade Communications Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +static bool t1_enabled = false; +module_param(t1_enabled, bool, 0444); +MODULE_PARM_DESC(t1_enabled, "Type 1 Metadata log enabled"); + +#define MAX_T2_CLASSES 10 +static unsigned int t2_classes[MAX_T2_CLASSES]; +static int num_t2 = 0; +module_param_array(t2_classes, uint, &num_t2, 0444); +MODULE_PARM_DESC(t2_classes, "Type 2 Metadata classes log enabled"); + +static const char *nsh_next_proto(u8 next_proto) +{ + switch (next_proto) { + case NSH_NEXT_PROTO_IPv4: + return "IPv4"; + case NSH_NEXT_PROTO_IPv6: + return "IPv6"; + case NSH_NEXT_PROTO_ETH: + return "Eth"; + default: + return "Unknown"; + } +} + +/* Type 1 metadata has fixed length, 4 x 32-bit words */ +static int nsh_log_t1(struct sk_buff *skb, u32 service_path_id, + u8 service_index, u8 next_proto, + struct nsh_metadata *ctx_hdr, unsigned int num_ctx_hdrs) +{ + u32 *data; + + if ((ctx_hdr->class != NSH_MD_CLASS_TYPE_1) || + (ctx_hdr->type != NSH_MD_TYPE_TYPE_1) || + (ctx_hdr->len != NSH_MD_LEN_TYPE_1) || + (num_ctx_hdrs != 1)) + return -EINVAL; + + data = ctx_hdr->data; + pr_info("NSH T1 Rx(%s): SPI=%u SI=%u Next=%s" + " MD 0x%08x 0x%08x 0x%08x 0x%08x\n", skb->dev->name, + service_path_id, service_index, nsh_next_proto(next_proto), + data[0], data[1], data[2], data[3]); + + return 0; +} + +/* Type 2 metadata consists of a variable number of TLVs */ +#define T2_BUFSIZE 512 +static int nsh_log_t2(struct sk_buff *skb, u32 service_path_id, + u8 service_index, u8 next_proto, + struct nsh_metadata *ctx_hdrs, unsigned int num_ctx_hdrs) +{ + char t2_buf[T2_BUFSIZE]; + int wrlen; + u32 *data; + int i,j; + + wrlen = snprintf(t2_buf, T2_BUFSIZE, +"NSH T2 Class %u Rx(%s): SPI=%u SI=%u Next=%s MD", +ctx_hdrs[0].class, skb->dev->name, service_path_id, +service_index, nsh_next_proto(next_proto)); + + for (i = 0; i < num_ctx_hdrs; i++) { + wrlen += snprintf(t2_buf+wrlen, T2_BUFSIZE-wrlen, + " TLV%d Type=%u Len=%u", i+1, + ctx_hdrs[i].type, ctx_hdrs[i].len); + data = ctx_hdrs[i].data; + for (j = 0; j < ctx_hdrs[i].len; j++) + wrlen += snprintf(t2_buf+wrlen, T2_BUFSIZE-wrlen, + " 0x%08x", data[j]); + } + pr_info("%s\n", t2_buf); + return 0; +} + +static struct nsh_listener nsh_log_t1_entry = { + .class = NSH_MD_CLASS_TYPE_1, + .notify = nsh_log_t1, +}; + +static struct nsh_listener nsh_log_t2_entry[MAX_T2_CLASSES]; + +static int __init nsh_log_init(void) +{
Re: [PATCH net-next v2 1/2] nsh: encapsulation module
On 15/02/16 17:01, Jiri Benc wrote: > On Thu, 11 Feb 2016 19:57:05 +0000, Brian Russell wrote: >> --- /dev/null >> +++ b/net/ipv4/nsh.c >> @@ -0,0 +1,365 @@ >> +/* >> + * Network Service Header (NSH) inserted onto encapsulated packets >> + * or frames to realize service function paths. >> + * NSH also provides a mechanism for metadata exchange along the >> + * instantiated service path. >> + * >> + * >> https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Dietf-2Dsfc-2Dnsh-2D01&d=CwICAg&c=IL_XqQWOjubgfqINi2jTzg&r=Doie302MT-sezztwQymkPQ3_4X5Q3a0mKbiZzzoNm-0&m=_l0yn4-EnXWqISq7YNUBglAxKAsglgRhuBK6CMa3dI0&s=V0t-CrNcmmRojyUSSZZP22sZZZAR0ztofpOYoZh7--E&e= >> >> + * >> + * Copyright (c) 2016 by Brocade Communications Systems, Inc. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> +#include >> +#include >> + >> +static struct list_head nsh_listeners; >> +static DEFINE_MUTEX(nsh_listener_mutex); >> +static struct nsh_metadata *decap_ctx_hdrs; >> +static unsigned char limit_ctx_hdrs = 10; >> +module_param_named(nsh_hdrs, limit_ctx_hdrs, byte, 0444); >> +MODULE_PARM_DESC(nsh_hdrs, "Maximum NSH metadata headers per packet"); > > No module parameters, please. Especially not for something like > encapsulation where multiple users will want different settings. > Ok. >> + >> +int nsh_register_listener(struct nsh_listener *listener) >> +{ >> +if (listener->max_ctx_hdrs > limit_ctx_hdrs) >> +return -ENOMEM; >> + >> +mutex_lock(&nsh_listener_mutex); >> +list_add(&listener->list, &nsh_listeners); >> +mutex_unlock(&nsh_listener_mutex); >> +return 0; >> +} >> +EXPORT_SYMBOL(nsh_register_listener); >> + >> +int nsh_unregister_listener(struct nsh_listener *listener) >> +{ >> +mutex_lock(&nsh_listener_mutex); >> +list_del(&listener->list); >> +mutex_unlock(&nsh_listener_mutex); >> +return 0; >> +} >> +EXPORT_SYMBOL(nsh_unregister_listener); > > I'd like to see how this listener stuff is used. Please do not submit > patches adding API without actual users. It's hard (or, in this case, > I'd say even impossible) to properly review this without seeing how it > is used. > I've added a new module to the next patch iteration that uses it. >> + >> +static int >> +notify_listeners(struct sk_buff *skb, > > Please do not break lines between the return type and name of the function. > Ok. >> + u32 service_path_id, >> + u8 service_index, >> + u8 next_proto, >> + struct nsh_metadata *ctx_hdrs, >> + unsigned int num_ctx_hdrs) >> +{ >> +struct nsh_listener *listener; >> +int i, err = 0; >> + >> +mutex_lock(&nsh_listener_mutex); >> +list_for_each_entry(listener, &nsh_listeners, list) { >> +for (i = 0; i < num_ctx_hdrs; i++) >> +if (listener->class == ctx_hdrs[i].class) { >> +err = listener->notify(skb, >> + service_path_id, >> + service_index, >> + next_proto, >> + ctx_hdrs, >> + num_ctx_hdrs); >> +if (err < 0) { >> +mutex_unlock(&nsh_listener_mutex); >> +return err; >> +} >> +break; >> +} >> +} >> +mutex_unlock(&nsh_listener_mutex); >> +return 0; >> +} >> + >> +static int >> +type_1_decap(struct sk_buff *skb, >> + struct nsh_md_type_1 *md, >> + unsigned int max_ctx_hdrs, >> + struct nsh_metadata *ctx_hdrs, >> + unsigned int *num_ctx_hdrs) >> +{ >> +int i; >> +u32 *data = &md->ctx_hdr1; >> + >> +if (max_ctx_hdrs == 0) >> +return -ENOMEM; >> + >> +ctx_hdrs[0].class = NSH_MD_CLASS_TYPE_1; >> +ctx_hdrs[0].type = NSH_MD_TYPE_TYP
Re: [PATCH net-next v2 1/2] nsh: encapsulation module
On 17/02/16 03:31, Alexei Starovoitov wrote: > On Thu, Feb 11, 2016 at 07:57:05PM +0000, Brian Russell wrote: >> Support encap/decap of Network Service Header (NSH) as defined in >> https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Dietf-2Dsfc-2Dnsh-2D01&d=CwIBAg&c=IL_XqQWOjubgfqINi2jTzg&r=Doie302MT-sezztwQymkPQ3_4X5Q3a0mKbiZzzoNm-0&m=TRPN3Zh-t31lBDA9ENrL1q3xeXBbMVLbXQhuldfgGN4&s=2lOXPH9TaoFa0x2lbk74kXi0vaLni54K6Hwjlb_Zs5k&e= >> >> >> Includes support for Type 1 and Type 2 metadata and a simple registration >> for listeners to see decapsulated packets based on the Type/Class. >> >> Signed-off-by: Brian Russell > ... >> +int nsh_register_listener(struct nsh_listener *listener) >> +{ >> +if (listener->max_ctx_hdrs > limit_ctx_hdrs) >> +return -ENOMEM; >> + >> +mutex_lock(&nsh_listener_mutex); >> +list_add(&listener->list, &nsh_listeners); >> +mutex_unlock(&nsh_listener_mutex); >> +return 0; >> +} >> +EXPORT_SYMBOL(nsh_register_listener); >> +EXPORT_SYMBOL(nsh_unregister_listener); > > looks like this patch doesn't actually implement the protocol, > but rather provides a placeholder for out of tree modules? > It implements the protocol in terms of the NSH base and service path headers and it decaps the metadata if present. However, the actual interpretation of that metadata is left to registered listeners which might be out of tree modules. The NSH standard defines the mechanism to carry metadata but does not limit how it is used. Thanks, Brian
Re: [PATCH net-next v2 2/2] vxlan: support GPE/NSH
On 15/02/16 16:49, Jiri Benc wrote: > On Thu, 11 Feb 2016 19:57:06 +0000, Brian Russell wrote: >> +skip_l2: >> skb_reset_network_header(skb); >> + >> /* In flow-based mode, GBP is carried in dst_metadata */ >> -if (!(vs->flags & VXLAN_F_COLLECT_METADATA)) >> +if (!(vs->flags & VXLAN_F_COLLECT_METADATA) && >> +!(vs->flags & VXLAN_F_GPE)) >> skb->mark = md->gbp; > > This is completely wrong. You cannot return a packet with a garbage in > place of the Ethernet header from ARPHRD_ETHER interface. For proper > VXLAN-GPE support, the vxlan interface needs to be in L3 mode, e.g. > ARPHRD_NONE. > Yes, I see that, thanks for the clarification. (I was "getting away with" the broken code in my test as I was diverting packets bound for another interface onto the vxlan via a netfilter target.) > To support L3 mode, the vxlan driver needs *tons* of cleanups (or tons > of duplicate code). This is exactly what I've done and what I'm in > process of merging. The number of patches is too big to be submitted as > a single patchset, hence I'm submitting in parts. The first one has > been already merged (net-next commit 19f76f63507f). For the full code, > look at: > https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_jbenc_linux-2Dvxlan_commits_master&d=CwICAg&c=IL_XqQWOjubgfqINi2jTzg&r=Doie302MT-sezztwQymkPQ3_4X5Q3a0mKbiZzzoNm-0&m=dDreCW0fBOYAR9o10-A-Ifd5jVGfykbZGpkzbN11nMc&s=qdPcZavap7kJQOuN2Udz-h-CDNkP4GiV_CYrQwXD_Kg&e= > > > Comments are welcome. > This looks great so I'll drop my vxlan-gpe patch. I'd like to add the NSH capability on top of your patchset which I see is currently under review. Or did you have plans to roll out NSH soon also? Thanks, Brian > Jiri >
[PATCH net-next v2 0/2] NSH and VxLAN-GPE
These patches add a new module to support encap/decap of Network Service Header (NSH) as defined in: https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Both NSH Type 1 and Type 2 metadata are supported with a simple registration hook to allow listeners to register to see packets with Type 1 or a specific class of Type 2 metadata. NSH could be added to packets sent over a variety of link types, eg. VxLAN, GRE, ethernet. Also included is an extension to VxLAN to handle the Generic Protocol Extension (GPE) as defined in: https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 This allows multi-protocol encapsulation over the VxLAN so IPv4, IPv6, MPLS and NSH encapsulated packets can be sent and received in addition to ethernet frames. Non-ethernet frames are sent to the default destination, which requires that the remote option is specified when creating the VxLAN device. I've tested this by using a netfilter module to encap some app-specific metadata in NSH type 2 and send it over the VxLAN and a listener module to receive the corresponding decap'd metadata. I'm also submitting a corresponding patch for iproute2 to add the gpe option to the "ip link add type vxlan" command. v2 - fix copyright notices and tidy up use of types Brian Russell (2): nsh: encapsulation module vxlan: support GPE/NSH drivers/net/vxlan.c | 139 ++-- include/net/nsh.h | 161 +++ include/net/vxlan.h | 40 - include/uapi/linux/if_ether.h | 1 + include/uapi/linux/if_link.h | 1 + net/ipv4/Kconfig | 10 ++ net/ipv4/Makefile | 1 + net/ipv4/nsh.c| 365 ++ 8 files changed, 704 insertions(+), 14 deletions(-) create mode 100644 include/net/nsh.h create mode 100644 net/ipv4/nsh.c -- 2.1.4
[PATCH net-next v2 1/2] nsh: encapsulation module
Support encap/decap of Network Service Header (NSH) as defined in https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Includes support for Type 1 and Type 2 metadata and a simple registration for listeners to see decapsulated packets based on the Type/Class. Signed-off-by: Brian Russell --- include/net/nsh.h | 161 +++ include/uapi/linux/if_ether.h | 1 + net/ipv4/Kconfig | 10 ++ net/ipv4/Makefile | 1 + net/ipv4/nsh.c| 365 ++ 5 files changed, 538 insertions(+) create mode 100644 include/net/nsh.h create mode 100644 net/ipv4/nsh.c diff --git a/include/net/nsh.h b/include/net/nsh.h new file mode 100644 index 000..8abf5f5 --- /dev/null +++ b/include/net/nsh.h @@ -0,0 +1,161 @@ +/* + * Network Service Header (NSH) inserted onto encapsulated packets + * or frames to realize service function paths. + * NSH also provides a mechanism for metadata exchange along the + * instantiated service path. + * + * https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 + * + * Copyright (c) 2016 by Brocade Communications Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __NET_NSH_H +#define __NET_NSH_H + +#include +#include + +/* + * NSH Base Header + Service Path Header + * + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *|Ver|O|C|R|R|R|R|R|R| Length |MD Type| Next Protocol | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *| Service Path ID | Service Index | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Ver - Version, set to 0 + * O - Indicates payload is OAM. + * C - Indicates critical metadata TLV is present (must be 0 for MD type 1). + * Length - total header length in 4-byte words. + * MD Type - Metadata type + * Type 1 - 4 mandatory 4 byte context headers. + * Type 2 - 0 or more var length context headers. + * Next Protocol - protocol type of original packet. + * Service Path ID (SPI) - identifies a service path. Participating nodes + * MUST use this identifier for Service Function + * Path selection. + * Service Index (SI) - provides location within the SFP. + */ +#define NSH_BF_VER0 0 +#define NSH_BF_VER_MASK 0xc0 +#define NSH_BF_OAM BIT(5) +#define NSH_BF_CRIT BIT(4) +#define NSH_N_SPI (1u << 24) +#define NSH_SPI_MASK((NSH_N_SPI-1) << 8) +#define NSH_N_SI(1u << 8) +#define NSH_SI_MASK (NSH_N_SI-1) + +#define NSH_MD_TYPE_1 1 +#define NSH_MD_TYPE_2 2 + +#define NSH_NEXT_PROTO_IPv4 1 +#define NSH_NEXT_PROTO_IPv6 2 +#define NSH_NEXT_PROTO_ETH 3 + +#define NSH_LEN_TYPE_1 6 +#define NSH_LEN_TYPE_2_MIN 2 + +struct nsh_base { + u8 base_flags; + u8 length; + u8 md_type; + u8 next_proto; +}; + +struct nsh_header { + struct nsh_base base; + __be32 sp_header; +}; + +/* + * When the Base Header specifies MD Type 1, four 4-byte Context Headers + * MUST be added immediately following the Service Path Header. Thus length + * in the base header is set to 6. + * Context Headers that carry no metadata MUST be set to zero. + */ +#define NSH_MD_TYPE_1_NUM_HDRS 4 + +struct nsh_md_type_1 { + __be32 ctx_hdr1; + __be32 ctx_hdr2; + __be32 ctx_hdr3; + __be32 ctx_hdr4; +}; + +/* + * When the Base Header specifies MD Type 2, zero or more variable + * length Context Headers follow the Service Path Header. + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TLV Class|C|Type |R|R|R| Len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Metadata| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * TLV Class - Scope of class (e.g. may be vendor or standards body). + * Type - Specific type of information within the scope of given class. + *C bit (MSB) indicates criticality. When set, receiver must process. + * Len - Length of variable metadata in 4-byte words. + */ +#define NSH_TYPE_CRIT BIT(7) + +struct nsh_md_type_2 { + __be16 tlv_class; + u8 tlv_type; + u8 length; +}; + +/* + * Context header for encap/decap. + */ +#define NSH_MD_CLASS_TYPE_1 USHRT_MAX +#define NSH_MD_TYPE_TYPE_1 U8_MAX +#define NSH_MD_LEN_TYPE_1 4 + +struct nsh_metadata { + u16 class; + u8 crit; + u8 type; + u8 len; /* 4 byte words */ + void *data; +}; + +/* + * Parse NSH header and notify registered listeners about any metadata. + */ +int nsh_decap(struct sk_buff *skb, + u32 *spi, + u8 *si, +
[PATCH net-next v2 2/2] vxlan: support GPE/NSH
Support the Generic Protocol Extension to VxLAN which extends VxLAN to allow multi-protocol encapsulation. IPv4, IPv6, MPLS unicast and NSH encapsulated packets can be sent and received in addition to ethernet frames. As defined in: https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 Signed-off-by: Brian Russell --- drivers/net/vxlan.c | 139 +++ include/net/vxlan.h | 40 - include/uapi/linux/if_link.h | 1 + 3 files changed, 166 insertions(+), 14 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ebf57d9..e6a6bfb 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -50,6 +50,7 @@ #include #endif #include +#include #define VXLAN_VERSION "0.1" @@ -1168,14 +1169,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, if (!vxlan) goto drop; - skb_reset_mac_header(skb); skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); - skb->protocol = eth_type_trans(skb, vxlan->dev); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); - - /* Ignore packet loops (and multicast echo) */ - if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) - goto drop; /* Get data from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { @@ -1195,13 +1189,57 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, tun_dst = NULL; } + switch (md->gpe_np) { + case VXLAN_GPE_NP_IPv4: + skb->protocol = htons(ETH_P_IP); + goto skip_l2; +#if IS_ENABLED(CONFIG_IPV6) + case VXLAN_GPE_NP_IPv6: + skb->protocol = htons(ETH_P_IPV6); + goto skip_l2; +#endif +#if IS_ENABLED(CONFIG_MPLS) + case VXLAN_GPE_NP_MPLS: + skb->protocol = htons(ETH_P_MPLS_UC); + goto skip_l2; +#endif +#if IS_ENABLED(CONFIG_NET_NSH) + case VXLAN_GPE_NP_NSH: + { + u8 next_proto; + + if (nsh_decap(skb, NULL, NULL, &next_proto) < 0) + goto drop; + + if (next_proto != NSH_NEXT_PROTO_ETH) + goto skip_l2; + } + break; +#endif + case VXLAN_GPE_NP_ETH: + /* GPE with next proto eth is equivalent to vanilla vxlan. */ + default: + break; + } + + skb_reset_mac_header(skb); + skb->protocol = eth_type_trans(skb, vxlan->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + /* Ignore packet loops (and multicast echo) */ + if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) + goto drop; + if ((vxlan->flags & VXLAN_F_LEARN) && vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) goto drop; +skip_l2: skb_reset_network_header(skb); + /* In flow-based mode, GBP is carried in dst_metadata */ - if (!(vs->flags & VXLAN_F_COLLECT_METADATA)) + if (!(vs->flags & VXLAN_F_COLLECT_METADATA) && + !(vs->flags & VXLAN_F_GPE)) skb->mark = md->gbp; if (oip6) @@ -1252,6 +1290,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; + vs = rcu_dereference_sk_user_data(sk); + if (!vs) + goto drop; + /* Need Vxlan and inner Ethernet header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) goto error; @@ -1267,14 +1309,13 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) goto bad_flags; } - if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB))) + /* If GPE, protocol will be set once next proto examined. */ + if (iptunnel_pull_header(skb, VXLAN_HLEN, +vs->flags & VXLAN_F_GPE ? +htons(ETH_P_IP) : htons(ETH_P_TEB))) goto drop; vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1); - vs = rcu_dereference_sk_user_data(sk); - if (!vs) - goto drop; - if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); @@ -1318,6 +1359,16 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) flags &= ~VXLAN_GBP_USED_BITS; } + if (vs->flags & VXLAN_F_GPE) { + /* Next protocol is required
Re: [PATCH net-next 1/2] nsh: encapsulation module
On 11/02/16 16:39, David Miller wrote: > From: Brian Russell > Date: Thu, 11 Feb 2016 10:35:13 + > >> +++ b/include/net/nsh.h >> +struct nsh_metadata { >> +u_short class; >> +u_char crit; >> +u_char type; >> +u_int len; /* 4 byte words */ >> +void *data; > > Do not use these shorthands, spell out "unsigned short" etc. explicitly. > > But in these cases you should be using fixed sized types like "u16". > > Also, in a header file such as this one which is private to the kernel > you should be using the variants of these types without the leading > underscores. > Ok, will fix those up. Thanks, Brian
Re: [PATCH net-next 1/2] nsh: encapsulation module
On 11/02/16 16:17, Robert Shearman wrote: > On 11/02/16 11:35, Brian Russell wrote: > ... >> diff --git a/include/net/nsh.h b/include/net/nsh.h >> new file mode 100644 >> index 000..7a5fb95 >> --- /dev/null >> +++ b/include/net/nsh.h >> @@ -0,0 +1,158 @@ >> +/* >> + * Network Service Header (NSH) inserted onto encapsulated packets >> + * or frames to realize service function paths. >> + * NSH also provides a mechanism for metadata exchange along the >> + * instantiated service path. >> + * >> + * https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 >> + * >> + * Copyright (c) 2015 by Brocade Communications Systems, Inc. >> + * All rights reserved. >> + */ > > All rights reserved isn't really compatible with the GPL :-) > Oops. Will fix that up in next version. Thanks, Brian > ... >> diff --git a/net/ipv4/nsh.c b/net/ipv4/nsh.c >> new file mode 100644 >> index 000..70e5ef0 >> --- /dev/null >> +++ b/net/ipv4/nsh.c >> @@ -0,0 +1,362 @@ >> +/* >> + * Network Service Header (NSH) inserted onto encapsulated packets >> + * or frames to realize service function paths. >> + * NSH also provides a mechanism for metadata exchange along the >> + * instantiated service path. >> + * >> + * https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 >> + * >> + * Copyright (c) 2015 by Brocade Communications Systems, Inc. >> + * All rights reserved. >> + */ > > Ditto. > > Thanks, > Rob >
[PATCH iproute2 net-next] iplink: vxlan: gpe support
Add VXLAN GPE support to ip link Signed-off-by: Brian Russell --- include/linux/if_link.h | 1 + ip/iplink_vxlan.c | 21 ++--- man/man8/ip-link.8.in | 12 +++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 0331c72..759ea6b 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -454,6 +454,7 @@ enum { IFLA_VXLAN_GBP, IFLA_VXLAN_REMCSUM_NOPARTIAL, IFLA_VXLAN_COLLECT_METADATA, + IFLA_VXLAN_GPE, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index ede8482..df749fa 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -31,7 +31,7 @@ static void print_explain(FILE *f) fprintf(f, " [ ageing SECONDS ] [ maxaddress NUMBER ]\n"); fprintf(f, " [ [no]udpcsum ] [ [no]udp6zerocsumtx ] [ [no]udp6zerocsumrx ]\n"); fprintf(f, " [ [no]remcsumtx ] [ [no]remcsumrx ]\n"); - fprintf(f, " [ [no]external ] [ gbp ]\n"); + fprintf(f, " [ [no]external ] [ gbp | gpe ]\n"); fprintf(f, "\n"); fprintf(f, "Where: VNI := 0-16777215\n"); fprintf(f, " ADDR := { IP_ADDRESS | any }\n"); @@ -74,6 +74,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, __u8 remcsumrx = 0; __u8 metadata = 0; __u8 gbp = 0; + __u8 gpe = 0; int dst_port_set = 0; struct ifla_vxlan_port_range range = { 0, 0 }; @@ -217,6 +218,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, metadata = 0; } else if (!matches(*argv, "gbp")) { gbp = 1; + } else if (!matches(*argv, "gpe")) { + gpe = 1; } else if (matches(*argv, "help") == 0) { explain(); return -1; @@ -249,8 +252,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, fprintf(stderr, "vxlan: destination port not specified\n" "Will use Linux kernel default (non-standard value)\n"); fprintf(stderr, - "Use 'dstport 4789' to get the IANA assigned value\n" - "Use 'dstport 0' to get default and quiet this message\n"); + "Use 'dstport %s' to get the IANA assigned value\n" + "Use 'dstport 0' to get default and quiet this message\n", + gpe ? "4790" : "4789"); } addattr32(n, 1024, IFLA_VXLAN_ID, vni); @@ -296,9 +300,17 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, if (dstport) addattr16(n, 1024, IFLA_VXLAN_PORT, htons(dstport)); + if (gbp && gpe) { + fprintf(stderr, + "vxlan: both gbp and gpe cannot be specified\n"); + return -1; + } + if (gbp) addattr_l(n, 1024, IFLA_VXLAN_GBP, NULL, 0); + if (gpe) + addattr_l(n, 1024, IFLA_VXLAN_GPE, NULL, 0); return 0; } @@ -445,6 +457,9 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_VXLAN_GBP]) fputs("gbp ", f); + + if (tb[IFLA_VXLAN_GPE]) + fputs("gpe ", f); } static void vxlan_print_help(struct link_util *lu, int argc, char **argv, diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 4d32343..2b92e81 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -422,7 +422,7 @@ the following additional arguments are supported: ] [ .BI maxaddress " NUMBER " ] [ -.B gbp +.BR gbp " | " gpe ] .in +8 @@ -554,6 +554,16 @@ Example: .in -4 +.sp +.B gpe +- enables the Generic Protocol extension (VXLAN-GPE). This parameter cannot +be specified with the +.B gbp +parameter. Sending packets with encapsulations other than ethernet requires +that the +.B remote +parameter be specified. + .in -8 .TP -- 2.1.4
[PATCH net-next 2/2] vxlan: support GPE/NSH
Support the Generic Protocol Extension to VxLAN which extends VxLAN to allow multi-protocol encapsulation. IPv4, IPv6, MPLS unicast and NSH encapsulated packets can be sent and received in addition to ethernet frames. As defined in: https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 Signed-off-by: Brian Russell --- drivers/net/vxlan.c | 139 +++ include/net/vxlan.h | 40 - include/uapi/linux/if_link.h | 1 + 3 files changed, 166 insertions(+), 14 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65f5247..92a4cdc 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -50,6 +50,7 @@ #include #endif #include +#include #define VXLAN_VERSION "0.1" @@ -1168,14 +1169,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, if (!vxlan) goto drop; - skb_reset_mac_header(skb); skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); - skb->protocol = eth_type_trans(skb, vxlan->dev); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); - - /* Ignore packet loops (and multicast echo) */ - if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) - goto drop; /* Get data from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { @@ -1195,13 +1189,57 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, tun_dst = NULL; } + switch (md->gpe_np) { + case VXLAN_GPE_NP_IPv4: + skb->protocol = htons(ETH_P_IP); + goto skip_l2; +#if IS_ENABLED(CONFIG_IPV6) + case VXLAN_GPE_NP_IPv6: + skb->protocol = htons(ETH_P_IPV6); + goto skip_l2; +#endif +#if IS_ENABLED(CONFIG_MPLS) + case VXLAN_GPE_NP_MPLS: + skb->protocol = htons(ETH_P_MPLS_UC); + goto skip_l2; +#endif +#if IS_ENABLED(CONFIG_NET_NSH) + case VXLAN_GPE_NP_NSH: + { + u_char next_proto; + + if (nsh_decap(skb, NULL, NULL, &next_proto) < 0) + goto drop; + + if (next_proto != NSH_NEXT_PROTO_ETH) + goto skip_l2; + } + break; +#endif + case VXLAN_GPE_NP_ETH: + /* GPE with next proto eth is equivalent to vanilla vxlan. */ + default: + break; + } + + skb_reset_mac_header(skb); + skb->protocol = eth_type_trans(skb, vxlan->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + /* Ignore packet loops (and multicast echo) */ + if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) + goto drop; + if ((vxlan->flags & VXLAN_F_LEARN) && vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) goto drop; +skip_l2: skb_reset_network_header(skb); + /* In flow-based mode, GBP is carried in dst_metadata */ - if (!(vs->flags & VXLAN_F_COLLECT_METADATA)) + if (!(vs->flags & VXLAN_F_COLLECT_METADATA) && + !(vs->flags & VXLAN_F_GPE)) skb->mark = md->gbp; if (oip6) @@ -1252,6 +1290,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; + vs = rcu_dereference_sk_user_data(sk); + if (!vs) + goto drop; + /* Need Vxlan and inner Ethernet header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) goto error; @@ -1267,14 +1309,13 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) goto bad_flags; } - if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB))) + /* If GPE, protocol will be set once next proto examined. */ + if (iptunnel_pull_header(skb, VXLAN_HLEN, +vs->flags & VXLAN_F_GPE ? +htons(ETH_P_IP) : htons(ETH_P_TEB))) goto drop; vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1); - vs = rcu_dereference_sk_user_data(sk); - if (!vs) - goto drop; - if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { vxh = vxlan_remcsum(skb, vxh, sizeof(struct vxlanhdr), vni, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); @@ -1318,6 +1359,16 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) flags &= ~VXLAN_GBP_USED_BITS; } + if (vs->flags & VXLAN_F_GPE) { + /* Next protocol is required
[PATCH net-next 1/2] nsh: encapsulation module
Support encap/decap of Network Service Header (NSH) as defined in https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Includes support for Type 1 and Type 2 metadata and a simple registration for listeners to see decapsulated packets based on the Type/Class. Signed-off-by: Brian Russell --- include/net/nsh.h | 158 ++ include/uapi/linux/if_ether.h | 1 + net/ipv4/Kconfig | 10 ++ net/ipv4/Makefile | 1 + net/ipv4/nsh.c| 362 ++ 5 files changed, 532 insertions(+) create mode 100644 include/net/nsh.h create mode 100644 net/ipv4/nsh.c diff --git a/include/net/nsh.h b/include/net/nsh.h new file mode 100644 index 000..7a5fb95 --- /dev/null +++ b/include/net/nsh.h @@ -0,0 +1,158 @@ +/* + * Network Service Header (NSH) inserted onto encapsulated packets + * or frames to realize service function paths. + * NSH also provides a mechanism for metadata exchange along the + * instantiated service path. + * + * https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 + * + * Copyright (c) 2015 by Brocade Communications Systems, Inc. + * All rights reserved. + */ +#ifndef __NET_NSH_H +#define __NET_NSH_H + +#include +#include + +/* + * NSH Base Header + Service Path Header + * + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *|Ver|O|C|R|R|R|R|R|R| Length |MD Type| Next Protocol | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + *| Service Path ID | Service Index | + *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Ver - Version, set to 0 + * O - Indicates payload is OAM. + * C - Indicates critical metadata TLV is present (must be 0 for MD type 1). + * Length - total header length in 4-byte words. + * MD Type - Metadata type + * Type 1 - 4 mandatory 4 byte context headers. + * Type 2 - 0 or more var length context headers. + * Next Protocol - protocol type of original packet. + * Service Path ID (SPI) - identifies a service path. Participating nodes + * MUST use this identifier for Service Function + * Path selection. + * Service Index (SI) - provides location within the SFP. + */ +#define NSH_BF_VER0 0 +#define NSH_BF_VER_MASK 0xc0 +#define NSH_BF_OAM BIT(5) +#define NSH_BF_CRIT BIT(4) +#define NSH_N_SPI (1u << 24) +#define NSH_SPI_MASK((NSH_N_SPI-1) << 8) +#define NSH_N_SI(1u << 8) +#define NSH_SI_MASK (NSH_N_SI-1) + +#define NSH_MD_TYPE_1 1 +#define NSH_MD_TYPE_2 2 + +#define NSH_NEXT_PROTO_IPv4 1 +#define NSH_NEXT_PROTO_IPv6 2 +#define NSH_NEXT_PROTO_ETH 3 + +#define NSH_LEN_TYPE_1 6 +#define NSH_LEN_TYPE_2_MIN 2 + +struct nsh_base { + __u8 base_flags; + __u8 length; + __u8 md_type; + __u8 next_proto; +}; + +struct nsh_header { + struct nsh_base base; + __be32 sp_header; +}; + +/* + * When the Base Header specifies MD Type 1, four 4-byte Context Headers + * MUST be added immediately following the Service Path Header. Thus length + * in the base header is set to 6. + * Context Headers that carry no metadata MUST be set to zero. + */ +#define NSH_MD_TYPE_1_NUM_HDRS 4 + +struct nsh_md_type_1 { + __be32 ctx_hdr1; + __be32 ctx_hdr2; + __be32 ctx_hdr3; + __be32 ctx_hdr4; +}; + +/* + * When the Base Header specifies MD Type 2, zero or more variable + * length Context Headers follow the Service Path Header. + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TLV Class|C|Type |R|R|R| Len | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Metadata| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * TLV Class - Scope of class (e.g. may be vendor or standards body). + * Type - Specific type of information within the scope of given class. + *C bit (MSB) indicates criticality. When set, receiver must process. + * Len - Length of variable metadata in 4-byte words. + */ +#define NSH_TYPE_CRIT BIT(7) + +struct nsh_md_type_2 { + __be16 tlv_class; + __u8 tlv_type; + __u8 length; +}; + +/* + * Context header for encap/decap. + */ +#define NSH_MD_CLASS_TYPE_1 USHRT_MAX +#define NSH_MD_TYPE_TYPE_1 U8_MAX +#define NSH_MD_LEN_TYPE_1 4 + +struct nsh_metadata { + u_short class; + u_char crit; + u_char type; + u_int len; /* 4 byte words */ + void *data; +}; + +/* + * Parse NSH header and notify registered listeners about any metadata. + */ +int nsh_decap(struct sk_buff *skb, + u_int *spi, + u_char *si, + u_char *np); + +/* + * Add NSH header. + */ +int nsh_encap(struct sk_buff *skb, + u_int spi, +
[PATCH net-next 0/2] NSH and VxLAN-GPE
These patches add a new module to support encap/decap of Network Service Header (NSH) as defined in: https://tools.ietf.org/html/draft-ietf-sfc-nsh-01 Both NSH Type 1 and Type 2 metadata are supported with a simple registration hook to allow listeners to register to see packets with Type 1 or a specific class of Type 2 metadata. NSH could be added to packets sent over a variety of link types, eg. VxLAN, GRE, ethernet. Also included is an extension to VxLAN to handle the Generic Protocol Extension (GPE) as defined in: https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 This allows multi-protocol encapsulation over the VxLAN so IPv4, IPv6, MPLS and NSH encapsulated packets can be sent and received in addition to ethernet frames. Non-ethernet frames are sent to the default destination, which requires that the remote option is specified when creating the VxLAN device. I've tested this by using a netfilter module to encap some app-specific metadata in NSH type 2 and send it over the VxLAN and a listener module to receive the corresponding decap'd metadata. I'm also submitting a corresponding patch for iproute2 to add the gpe option to the "ip link add type vxlan" command. Brian Russell (2): nsh: encapsulation module vxlan: support GPE/NSH drivers/net/vxlan.c | 139 ++-- include/net/nsh.h | 158 ++ include/net/vxlan.h | 40 - include/uapi/linux/if_ether.h | 1 + include/uapi/linux/if_link.h | 1 + net/ipv4/Kconfig | 10 ++ net/ipv4/Makefile | 1 + net/ipv4/nsh.c| 362 ++ 8 files changed, 698 insertions(+), 14 deletions(-) create mode 100644 include/net/nsh.h create mode 100644 net/ipv4/nsh.c -- 2.1.4