From patchwork Sat May 19 00:49:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916679 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RnEB7OGb"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmft11pPz9s47 for ; Sat, 19 May 2018 10:50:30 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 09789C21; Sat, 19 May 2018 00:50:00 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7131BBC4 for ; Sat, 19 May 2018 00:49:56 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 0AA98674 for ; Sat, 19 May 2018 00:49:54 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id a22-v6so4494436pfn.6 for ; Fri, 18 May 2018 17:49:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iYOSj8PEEuNe50fP3PddKF9HVz/hjRJf8qZkd0VME+I=; b=RnEB7OGbv09T3m2LrdS2QPEd6Vxc5z0h1qIyk2CdyMuFu3YP2XlLu2pvRHdLtE5V8P Q3KKQqcgh0CT2/b0r27ub5JaknedTJDAUic+v+JgzaVgNNlxcs8BvA6e5fNCiyDAHoMU YeGpw1gJ+XfJWjtrUVNJz9FcgXYUoh6e55kHd/fTgsB6hwy9aKoJ8hNXhx1X71Xw1Dzr sSZ7A2RzJGZXAR5mTI6VqQNdXcGVD3o7JqRV9KofgixXc1toh0jppWMSNL17S/xUOMx9 iLbAIrePN4/h4PT91EWd4xNB5HjK6xFarP1dFDT4MVe6EjBEVku3xu2+oxkoUspXkNXQ Tznw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iYOSj8PEEuNe50fP3PddKF9HVz/hjRJf8qZkd0VME+I=; b=RHkiR9kgrV+ZVqvzQ16UosFnxLT9Te21xn9g/Xrxzy7wHKotzWa7AHhbZLCgUmZXCp oi9hhZRqf8/E7cGkttFswSQFj6F6ENrQrO/b3NzbuHvX9W7y9sfv6I9jEeDKtXdUMddN vTCpuXvebcn7mBoTKZ2VLJZs1lH/tMBqajQeUyQpLj0TVnk+0ZG3fz7uVDMHF4RWYfYe 9PvipTmzsDYP++j8ikcxvN5BAh83o2QSjRHUCVRmTiX+e7q3DRbN/N9lf6rFtZQm/zUY p4xNC/JhAg9xaeg1x62zLgQLE0n3KsAs/Oo6O9ZDbNuuAtCK5bu8QKYkKih+YHhc5O6b REnA== X-Gm-Message-State: ALKqPwdgtwQRjy5rx6HnCv9B0q8jIU7Lwoy+YMem4oBUm0fjZIf4zIPr yyCu8lTeFcn/MIcSTWU1w3eQgw== X-Google-Smtp-Source: AB8JxZqAsyFMdNii74d98hG/jLa4c+zhuw4Xljw0SaPt9+BOajXvdBWze+pUtrsYR5jRKpNDSpXGdA== X-Received: by 2002:a62:f24a:: with SMTP id y10-v6mr11473113pfl.75.1526690993765; Fri, 18 May 2018 17:49:53 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:53 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:09 -0700 Message-Id: <1526690988-29912-2-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 01/40] compat: Remove unsupported kernel compat code X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Anything less than 3.10 isn't supported since a couple of releases ago so remove the dead code. Signed-off-by: Greg Rose --- datapath/linux/compat/include/linux/etherdevice.h | 30 ------ datapath/linux/compat/include/linux/if_vlan.h | 11 --- datapath/linux/compat/include/linux/kconfig.h | 8 -- datapath/linux/compat/include/linux/kernel.h | 38 -------- .../linux/compat/include/linux/netdev_features.h | 19 ---- datapath/linux/compat/include/linux/netdevice.h | 5 - datapath/linux/compat/include/linux/skbuff.h | 7 -- datapath/linux/compat/include/linux/workqueue.h | 4 - datapath/linux/compat/include/net/checksum.h | 6 -- datapath/linux/compat/include/net/dst.h | 28 +----- datapath/linux/compat/include/net/genetlink.h | 11 --- datapath/linux/compat/include/net/ip6_route.h | 23 ----- datapath/linux/compat/include/net/ip_tunnels.h | 4 - datapath/linux/compat/include/net/ipv6.h | 15 --- .../include/net/netfilter/nf_conntrack_zones.h | 2 - datapath/linux/compat/include/net/netlink.h | 15 --- datapath/linux/compat/include/net/route.h | 105 --------------------- datapath/linux/compat/ip_gre.c | 11 --- datapath/linux/compat/ip_tunnel.c | 8 +- datapath/linux/compat/lisp.c | 2 - datapath/linux/compat/stt.c | 6 -- datapath/linux/compat/udp_tunnel.c | 2 - datapath/linux/compat/utils.c | 22 ----- 23 files changed, 2 insertions(+), 380 deletions(-) diff --git a/datapath/linux/compat/include/linux/etherdevice.h b/datapath/linux/compat/include/linux/etherdevice.h index 850b779..4b27074 100644 --- a/datapath/linux/compat/include/linux/etherdevice.h +++ b/datapath/linux/compat/include/linux/etherdevice.h @@ -4,36 +4,6 @@ #include #include_next -#ifndef HAVE_ETH_HW_ADDR_RANDOM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - dev_hw_addr_random(dev, dev->dev_addr); -} -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) -#define eth_mac_addr rpl_eth_mac_addr -static inline int eth_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; -#ifdef NET_ADDR_RANDOM - dev->addr_assign_type &= ~NET_ADDR_RANDOM; -#endif - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} -#endif - #ifndef HAVE_ETHER_ADDR_COPY static inline void ether_addr_copy(u8 *dst, const u8 *src) { diff --git a/datapath/linux/compat/include/linux/if_vlan.h b/datapath/linux/compat/include/linux/if_vlan.h index fc95b04..2cf18e5 100644 --- a/datapath/linux/compat/include/linux/if_vlan.h +++ b/datapath/linux/compat/include/linux/if_vlan.h @@ -90,17 +90,6 @@ static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -static inline struct sk_buff *rpl___vlan_hwaccel_put_tag(struct sk_buff *skb, - __be16 vlan_proto, - u16 vlan_tci) -{ - return __vlan_hwaccel_put_tag(skb, vlan_tci); -} - -#define __vlan_hwaccel_put_tag rpl___vlan_hwaccel_put_tag -#endif - #ifndef HAVE_ETH_TYPE_VLAN /** * eth_type_vlan - check for valid vlan ether type. diff --git a/datapath/linux/compat/include/linux/kconfig.h b/datapath/linux/compat/include/linux/kconfig.h index 5717a26..d3fa57a 100644 --- a/datapath/linux/compat/include/linux/kconfig.h +++ b/datapath/linux/compat/include/linux/kconfig.h @@ -3,14 +3,6 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -#define CONFIG_NET_IPGRE_DEMUX 1 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) -#include_next -#endif - #ifndef IS_ENABLED /* diff --git a/datapath/linux/compat/include/linux/kernel.h b/datapath/linux/compat/include/linux/kernel.h index 5c4269b..2e81abc 100644 --- a/datapath/linux/compat/include/linux/kernel.h +++ b/datapath/linux/compat/include/linux/kernel.h @@ -8,44 +8,6 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -#define pr_warn pr_warning -#endif - -/* - * Print a one-time message (analogous to WARN_ONCE() et al): - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) -#undef printk_once -#define printk_once(fmt, ...) \ -({ \ - static bool __print_once; \ - \ - if (!__print_once) { \ - __print_once = true; \ - printk(fmt, ##__VA_ARGS__); \ - } \ -}) - -#define pr_emerg_once(fmt, ...) \ - printk_once(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) -#define pr_alert_once(fmt, ...) \ - printk_once(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) -#define pr_crit_once(fmt, ...) \ - printk_once(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) -#define pr_err_once(fmt, ...) \ - printk_once(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) -#define pr_warn_once(fmt, ...) \ - printk_once(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) -#define pr_notice_once(fmt, ...) \ - printk_once(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) -#define pr_info_once(fmt, ...) \ - printk_once(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) -#define pr_cont_once(fmt, ...) \ - printk_once(KERN_CONT pr_fmt(fmt), ##__VA_ARGS__) - -#endif - #ifndef USHRT_MAX #define USHRT_MAX ((u16)(~0U)) #define SHRT_MAX ((s16)(USHRT_MAX>>1)) diff --git a/datapath/linux/compat/include/linux/netdev_features.h b/datapath/linux/compat/include/linux/netdev_features.h index a39bd4a..411f294 100644 --- a/datapath/linux/compat/include/linux/netdev_features.h +++ b/datapath/linux/compat/include/linux/netdev_features.h @@ -1,18 +1,7 @@ #ifndef __LINUX_NETDEV_FEATURES_WRAPPER_H #define __LINUX_NETDEV_FEATURES_WRAPPER_H -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) #include_next -#endif - -#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) -/* On RHEL 6, netdev features are defined in netdevice.h header. */ -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_TX -#endif #ifndef NETIF_F_GSO_GRE #define NETIF_F_GSO_GRE 0 @@ -81,14 +70,6 @@ NETIF_F_GSO_MPLS) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) -#define SKB_GSO_GRE 0 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -#define SKB_GSO_UDP_TUNNEL 0 -#endif - #ifndef HAVE_NETIF_F_GSO_GRE_CSUM #define SKB_GSO_GRE_CSUM 0 #endif diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 9d3b249..29ef6c7 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -37,11 +37,6 @@ struct net; alloc_netdev_mq(sizeof_priv, name, setup, 1) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#define unregister_netdevice_queue(dev, head) unregister_netdevice(dev) -#define unregister_netdevice_many(head) -#endif - #ifndef HAVE_DEV_DISABLE_LRO extern void dev_disable_lro(struct net_device *dev); #endif diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 2910f3f..149ef28 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -212,13 +212,6 @@ static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask) #define skb_get_hash skb_get_rxhash #endif /* HAVE_SKB_GET_HASH */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) -static inline void skb_tx_error(struct sk_buff *skb) -{ - return; -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) */ - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #define skb_zerocopy_headlen rpl_skb_zerocopy_headlen unsigned int rpl_skb_zerocopy_headlen(const struct sk_buff *from); diff --git a/datapath/linux/compat/include/linux/workqueue.h b/datapath/linux/compat/include/linux/workqueue.h index 461fefd..ed573c2 100644 --- a/datapath/linux/compat/include/linux/workqueue.h +++ b/datapath/linux/compat/include/linux/workqueue.h @@ -3,8 +3,4 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_work(wq, dw) schedule_work(dw); -#endif - #endif diff --git a/datapath/linux/compat/include/net/checksum.h b/datapath/linux/compat/include/net/checksum.h index 398df93..d1f1125 100644 --- a/datapath/linux/compat/include/net/checksum.h +++ b/datapath/linux/compat/include/net/checksum.h @@ -36,10 +36,4 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to) #define CSUM_MANGLED_0 ((__force __sum16)0xffff) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -#define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16 -void rpl_inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, - const __be32 *from, const __be32 *to, - int pseudohdr); -#endif #endif /* checksum.h */ diff --git a/datapath/linux/compat/include/net/dst.h b/datapath/linux/compat/include/net/dst.h index 5ec3d30..af78a6c 100644 --- a/datapath/linux/compat/include/net/dst.h +++ b/datapath/linux/compat/include/net/dst.h @@ -4,13 +4,6 @@ #include #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(3,0,20) - -#define dst_get_neighbour_noref dst_get_neighbour - -#endif - #ifndef HAVE_SKB_DST_ACCESSOR_FUNCS static inline void skb_dst_drop(struct sk_buff *skb) @@ -30,19 +23,7 @@ static inline void skb_dst_drop(struct sk_buff *skb) #define DST_NOCOUNT 0 #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) -{ - nskb->_skb_dst = refdst; - dst_clone(skb_dst(nskb)); -} - -static inline void refdst_drop(unsigned long refdst) { } -static inline void skb_dst_set_noref(struct sk_buff *skb, - struct dst_entry *dst) { } -static inline void dst_init_metrics(struct dst_entry *dst, const u32 *metrics, - bool read_only) { } -#elif !defined(HAVE___SKB_DST_COPY) +#if !defined(HAVE___SKB_DST_COPY) static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) { nskb->_skb_refdst = refdst; @@ -51,13 +32,6 @@ static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -static inline void dst_entries_add(struct dst_ops *ops, int count) -{ - atomic_add(count, &ops->entries); -} -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) static const u32 rpl_dst_default_metrics[RTAX_MAX + 1] = { /* This initializer is needed to force linker to place this variable diff --git a/datapath/linux/compat/include/net/genetlink.h b/datapath/linux/compat/include/net/genetlink.h index b05eae5..602ce38 100644 --- a/datapath/linux/compat/include/net/genetlink.h +++ b/datapath/linux/compat/include/net/genetlink.h @@ -6,17 +6,6 @@ #include #include_next -/* - * 15e473046cb6e5d18a4d0057e61d76315230382b renames pid to portid - * the affected structures are - * netlink_skb_parms::pid -> portid - * genl_info::snd_pid -> snd_portid - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -#define snd_portid snd_pid -#define portid pid -#endif - #ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY struct rpl_genl_family { struct genl_family compat_family; diff --git a/datapath/linux/compat/include/net/ip6_route.h b/datapath/linux/compat/include/net/ip6_route.h index e49ca39..7c78fd5 100644 --- a/datapath/linux/compat/include/net/ip6_route.h +++ b/datapath/linux/compat/include/net/ip6_route.h @@ -7,29 +7,6 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) - -static inline -struct dst_entry *rpl_ip6_route_output(struct net *net, const struct sock *sk, - struct flowi6 *fl6) -{ - struct flowi fl; - - memset(&fl, 0, sizeof(fl)); - fl.oif = fl6->flowi6_oif; - fl.fl6_dst = fl6->daddr; - fl.fl6_src = fl6->saddr; - fl.mark = fl6->flowi6_mark; - fl.proto = fl6->flowi6_proto; - - return ip6_route_output(net, (struct sock *) sk, &fl); -} -#define ip6_route_output rpl_ip6_route_output - -#define ip6_dst_hoplimit(dst) dst_metric(dst, RTAX_HOPLIMIT) - -#endif /* 2.6.39 */ - #ifndef HAVE_NF_IPV6_OPS_FRAGMENT int rpl_ip6_fragment(struct sock *sk, struct sk_buff *skb, int (*output)(OVS_VPORT_OUTPUT_PARAMS)); diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index ae60f09..68dbd7c 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -301,11 +301,7 @@ int rpl_ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p); #define ip_tunnel_dellink rpl_ip_tunnel_dellink -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head); -#else -void rpl_ip_tunnel_dellink(struct net_device *dev); -#endif #define ip_tunnel_init_net rpl_ip_tunnel_init_net int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, diff --git a/datapath/linux/compat/include/net/ipv6.h b/datapath/linux/compat/include/net/ipv6.h index 48a307a..7fc0339 100644 --- a/datapath/linux/compat/include/net/ipv6.h +++ b/datapath/linux/compat/include/net/ipv6.h @@ -26,21 +26,6 @@ extern int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff, int *fragflg); #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) -static inline u32 ipv6_addr_hash(const struct in6_addr *a) -{ -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 - const unsigned long *ul = (const unsigned long *)a; - unsigned long x = ul[0] ^ ul[1]; - - return (u32)(x ^ (x >> 32)); -#else - return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^ - a->s6_addr32[2] ^ a->s6_addr32[3]); -#endif -} -#endif - #ifndef HAVE___IPV6_ADDR_JHASH static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 unused) { diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h index fb43acb..d46c098 100644 --- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h @@ -3,9 +3,7 @@ #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) #include_next -#endif #ifndef HAVE_NF_CT_ZONE_INIT diff --git a/datapath/linux/compat/include/net/netlink.h b/datapath/linux/compat/include/net/netlink.h index ba24a34..d42bf10 100644 --- a/datapath/linux/compat/include/net/netlink.h +++ b/datapath/linux/compat/include/net/netlink.h @@ -16,21 +16,6 @@ static inline __be16 nla_get_be16(const struct nlattr *nla) } #endif /* !HAVE_NLA_GET_BE16 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -/* This function was introduced in 2.6.31, but initially it performed an - * unaligned access, so we replace it up to 2.6.34 where it was fixed. */ -#define nla_get_be64 rpl_nla_get_be64 -static inline __be64 nla_get_be64(const struct nlattr *nla) -{ - __be64 tmp; - - /* The additional cast is necessary because */ - nla_memcpy(&tmp, (struct nlattr *) nla, sizeof(tmp)); - - return tmp; -} -#endif - #ifndef HAVE_NLA_PUT_BE16 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { diff --git a/datapath/linux/compat/include/net/route.h b/datapath/linux/compat/include/net/route.h index 8f336b6..9e4a1f1 100644 --- a/datapath/linux/compat/include/net/route.h +++ b/datapath/linux/compat/include/net/route.h @@ -3,109 +3,4 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -struct flowi_common { - int flowic_oif; - __u32 flowic_mark; - __u8 flowic_tos; - __u8 flowic_proto; -}; - -union flowi_uli { - struct { - __be16 dport; - __be16 sport; - } ports; - - struct { - __u8 type; - __u8 code; - } icmpt; - - struct { - __le16 dport; - __le16 sport; - } dnports; - - __be32 spi; - __be32 gre_key; - - struct { - __u8 type; - } mht; -}; - -struct flowi4 { - struct flowi_common __fl_common; -#define flowi4_oif __fl_common.flowic_oif -#define flowi4_iif __fl_common.flowic_iif -#define flowi4_mark __fl_common.flowic_mark -#define flowi4_tos __fl_common.flowic_tos -#define flowi4_scope __fl_common.flowic_scope -#define flowi4_proto __fl_common.flowic_proto -#define flowi4_flags __fl_common.flowic_flags -#define flowi4_secid __fl_common.flowic_secid -#define flowi4_tun_key __fl_common.flowic_tun_key - - union flowi_uli uli; -#define fl4_gre_key uli.gre_key - - /* (saddr,daddr) must be grouped, same order as in IP header */ - __be32 saddr; - __be32 daddr; - -} __attribute__((__aligned__(BITS_PER_LONG/8))); - -struct flowi6 { - struct flowi_common __fl_common; -#define flowi6_oif __fl_common.flowic_oif -#define flowi6_iif __fl_common.flowic_iif -#define flowi6_mark __fl_common.flowic_mark -#define flowi6_tos __fl_common.flowic_tos -#define flowi6_scope __fl_common.flowic_scope -#define flowi6_proto __fl_common.flowic_proto -#define flowi6_flags __fl_common.flowic_flags -#define flowi6_secid __fl_common.flowic_secid -#define flowi6_tun_key __fl_common.flowic_tun_key - struct in6_addr daddr; - struct in6_addr saddr; - __be32 flowlabel; - union flowi_uli uli; -#define fl6_sport uli.ports.sport -#define fl6_dport uli.ports.dport -#define fl6_icmp_type uli.icmpt.type -#define fl6_icmp_code uli.icmpt.code -#define fl6_ipsec_spi uli.spi -#define fl6_mh_type uli.mht.type -#define fl6_gre_key uli.gre_key -} __attribute__((__aligned__(BITS_PER_LONG/8))); - -static inline struct rtable *rpl_ip_route_output_key(struct net *net, struct flowi4 *flp) -{ - struct rtable *rt; - /* Tunnel configuration keeps DSCP part of TOS bits, But Linux - * router expect RT_TOS bits only. - */ - - struct flowi fl = { .nl_u = { .ip4_u = { - .daddr = flp->daddr, - .saddr = flp->saddr, - .tos = RT_TOS(flp->flowi4_tos) } }, - .mark = flp->flowi4_mark, - .proto = flp->flowi4_proto }; - - if (unlikely(ip_route_output_key(net, &rt, &fl))) - return ERR_PTR(-EADDRNOTAVAIL); - flp->saddr = fl.nl_u.ip4_u.saddr; - return rt; -} -#define ip_route_output_key rpl_ip_route_output_key -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) -static inline int ip4_dst_hoplimit(const struct dst_entry *dst) -{ - return dst_metric(dst, RTAX_HOPLIMIT); -} -#endif #endif diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 2f297a5..4304862 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -365,16 +365,12 @@ static void __gre_tunnel_init(struct net_device *dev) dev->mtu = ETH_DATA_LEN - t_hlen - 4; dev->features |= GRE_FEATURES; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= GRE_FEATURES; -#endif if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { /* TCP offload with GRE SEQ is not supported. */ dev->features |= NETIF_F_GSO_SOFTWARE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= NETIF_F_GSO_SOFTWARE; -#endif /* Can use a lockless transmit, unless we generate * output sequences */ @@ -496,9 +492,7 @@ static const struct net_device_ops gre_tap_netdev_ops = { #else .ndo_change_mtu = ip_tunnel_change_mtu, #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif #ifdef HAVE_NDO_GET_IFLINK .ndo_get_iflink = ip_tunnel_get_iflink, #endif @@ -515,13 +509,8 @@ static void ipgre_tap_setup(struct net_device *dev) ip_tunnel_setup(dev, gre_tap_net_id); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) -#else -static int ipgre_newlink(struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) -#endif { struct ip_tunnel_parm p; int err; diff --git a/datapath/linux/compat/ip_tunnel.c b/datapath/linux/compat/ip_tunnel.c index be82b55..ebd1544 100644 --- a/datapath/linux/compat/ip_tunnel.c +++ b/datapath/linux/compat/ip_tunnel.c @@ -168,11 +168,7 @@ static void ip_tunnel_dev_free(struct net_device *dev) free_netdev(dev); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head) -#else -void rpl_ip_tunnel_dellink(struct net_device *dev) -#endif { struct ip_tunnel *tunnel = netdev_priv(dev); struct ip_tunnel_net *itn; @@ -180,9 +176,7 @@ void rpl_ip_tunnel_dellink(struct net_device *dev) itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); ip_tunnel_del(itn, netdev_priv(dev)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) - unregister_netdevice_queue(dev, head); -#endif + unregister_netdevice_queue(dev, head); } int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c index 4882a63..41531ad 100644 --- a/datapath/linux/compat/lisp.c +++ b/datapath/linux/compat/lisp.c @@ -597,10 +597,8 @@ static void lisp_setup(struct net_device *dev) dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_GSO_SOFTWARE; -#endif #ifdef USE_UPSTREAM_TUNNEL netif_keep_dst(dev); #endif diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c index ee1c7aa..69859e2 100644 --- a/datapath/linux/compat/stt.c +++ b/datapath/linux/compat/stt.c @@ -239,9 +239,7 @@ static void copy_skb_metadata(struct sk_buff *to, struct sk_buff *from) to->priority = from->priority; to->mark = from->mark; to->vlan_tci = from->vlan_tci; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) to->vlan_proto = from->vlan_proto; -#endif skb_copy_secmark(to, from); } @@ -762,10 +760,8 @@ static int stt_can_offload(struct sk_buff *skb, __be16 l3_proto, u8 l4_proto) if (skb->len + STT_HEADER_LEN + sizeof(struct iphdr) > 65535) return 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (skb_vlan_tag_present(skb) && skb->vlan_proto != htons(ETH_P_8021Q)) return 0; -#endif return 1; } @@ -792,7 +788,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, int min_headroom) { int err; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (skb_vlan_tag_present(skb) && skb->vlan_proto != htons(ETH_P_8021Q)) { min_headroom += VLAN_HLEN; @@ -812,7 +807,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, int min_headroom) goto error; } } -#endif if (skb_is_gso(skb)) { struct sk_buff *nskb; diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c index 23801bb..852069f 100644 --- a/datapath/linux/compat/udp_tunnel.c +++ b/datapath/linux/compat/udp_tunnel.c @@ -130,9 +130,7 @@ void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock, udp_sk(sk)->encap_type = cfg->encap_type; udp_sk(sk)->encap_rcv = cfg->encap_rcv; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) udp_sk(sk)->encap_destroy = cfg->encap_destroy; -#endif #ifdef HAVE_UDP_TUNNEL_SOCK_CFG_GRO_RECEIVE udp_sk(sk)->gro_receive = cfg->gro_receive; udp_sk(sk)->gro_complete = cfg->gro_complete; diff --git a/datapath/linux/compat/utils.c b/datapath/linux/compat/utils.c index c9546ea..a4a98ba 100644 --- a/datapath/linux/compat/utils.c +++ b/datapath/linux/compat/utils.c @@ -18,28 +18,6 @@ #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -void rpl_inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, - const __be32 *from, const __be32 *to, - int pseudohdr) -{ - __be32 diff[] = { - ~from[0], ~from[1], ~from[2], ~from[3], - to[0], to[1], to[2], to[3], - }; - if (skb->ip_summed != CHECKSUM_PARTIAL) { - *sum = csum_fold(csum_partial(diff, sizeof(diff), - ~csum_unfold(*sum))); - if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) - skb->csum = ~csum_partial(diff, sizeof(diff), - ~skb->csum); - } else if (pseudohdr) - *sum = ~csum_fold(csum_partial(diff, sizeof(diff), - csum_unfold(*sum))); -} -EXPORT_SYMBOL_GPL(rpl_inet_proto_csum_replace16); -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) bool rpl___net_get_random_once(void *buf, int nbytes, bool *done, From patchwork Sat May 19 00:49:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="czivzTsP"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmk60Vdfz9s4w for ; Sat, 19 May 2018 10:53:18 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4B6EBD3D; Sat, 19 May 2018 00:50:15 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 26E25C9D for ; Sat, 19 May 2018 00:50:02 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9C861674 for ; Sat, 19 May 2018 00:49:57 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id c10-v6so4484082pfi.12 for ; Fri, 18 May 2018 17:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=++inPSDS43Z0+rJd8Rp9AGOo20Kw4zZ04iuZEHmOBo4=; b=czivzTsP8ExyTTKCO4jkZ0MGJC8nUKLuL5Dg0PMO0pqmVD2nxy0GmHwET/r+0UVehM vShW9DTU3vMW/BLUkcvuzA7V0rIrA4X7OBzCzRMEPWaDMIa1U0Thf8M0GsOpk5Z0gLiJ Ii3KiOKMveNPrF9p+EdZvSN97wtyCpa1o6FgM/M/XntxXXlvOgs5k4k47JOK0wudnfnK /i2ht1ujjZFyvHaJ4kHXW0akx9wY04Qw/0wUNYCGz2oGdwo4v3RBcqXBxrga91P9nCPY O9ZYxu9+oa2gQ5wg/uu5+ZjLT8Un/znQ293HmjZNiHhYfmC1u/UdvivMti8PhNzXedHK mplw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=++inPSDS43Z0+rJd8Rp9AGOo20Kw4zZ04iuZEHmOBo4=; b=aIP9jtEMBfB6OAQRrMWMPn7AaozD5ALrboMhep774attO00Aa8Fk6PShEffMWaN/p/ BSp83e7BdVNsmRZogct+RHLA2l4+SUMv5NnWQLvpwJamcoa56AJnfqigj0B9clcCuczY bKvjSzRh6Mct7UXpI77x3RBjBLozzI6Zv+sPOfjMjNSAgM/AMp2wRInJx5cz387ibP5l XhDcfV/sfjwjcgD83Nxnhb0Rhs6UN/ylcmlVtt1EJo1xVi6AdtTya6Nz/XqMzig5n0uh a+dL+I/IRi7I0vl1xveUsjOwwUPwMWLcJaYokxb2fMa0EsBqPJjTRKuT97JqnRQGLOam ZkyA== X-Gm-Message-State: ALKqPwfQ/5nbV/qNiQJHNOho+4V6zzayj0b5REBLH0R2WkkLg9vXS4ww VFzOZe8kqJfq6j4qPz87aVpBZw== X-Google-Smtp-Source: AB8JxZo6YmFKArqg1GFz0s4Kn7ju7QVdHMsSlnmsxufXkG/6dIh9iIoXRHZNBRC0ccL56M3jRz++3g== X-Received: by 2002:a62:1f03:: with SMTP id f3-v6mr11496587pff.213.1526690995220; Fri, 18 May 2018 17:49:55 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:54 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:10 -0700 Message-Id: <1526690988-29912-3-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 02/40] gre: introduce native tunnel support for ERSPAN X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 84e54fe0a5eaed696dee4019c396f8396f5a908b Author: William Tu Date: Tue Aug 22 09:40:28 2017 -0700 gre: introduce native tunnel support for ERSPAN The patch adds ERSPAN type II tunnel support. The implementation is based on the draft at [1]. One of the purposes is for Linux box to be able to receive ERSPAN monitoring traffic sent from the Cisco switch, by creating a ERSPAN tunnel device. In addition, the patch also adds ERSPAN TX, so Linux virtual switch can redirect monitored traffic to the ERSPAN tunnel device. The traffic will be encapsulated into ERSPAN and sent out. The implementation reuses tunnel key as ERSPAN session ID, and field 'erspan' as ERSPAN Index fields: ./ip link add dev ers11 type erspan seq key 100 erspan 123 \ local 172.16.1.200 remote 172.16.1.100 To use the above device as ERSPAN receiver, configure Nexus 5000 switch as below: monitor session 100 type erspan-source erspan-id 123 vrf default destination ip 172.16.1.200 source interface Ethernet1/11 both source interface Ethernet1/12 both no shut monitor erspan origin ip-address 172.16.1.100 global [1] https://tools.ietf.org/html/draft-foschiano-erspan-01 [2] iproute2 patch: http://marc.info/?l=linux-netdev&m=150306086924951&w=2 [3] test script: http://marc.info/?l=linux-netdev&m=150231021807304&w=2 Signed-off-by: William Tu Signed-off-by: Meenakshi Vohra Cc: Alexey Kuznetsov Cc: Hideaki YOSHIFUJI Signed-off-by: David S. Miller This commit also backports heavily from upstream gre, ip_gre and ip_tunnel modules to support the necessary erspan ip gre infrastructure as well as implementing a variety of compatability layer changes for same support. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- acinclude.m4 | 49 +- datapath/linux/Modules.mk | 3 +- datapath/linux/compat/gre.c | 222 +++-- datapath/linux/compat/include/linux/if_ether.h | 4 + datapath/linux/compat/include/linux/skbuff.h | 29 + datapath/linux/compat/include/net/dst_metadata.h | 23 +- datapath/linux/compat/include/net/erspan.h | 65 ++ datapath/linux/compat/include/net/gre.h | 13 +- datapath/linux/compat/include/net/ip_tunnels.h | 158 +++- datapath/linux/compat/ip_gre.c | 1069 ++++++++++++++++++++-- datapath/linux/compat/ip_tunnel.c | 493 +++++++++- datapath/linux/compat/ip_tunnels_core.c | 41 + 12 files changed, 1935 insertions(+), 234 deletions(-) create mode 100644 datapath/linux/compat/include/net/erspan.h diff --git a/acinclude.m4 b/acinclude.m4 index a2444af..8962862 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -818,7 +818,54 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], frag_percpu_counter_batch[], [OVS_DEFINE([HAVE_FRAG_PERCPU_COUNTER_BATCH])]) - + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [null_compute_pseudo], + [OVS_DEFINE([HAVE_NULL_COMPUTE_PSEUDO])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [__skb_checksum_convert], + [OVS_DEFINE([HAVE_SKB_CHECKSUM_CONVERT])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h], [net_device], + [max_mtu], + [OVS_DEFINE([HAVE_NET_DEVICE_MAX_MTU])]) + OVS_GREP_IFELSE([$KSRC/include/net/erspan.h], + [__LINUX_ERSPAN_H], + [OVS_DEFINE([HAVE_LINUX_ERSPAN_H])]) + OVS_FIND_PARAM_IFELSE([$KSRC/net/ipv6/ip6_gre.c], + [ip6gre_tunnel_validate], [extack], + [OVS_DEFINE([HAVE_IP6GRE_EXTACK])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ip6_tunnel.h], [__ip6_tnl_parm], + [erspan_ver], + [OVS_DEFINE([HAVE_IP6_TNL_PARM_ERSPAN_VER])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [SKB_GSO_IPXIP6], + [OVS_DEFINE([HAVE_SKB_GSO_IPXIP6])]) + OVS_FIND_PARAM_IFELSE([$KSRC/include/net/ipv6.h], + [ip6_make_flowlabel], [fl6], + [OVS_DEFINE([HAVE_IP6_MAKE_FLOWLABEL_FL6])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ipv6.h], [netns_sysctl_ipv6], + [auto_flowlabels], + [OVS_DEFINE([HAVE_NETNS_SYSCTL_IPV6_AUTO_FLOWLABELS])]) + OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], + [netif_keep_dst], + [OVS_DEFINE([HAVE_NETIF_KEEP_DST])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h], [net_device_ops], + [ndo_get_iflink], + [OVS_DEFINE([HAVE_NDO_GET_IFLINK])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [skb_set_inner_ipproto], + [OVS_DEFINE([HAVE_SKB_SET_INNER_IPPROTO])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [tunnel_encap_types], + [OVS_DEFINE([HAVE_TUNNEL_ENCAP_TYPES])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_IPTUN_ENCAP_TYPE], + [OVS_DEFINE([HAVE_IFLA_IPTUN_ENCAP_TYPE])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_IPTUN_COLLECT_METADATA], + [OVS_DEFINE([HAVE_IFLA_IPTUN_COLLECT_METADATA])]) + OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c], + [parse_gre_header], + [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])]) if cmp -s datapath/linux/kcompat.h.new \ datapath/linux/kcompat.h >/dev/null 2>&1; then diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index 0dbc1ed..e0a90c3 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -104,5 +104,6 @@ openvswitch_headers += \ linux/compat/include/net/netfilter/nf_conntrack_zones.h \ linux/compat/include/net/netfilter/nf_nat.h \ linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \ - linux/compat/include/net/sctp/checksum.h + linux/compat/include/net/sctp/checksum.h \ + linux/compat/include/net/erspan.h EXTRA_DIST += linux/compat/build-aux/export-check-whitelist diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index a341fa3..08a5a30 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -41,91 +41,25 @@ #ifndef USE_UPSTREAM_TUNNEL #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) -#ifndef HAVE_GRE_HANDLE_OFFLOADS - -#ifndef HAVE_GRE_CISCO_REGISTER - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - -#define GREPROTO_CISCO 0 -#define GREPROTO_MAX 1 - -struct gre_protocol { - int (*handler)(struct sk_buff *skb); -}; -static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; - -static int gre_rcv(struct sk_buff *skb) -{ - const struct gre_protocol *proto; - u8 ver; - int ret; - - if (!pskb_may_pull(skb, 12)) - goto drop; - - ver = skb->data[1] & 0x7f; - if (ver >= GREPROTO_MAX) - goto drop; - - rcu_read_lock(); - proto = rcu_dereference(gre_proto[ver]); - if (!proto || !proto->handler) - goto drop_unlock; - ret = proto->handler(skb); - rcu_read_unlock(); - return ret; - -drop_unlock: - rcu_read_unlock(); -drop: - kfree_skb(skb); - return NET_RX_DROP; -} - -static const struct net_protocol net_gre_protocol = { - .handler = gre_rcv, - .netns_ok = 1, -}; - -static int gre_add_protocol(const struct gre_protocol *proto, u8 version) -{ - if (version >= GREPROTO_MAX) - return -EINVAL; - - if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { - pr_err("%s: cannot register gre protocol handler\n", __func__); - return -EAGAIN; - } - - return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? - 0 : -EBUSY; -} - -static int gre_del_protocol(const struct gre_protocol *proto, u8 version) +#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen +#define gre_calc_hlen rpl_ip_gre_calc_hlen +static int rpl_ip_gre_calc_hlen(__be16 o_flags) { - int ret; - - if (version >= GREPROTO_MAX) - return -EINVAL; - - ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? - 0 : -EBUSY; - - if (ret) - return ret; - - synchronize_net(); - - ret = inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); - if (ret) - return ret; + int addend = 4; - return 0; + if (o_flags & TUNNEL_CSUM) + addend += 4; + if (o_flags & TUNNEL_KEY) + addend += 4; + if (o_flags & TUNNEL_SEQ) + addend += 4; + return addend; } -#endif +#ifndef HAVE_GRE_HANDLE_OFFLOADS +#ifndef HAVE_GRE_CISCO_REGISTER +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER static __sum16 check_checksum(struct sk_buff *skb) { __sum16 csum = 0; @@ -148,20 +82,6 @@ static __sum16 check_checksum(struct sk_buff *skb) return csum; } -#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen -static int ip_gre_calc_hlen(__be16 o_flags) -{ - int addend = 4; - - if (o_flags & TUNNEL_CSUM) - addend += 4; - if (o_flags & TUNNEL_KEY) - addend += 4; - if (o_flags & TUNNEL_SEQ) - addend += 4; - return addend; -} - #define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags static __be16 gre_flags_to_tnl_flags(__be16 flags) { @@ -202,13 +122,12 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, tpi->flags = gre_flags_to_tnl_flags(greh->flags); hdr_len = ip_gre_calc_hlen(tpi->flags); + tpi->hdr_len = hdr_len; + tpi->proto = greh->protocol; if (!pskb_may_pull(skb, hdr_len)) return -EINVAL; - greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); - tpi->proto = greh->protocol; - options = (__be32 *)(greh + 1); if (greh->flags & GRE_CSUM) { if (check_checksum(skb)) { @@ -246,20 +165,25 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, return iptunnel_pull_header(skb, hdr_len, tpi->proto, false); } +#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ + static struct gre_cisco_protocol __rcu *gre_cisco_proto; static int gre_cisco_rcv(struct sk_buff *skb) { struct tnl_ptk_info tpi; - bool csum_err = false; struct gre_cisco_protocol *proto; rcu_read_lock(); proto = rcu_dereference(gre_cisco_proto); if (!proto) goto drop; - - if (parse_gre_header(skb, &tpi, &csum_err) < 0) - goto drop; +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + { + bool csum_err = false; + if (parse_gre_header(skb, &tpi, &csum_err) < 0) + goto drop; + } +#endif proto->handler(skb, &tpi); rcu_read_unlock(); return 0; @@ -309,5 +233,101 @@ EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister); #endif /* !HAVE_GRE_CISCO_REGISTER */ #endif +void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct gre_base_hdr *greh; + + skb_push(skb, hdr_len); + + skb_reset_transport_header(skb); + greh = (struct gre_base_hdr *)skb->data; + greh->flags = tnl_flags_to_gre_flags(tpi->flags); + greh->protocol = tpi->proto; + + if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) { + __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); + + if (tpi->flags&TUNNEL_SEQ) { + *ptr = tpi->seq; + ptr--; + } + if (tpi->flags&TUNNEL_KEY) { + *ptr = tpi->key; + ptr--; + } + if (tpi->flags&TUNNEL_CSUM && + !(skb_shinfo(skb)->gso_type & + (SKB_GSO_GRE|SKB_GSO_GRE_CSUM))) { + *ptr = 0; + *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, + skb->len, 0)); + } + } +} +EXPORT_SYMBOL_GPL(rpl_gre_build_header); + +/* Fills in tpi and returns header length to be pulled. */ +int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool *csum_err, __be16 proto, int nhs) +{ + const struct gre_base_hdr *greh; + __be32 *options; + int hdr_len; + + if (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr)))) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb->data + nhs); + if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) + return -EINVAL; + + tpi->flags = gre_flags_to_tnl_flags(greh->flags); + hdr_len = gre_calc_hlen(tpi->flags); + + if (!pskb_may_pull(skb, nhs + hdr_len)) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb->data + nhs); + tpi->proto = greh->protocol; + + options = (__be32 *)(greh + 1); + if (greh->flags & GRE_CSUM) { + if (skb_checksum_simple_validate(skb)) { + *csum_err = true; + return -EINVAL; + } + + skb_checksum_try_convert(skb, IPPROTO_GRE, 0, + null_compute_pseudo); + options++; + } + + if (greh->flags & GRE_KEY) { + tpi->key = *options; + options++; + } else { + tpi->key = 0; + } + if (unlikely(greh->flags & GRE_SEQ)) { + tpi->seq = *options; + options++; + } else { + tpi->seq = 0; + } + /* WCCP version 1 and 2 protocol decoding. + * - Change protocol to IPv4/IPv6 + * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header + */ + if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { + tpi->proto = proto; + if ((*(u8 *)options & 0xF0) != 0x40) + hdr_len += 4; + } + tpi->hdr_len = hdr_len; + return hdr_len; +} +EXPORT_SYMBOL(rpl_gre_parse_header); + #endif /* CONFIG_NET_IPGRE_DEMUX */ #endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h index c989c6e..aaa88db 100644 --- a/datapath/linux/compat/include/linux/if_ether.h +++ b/datapath/linux/compat/include/linux/if_ether.h @@ -23,6 +23,10 @@ #define ETH_P_NSH 0x894F /* Network Service Header */ #endif +#ifndef ETH_P_ERSPAN +#define ETH_P_ERSPAN 0x88BE /* ERSPAN TYPE II */ +#endif + #define inner_eth_hdr rpl_inner_eth_hdr static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 149ef28..45778bd 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -21,6 +21,35 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, #define ignore_df local_df #endif + +#ifndef HAVE_NULL_COMPUTE_PSEUDO +static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto) +{ + return 0; +} +#endif + +#ifndef HAVE_SKB_CHECKSUM_CONVERT +static inline bool __skb_checksum_convert_check(struct sk_buff *skb) +{ + return (skb->ip_summed == CHECKSUM_NONE && skb->csum_valid); +} + +static inline void __skb_checksum_convert(struct sk_buff *skb, + __sum16 check, __wsum pseudo) +{ + skb->csum = ~pseudo; + skb->ip_summed = CHECKSUM_COMPLETE; +} + +#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \ +do { \ + if (__skb_checksum_convert_check(skb)) \ + __skb_checksum_convert(skb, check, \ + compute_pseudo(skb, proto)); \ +} while (0) + +#endif #ifndef HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb, const int offset, void *to, diff --git a/datapath/linux/compat/include/net/dst_metadata.h b/datapath/linux/compat/include/net/dst_metadata.h index e401eb4..93ea954 100644 --- a/datapath/linux/compat/include/net/dst_metadata.h +++ b/datapath/linux/compat/include/net/dst_metadata.h @@ -1,6 +1,11 @@ #ifndef __NET_DST_METADATA_WRAPPER_H #define __NET_DST_METADATA_WRAPPER_H 1 +enum metadata_type { + METADATA_IP_TUNNEL, + METADATA_HW_PORT_MUX, +}; + #ifdef USE_UPSTREAM_TUNNEL #include_next #else @@ -11,19 +16,26 @@ #include #include +struct hw_port_info { + struct net_device *lower_dev; + u32 port_id; +}; + struct metadata_dst { - unsigned long dst; + struct dst_entry dst; + enum metadata_type type; union { struct ip_tunnel_info tun_info; + struct hw_port_info port_info; } u; }; static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen) { - unsigned long *dst; + struct dst_entry *dst; dst = &md_dst->dst; - *dst = 0; + #if 0 dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, DST_METADATA | DST_NOCACHE | DST_NOCOUNT); @@ -105,11 +117,6 @@ void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb, struct metadata_dst *tun_dst); #ifndef HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE -enum metadata_type { - METADATA_IP_TUNNEL, - METADATA_HW_PORT_MUX, -}; - static inline struct metadata_dst * rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags) { diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h new file mode 100644 index 0000000..6c5d3a7 --- /dev/null +++ b/datapath/linux/compat/include/net/erspan.h @@ -0,0 +1,65 @@ +#ifndef USE_UPSTREAM_TUNNEL +#ifndef __LINUX_ERSPAN_H +#define __LINUX_ERSPAN_H + +/* + * GRE header for ERSPAN encapsulation (8 octets [34:41]) -- 8 bytes + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|0|0|1|0|00000|000000000|00000| Protocol Type for ERSPAN | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (increments per packet per session) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Note that in the above GRE header [RFC1701] out of the C, R, K, S, + * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The + * other fields are set to zero, so only a sequence number follows. + * + * ERSPAN Type II header (8 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS | En|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB + */ + +#define ERSPAN_VERSION 0x1 + +#define VER_MASK 0xf000 +#define VLAN_MASK 0x0fff +#define COS_MASK 0xe000 +#define EN_MASK 0x1800 +#define T_MASK 0x0400 +#define ID_MASK 0x03ff +#define INDEX_MASK 0xfffff + +enum erspan_encap_type { + ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ + ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ + ERSPAN_ENCAP_8021Q = 0x2, /* originally 802.1Q encapsulated */ + ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ +}; + +struct erspan_metadata { + __be32 index; /* type II */ +}; + +struct erspanhdr { + __be16 ver_vlan; +#define VER_OFFSET 12 + __be16 session_id; +#define COS_OFFSET 13 +#define EN_OFFSET 11 +#define T_OFFSET 10 + struct erspan_metadata md; +}; + +#endif +#else +#include_next +#endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 764b9f1..ead86f6 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -28,11 +28,7 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #endif #else - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || \ - defined(HAVE_GRE_CISCO_REGISTER) #include_next -#endif #ifndef HAVE_GRE_CISCO_REGISTER @@ -62,6 +58,10 @@ struct gre_base_hdr { #endif /* HAVE_GRE_CISCO_REGISTER */ +#define gre_build_header rpl_gre_build_header +void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len); + int rpl_ipgre_init(void); void rpl_ipgre_fini(void); @@ -69,6 +69,10 @@ void rpl_ipgre_fini(void); struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type); +#define gre_parse_header rpl_gre_parse_header +int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool *csum_err, __be16 proto, int nhs); + #define gre_fb_xmit rpl_gre_fb_xmit netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #endif /* USE_UPSTREAM_TUNNEL */ @@ -79,4 +83,5 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); + #endif diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 68dbd7c..2685de7 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -8,6 +8,11 @@ * Only function that do not depend on ip_tunnel structure can * be used. Those needs to be explicitly defined in this header file. */ #include_next + +#ifndef TUNNEL_ERSPAN_OPT +#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) +#endif +#define ovs_ip_tunnel_encap ip_tunnel_encap #else #include @@ -18,6 +23,21 @@ #include #include #include +#include + +#ifndef MAX_IPTUN_ENCAP_OPS +#define MAX_IPTUN_ENCAP_OPS 8 +#endif + +#ifndef HAVE_TUNNEL_ENCAP_TYPES +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, +}; + +#define HAVE_TUNNEL_ENCAP_TYPES 1 +#endif #define __iptunnel_pull_header rpl___iptunnel_pull_header int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len, @@ -41,13 +61,17 @@ int ovs_iptunnel_handle_offloads(struct sk_buff *skb, */ #define iptunnel_handle_offloads rpl_iptunnel_handle_offloads struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, - bool csum_help, - int gso_type_mask); + bool csum_help, + int gso_type_mask); #define iptunnel_xmit rpl_iptunnel_xmit void rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, __be16 df, bool xnet); +#define ip_tunnel_xmit rpl_ip_tunnel_xmit +void rpl_ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, const u8 protocol); + #ifndef TUNNEL_CSUM #define TUNNEL_CSUM __cpu_to_be16(0x01) @@ -64,12 +88,17 @@ struct tnl_ptk_info { __be16 proto; __be32 key; __be32 seq; + int hdr_len; }; #define PACKET_RCVD 0 #define PACKET_REJECT 1 +#define PACKET_NEXT 2 #endif +#define IP_TNL_HASH_BITS 7 +#define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) + #ifndef TUNNEL_DONT_FRAGMENT #define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) #endif @@ -91,6 +120,9 @@ struct tnl_ptk_info { #undef TUNNEL_OPTIONS_PRESENT #define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT) +/* Keep error state on tunnel for 30 sec */ +#define IPTUNNEL_ERR_TIMEO (30*HZ) + /* Used to memset ip_tunnel padding. */ #define IP_TUNNEL_KEY_SIZE offsetofend(struct ip_tunnel_key, tp_dst) @@ -131,6 +163,30 @@ struct ip_tunnel_info { u8 mode; }; +/* 6rd prefix/relay information */ +#ifdef CONFIG_IPV6_SIT_6RD +struct ip_tunnel_6rd_parm { + struct in6_addr prefix; + __be32 relay_prefix; + u16 prefixlen; + u16 relay_prefixlen; +}; +#endif + +struct ip_tunnel_encap { + u16 type; + u16 flags; + __be16 sport; + __be16 dport; +}; + +struct ip_tunnel_prl_entry { + struct ip_tunnel_prl_entry __rcu *next; + __be32 addr; + u16 flags; + struct rcu_head rcu_head; +}; + static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info *tun_info) { return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET; @@ -203,39 +259,115 @@ ip_tunnel_dst_cache_usable(const struct sk_buff *skb, } #endif -#define ip_tunnel rpl_ip_tunnel +#define ip_tunnel_dst rpl_ip_tunnel_dst +struct rpl_ip_tunnel_dst { + struct dst_entry __rcu *dst; + __be32 saddr; +}; +#define ip_tunnel rpl_ip_tunnel struct ip_tunnel { + struct ip_tunnel __rcu *next; + struct hlist_node hash_node; struct net_device *dev; struct net *net; /* netns for packet i/o */ - int err_count; /* Number of arrived ICMP errors */ unsigned long err_time; /* Time when the last ICMP error - * arrived - */ + * arrived */ + int err_count; /* Number of arrived ICMP errors */ /* These four fields used only by GRE */ u32 i_seqno; /* The last seen seqno */ u32 o_seqno; /* The last output seqno */ int tun_hlen; /* Precalculated header length */ - int mlink; + + /* These four fields used only by ERSPAN */ + u32 index; /* ERSPAN type II index */ + u8 erspan_ver; /* ERSPAN version */ + u8 dir; /* ERSPAN direction */ + u16 hwid; /* ERSPAN hardware ID */ + + struct dst_cache dst_cache; struct ip_tunnel_parm parms; + int mlink; int encap_hlen; /* Encap header length (FOU,GUE) */ int hlen; /* tun_hlen + encap_hlen */ + struct ip_tunnel_encap encap; - int ip_tnl_net_id; - bool collect_md; + /* for SIT */ +#ifdef CONFIG_IPV6_SIT_6RD + struct ip_tunnel_6rd_parm ip6rd; +#endif + struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */ + unsigned int prl_count; /* # of entries in PRL */ + unsigned int ip_tnl_net_id; + struct gro_cells gro_cells; + __u32 fwmark; + bool collect_md; + bool ignore_df; }; #define ip_tunnel_net rpl_ip_tunnel_net struct ip_tunnel_net { + struct net_device *fb_tunnel_dev; + struct hlist_head tunnels[IP_TNL_HASH_SIZE]; struct ip_tunnel __rcu *collect_md_tun; - struct rtnl_link_ops *rtnl_ops; }; +struct ip_tunnel_encap_ops { + size_t (*encap_hlen)(struct ip_tunnel_encap *e); + int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, + const u8 *protocol, struct flowi4 *fl4); +}; + +extern const struct ip_tunnel_encap_ops __rcu * + rpl_iptun_encaps[MAX_IPTUN_ENCAP_OPS]; + +#define ip_encap_hlen rpl_ip_encap_hlen +static inline int rpl_ip_encap_hlen(struct ip_tunnel_encap *e) +{ + const struct ip_tunnel_encap_ops *ops; + int hlen = -EINVAL; + + if (e->type == TUNNEL_ENCAP_NONE) + return 0; + + if (e->type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_iptun_encaps[e->type]); + if (likely(ops && ops->encap_hlen)) + hlen = ops->encap_hlen(e); + rcu_read_unlock(); + + return hlen; +} + +static inline int ovs_ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, + const u8 *protocol, struct flowi4 *fl4) +{ + const struct ip_tunnel_encap_ops *ops; + int ret = -EINVAL; + + if (t->encap.type == TUNNEL_ENCAP_NONE) + return 0; + + if (t->encap.type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_iptun_encaps[t->encap.type]); + if (likely(ops && ops->build_header)) + ret = ops->build_header(skb, &t->encap, protocol, fl4); + rcu_read_unlock(); + + return ret; +} + #ifndef HAVE_PCPU_SW_NETSTATS #define ip_tunnel_get_stats64 rpl_ip_tunnel_get_stats64 #else @@ -322,6 +454,12 @@ struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev); #define __ip_tunnel_change_mtu rpl___ip_tunnel_change_mtu int rpl___ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); +#define ip_tunnel_lookup rpl_ip_tunnel_lookup +struct ip_tunnel *rpl_ip_tunnel_lookup(struct ip_tunnel_net *itn, + int link, __be16 flags, + __be32 remote, __be32 local, + __be32 key); + static inline int iptunnel_pull_offloads(struct sk_buff *skb) { if (skb_is_gso(skb)) { diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 4304862..3001f3f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -52,6 +52,7 @@ #include #include #include +#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -63,6 +64,10 @@ #include "vport-netdev.h" static int gre_tap_net_id __read_mostly; +static int ipgre_net_id __read_mostly; +static unsigned int erspan_net_id __read_mostly; + +static struct rtnl_link_ops ipgre_link_ops __read_mostly; #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen static int ip_gre_calc_hlen(__be16 o_flags) @@ -78,100 +83,308 @@ static int ip_gre_calc_hlen(__be16 o_flags) return addend; } -#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags -static __be16 tnl_flags_to_gre_flags(__be16 tflags) +/* Returns the least-significant 32 bits of a __be64. */ +static __be32 tunnel_id_to_key(__be64 x) { - __be16 flags = 0; - - if (tflags & TUNNEL_CSUM) - flags |= GRE_CSUM; - if (tflags & TUNNEL_ROUTING) - flags |= GRE_ROUTING; - if (tflags & TUNNEL_KEY) - flags |= GRE_KEY; - if (tflags & TUNNEL_SEQ) - flags |= GRE_SEQ; - if (tflags & TUNNEL_STRICT) - flags |= GRE_STRICT; - if (tflags & TUNNEL_REC) - flags |= GRE_REC; - if (tflags & TUNNEL_VERSION) - flags |= GRE_VERSION; +#ifdef __BIG_ENDIAN + return (__force __be32)x; +#else + return (__force __be32)((__force u64)x >> 32); +#endif +} - return flags; +/* Called with rcu_read_lock and BH disabled. */ +static int gre_err(struct sk_buff *skb, u32 info, + const struct tnl_ptk_info *tpi) +{ + return PACKET_REJECT; } -static __be64 key_to_tunnel_id(__be32 key) +static struct dst_ops md_dst_ops = { + .family = AF_UNSPEC, +}; + +#ifndef DST_METADATA +#define DST_METADATA 0x0080 +#endif + +static void rpl__metadata_dst_init(struct metadata_dst *md_dst, + enum metadata_type type, u8 optslen) + { -#ifdef __BIG_ENDIAN - return (__force __be64)((__force u32)key); -#else - return (__force __be64)((__force u64)key << 32); + struct dst_entry *dst; + + dst = &md_dst->dst; + dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, + DST_METADATA | DST_NOCOUNT); + +#if 0 + /* unused in OVS */ + dst->input = dst_md_discard; + dst->output = dst_md_discard_out; #endif + memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst)); + md_dst->type = type; } -/* Returns the least-significant 32 bits of a __be64. */ -static __be32 tunnel_id_to_key(__be64 x) +static struct metadata_dst *erspan_rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, + gfp_t flags) { -#ifdef __BIG_ENDIAN - return (__force __be32)x; -#else - return (__force __be32)((__force u64)x >> 32); -#endif + struct metadata_dst *md_dst; + + md_dst = kmalloc(sizeof(*md_dst) + optslen, flags); + if (!md_dst) + return NULL; + + rpl__metadata_dst_init(md_dst, type, optslen); + + return md_dst; +} +static inline struct metadata_dst *rpl_tun_rx_dst(int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = erspan_rpl_metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC); + if (!tun_dst) + return NULL; + + tun_dst->u.tun_info.options_len = 0; + tun_dst->u.tun_info.mode = 0; + return tun_dst; +} +static inline struct metadata_dst *rpl__ip_tun_set_dst(__be32 saddr, + __be32 daddr, + __u8 tos, __u8 ttl, + __be16 tp_dst, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = rpl_tun_rx_dst(md_size); + if (!tun_dst) + return NULL; + + ip_tunnel_key_init(&tun_dst->u.tun_info.key, + saddr, daddr, tos, ttl, + 0, 0, tp_dst, tunnel_id, flags); + return tun_dst; } -static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +static inline struct metadata_dst *rpl_ip_tun_rx_dst(struct sk_buff *skb, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + const struct iphdr *iph = ip_hdr(skb); + + return rpl__ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, + 0, flags, tunnel_id, md_size); +} + +static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, + int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst; + struct metadata_dst *tun_dst = NULL; struct ip_tunnel_net *itn; - const struct iphdr *iph; struct ip_tunnel *tunnel; + struct erspanhdr *ershdr; + const struct iphdr *iph; + __be32 session_id; + __be32 index; + int len; - if (tpi->proto != htons(ETH_P_TEB)) - return PACKET_REJECT; + itn = net_generic(net, erspan_net_id); + iph = ip_hdr(skb); + len = gre_hdr_len + sizeof(*ershdr); - itn = net_generic(net, gre_tap_net_id); + if (unlikely(!pskb_may_pull(skb, len))) + return -ENOMEM; iph = ip_hdr(skb); - tunnel = rcu_dereference(itn->collect_md_tun); + ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len); + + /* The original GRE header does not have key field, + * Use ERSPAN 10-bit session ID as key. + */ + tpi->key = cpu_to_be32(get_session_id(ershdr)); + /* OVS doesn't set tunnel key - so don't bother with it */ + tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, + tpi->flags, + iph->saddr, iph->daddr, 0); + if (tunnel) { - __be16 flags; - __be64 tun_id; - int err; - - if (iptunnel_pull_offloads(skb)) - return PACKET_REJECT; - - skb_pop_mac_header(skb); - flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); - tun_id = key_to_tunnel_id(tpi->key); - ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); - - skb_reset_network_header(skb); - err = IP_ECN_decapsulate(iph, skb); - if (unlikely(err)) { - if (err > 1) { - ++tunnel->dev->stats.rx_frame_errors; - ++tunnel->dev->stats.rx_errors; + if (__iptunnel_pull_header(skb, + gre_hdr_len + sizeof(*ershdr), + htons(ETH_P_TEB), + false, false) < 0) + goto drop; + + if (tunnel->collect_md) { + struct ip_tunnel_info *info; + struct erspan_metadata *md; + __be64 tun_id; + __be16 flags; + + tpi->flags |= TUNNEL_KEY; + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ip_tun_rx_dst(skb, flags, tun_id, sizeof(*md)); + if (!tun_dst) return PACKET_REJECT; - } + + md = ip_tunnel_info_opts(&tun_dst->u.tun_info); + md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); + + info = &tun_dst->u.tun_info; + info->key.tun_flags |= TUNNEL_ERSPAN_OPT; + info->options_len = sizeof(*md); + } + + skb_reset_mac_header(skb); + ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + kfree(tun_dst); + return PACKET_RCVD; + } +drop: + kfree_skb(skb); + return PACKET_RCVD; +} + + +static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) +{ + struct metadata_dst tun_dst; + const struct iphdr *iph; + struct ip_tunnel *tunnel; + + iph = ip_hdr(skb); + tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, + iph->saddr, iph->daddr, tpi->key); + + if (tunnel) { + if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, + raw_proto, false) < 0) + goto drop; + + if (tunnel->dev->type != ARPHRD_NONE) + skb_pop_mac_header(skb); + else + skb_reset_mac_header(skb); + if (tunnel->collect_md) { + __be16 flags; + __be64 tun_id; + + flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); + tun_id = key32_to_tunnel_id(tpi->key); + ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); } ovs_ip_tunnel_rcv(tunnel->dev, skb, &tun_dst); return PACKET_RCVD; } - return PACKET_REJECT; + return PACKET_NEXT; + +drop: + kfree_skb(skb); + return PACKET_RCVD; +} + + +static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct net *net = dev_net(skb->dev); + struct ip_tunnel_net *itn; + int res; + + if (tpi->proto == htons(ETH_P_TEB)) + itn = net_generic(net, gre_tap_net_id); + else + itn = net_generic(net, ipgre_net_id); + + res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); + if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { + /* ipgre tunnels in collect metadata mode should receive + * also ETH_P_TEB traffic. + */ + itn = net_generic(net, ipgre_net_id); + res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); + } + return res; } -static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, + __be16 proto) { - if (ipgre_rcv(skb, tpi) == PACKET_RCVD) + struct ip_tunnel *tunnel = netdev_priv(dev); + struct tnl_ptk_info tpi; + + tpi.flags = tunnel->parms.o_flags; + tpi.proto = proto; + tpi.key = tunnel->parms.o_key; + if (tunnel->parms.o_flags & TUNNEL_SEQ) + tunnel->o_seqno++; + tpi.seq = htonl(tunnel->o_seqno); + + /* Push GRE header. */ + gre_build_header(skb, &tpi, tunnel->hlen); + + ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); +} + +#ifndef HAVE_DEMUX_PARSE_GRE_HEADER +static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) +{ + struct tnl_ptk_info tpi; + bool csum_err = false; + int hdr_len; + + hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); + if (hdr_len < 0) + goto drop; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { + if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) + return 0; + } + + if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) + return 0; +drop: + + kfree_skb(skb); + return 0; +} +#else +static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *__tpi) +{ + struct tnl_ptk_info tpi = *__tpi; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { + if (erspan_rcv(skb, &tpi, 0) == PACKET_RCVD) + return 0; + goto drop; + } + + if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD) return 0; +drop: + kfree_skb(skb); return 0; } +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) /* gre_handle_offloads() has different return type on older kernsl. */ @@ -342,6 +555,83 @@ err_free_skb: } EXPORT_SYMBOL(rpl_gre_fb_xmit); +static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, + __be16 proto) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct erspan_metadata *md; + struct rtable *rt = NULL; + struct tnl_ptk_info tpi; + bool truncate = false; + struct flowi4 fl; + int tunnel_hlen; + int version; + __be16 df; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET)) + goto err_free_skb; + + key = &tun_info->key; + md = ip_tunnel_info_opts(tun_info); + if (!md) + goto err_free_rt; + + /* ERSPAN has fixed 8 byte GRE header */ + version = md->version; + tunnel_hlen = 8 + erspan_hdr_len(version); + + rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); + if (!rt) + return; + + if (gre_handle_offloads(skb, false)) + goto err_free_rt; + + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); + truncate = true; + } + + if (version == 1) { + erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), + ntohl(md->u.index), truncate, true); + tpi.hdr_len = ERSPAN_V1_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN); + } else if (version == 2) { + erspan_build_header_v2(skb, + ntohl(tunnel_id_to_key32(key->tun_id)), + md->u.md2.dir, + get_hwid(&md->u.md2), + truncate, true); + tpi.hdr_len = ERSPAN_V2_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN2); + } else { + goto err_free_rt; + } + + tpi.flags = TUNNEL_SEQ; + tpi.key = tunnel_id_to_key32(key->tun_id); + tpi.seq = htonl(tunnel->o_seqno++); + + gre_build_header(skb, &tpi, 8); + + df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; + + iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, + key->tos, key->ttl, df, false); + return; + +err_free_rt: + ip_rt_put(rt); +err_free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; +} + #define GRE_FEATURES (NETIF_F_SG | \ NETIF_F_FRAGLIST | \ NETIF_F_HIGHDMA | \ @@ -354,23 +644,27 @@ static void __gre_tunnel_init(struct net_device *dev) int t_hlen; tunnel = netdev_priv(dev); - tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags); + tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; t_hlen = tunnel->hlen + sizeof(struct iphdr); - dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; - dev->mtu = ETH_DATA_LEN - t_hlen - 4; - dev->features |= GRE_FEATURES; dev->hw_features |= GRE_FEATURES; if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { - /* TCP offload with GRE SEQ is not supported. */ - dev->features |= NETIF_F_GSO_SOFTWARE; - dev->hw_features |= NETIF_F_GSO_SOFTWARE; + /* TCP offload with GRE SEQ is not supported, nor + * can we support 2 levels of outer headers requiring + * an update. + */ + if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || + (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; + } + /* Can use a lockless transmit, unless we generate * output sequences */ @@ -378,19 +672,31 @@ static void __gre_tunnel_init(struct net_device *dev) } } -/* Called with rcu_read_lock and BH disabled. */ -static int gre_err(struct sk_buff *skb, u32 info, - const struct tnl_ptk_info *tpi) -{ - return PACKET_REJECT; -} - static struct gre_cisco_protocol ipgre_protocol = { .handler = gre_rcv, .err_handler = gre_err, .priority = 1, }; +static int __net_init ipgre_init_net(struct net *net) +{ + return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); +} + +static void __net_exit ipgre_exit_net(struct net *net) +{ + struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); + + ip_tunnel_delete_net(itn, &ipgre_link_ops); +} + +static struct pernet_operations ipgre_net_ops = { + .init = ipgre_init_net, + .exit = ipgre_exit_net, + .id = &ipgre_net_id, + .size = sizeof(struct ip_tunnel_net), +}; + static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) { __be16 flags; @@ -433,14 +739,129 @@ out: return ipgre_tunnel_validate(tb, data); } -static void ipgre_netlink_parms(struct net_device *dev, - struct nlattr *data[], - struct nlattr *tb[], - struct ip_tunnel_parm *parms) +enum { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) + IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) + IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) + IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) + IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, +#endif +}; + +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_INDEX + 1) + +static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + __be16 flags = 0; + int ret; + + if (!data) + return 0; + + ret = ipgre_tap_validate(tb, data); + if (ret) + return ret; + + /* ERSPAN should only have GRE sequence and key flag */ + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (flags != (GRE_SEQ | GRE_KEY)) + return -EINVAL; + + /* ERSPAN Session ID only has 10-bit. Since we reuse + * 32-bit key field as ID, check it's range. + */ + if (data[IFLA_GRE_IKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_OKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) + return -EINVAL; + + return 0; +} + +static int ipgre_netlink_parms(struct net_device *dev, + struct nlattr *data[], + struct nlattr *tb[], + struct ip_tunnel_parm *parms) { + struct ip_tunnel *t = netdev_priv(dev); + memset(parms, 0, sizeof(*parms)); parms->iph.protocol = IPPROTO_GRE; + + if (!data) + return 0; + + if (data[IFLA_GRE_LINK]) + parms->link = nla_get_u32(data[IFLA_GRE_LINK]); + + if (data[IFLA_GRE_IFLAGS]) + parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); + + if (data[IFLA_GRE_OFLAGS]) + parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); + + if (data[IFLA_GRE_IKEY]) + parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); + + if (data[IFLA_GRE_OKEY]) + parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); + + if (data[IFLA_GRE_LOCAL]) + parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); + + if (data[IFLA_GRE_REMOTE]) + parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); + + if (data[IFLA_GRE_TTL]) + parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); + + if (data[IFLA_GRE_TOS]) + parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); + + if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { + if (t->ignore_df) + return -EINVAL; + parms->iph.frag_off = htons(IP_DF); + } + + if (data[IFLA_GRE_COLLECT_METADATA]) { + t->collect_md = true; + if (dev->type == ARPHRD_IPGRE) + dev->type = ARPHRD_NONE; + } + + if (data[IFLA_GRE_IGNORE_DF]) { + if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) + && (parms->iph.frag_off & htons(IP_DF))) + return -EINVAL; + t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); + } + + if (data[IFLA_GRE_ERSPAN_INDEX]) { + t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + + if (t->index & ~INDEX_MASK) + return -EINVAL; + } + + return 0; } static int gre_tap_init(struct net_device *dev) @@ -462,6 +883,87 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static inline u8 tos_to_cos(u8 tos) +{ + u8 dscp, cos; + + dscp = tos >> 2; + cos = dscp >> 3; + return cos; +} + +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, bool truncate) +{ + struct iphdr *iphdr = ip_hdr(skb); + struct ethhdr *eth = eth_hdr(skb); + enum erspan_encap_type enc_type; + struct erspanhdr *ershdr; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + + enc_type = ERSPAN_ENCAP_NOVLAN; + + /* If mirrored packet has vlan tag, extract tci and + * perserve vlan header in the mirrored frame. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + enc_type = ERSPAN_ENCAP_INFRAME; + } + + skb_push(skb, sizeof(*ershdr)); + ershdr = (struct erspanhdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr)); + + ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION << VER_OFFSET)); + ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) | + (enc_type << EN_OFFSET & EN_MASK) | + ((truncate << T_OFFSET) & T_MASK)); + ershdr->md.index = htonl(index & INDEX_MASK); +} + +static netdev_tx_t erspan_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + bool truncate = false; + + if (gre_handle_offloads(skb, false)) + goto free_skb; + + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; + + if (skb->len > dev->mtu) { + pskb_trim(skb, dev->mtu); + truncate = true; + } + + /* Push ERSPAN header */ + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate); + tunnel->parms.o_flags &= ~TUNNEL_KEY; + __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); + return NETDEV_TX_OK; + +free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +} + +static netdev_tx_t __erspan_fb_xmit(struct sk_buff *skb) +{ + erspan_fb_xmit(skb, skb->dev, skb->protocol); + return NETDEV_TX_OK; +} + int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -481,9 +983,140 @@ int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(ovs_gre_fill_metadata_dst); +static int erspan_tunnel_init(struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + int t_hlen; + + tunnel->tun_hlen = 8; + tunnel->parms.iph.protocol = IPPROTO_GRE; + t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr); + + dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; + dev->mtu = ETH_DATA_LEN - t_hlen - 4; + dev->features |= GRE_FEATURES; + dev->hw_features |= GRE_FEATURES; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + return ip_tunnel_init(dev); +} + +static int ipgre_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + const void *daddr, const void *saddr, unsigned int len) +{ + struct ip_tunnel *t = netdev_priv(dev); + struct iphdr *iph; + struct gre_base_hdr *greh; + + iph = (struct iphdr *)__skb_push(skb, t->hlen + sizeof(*iph)); + greh = (struct gre_base_hdr *)(iph+1); + greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); + greh->protocol = htons(type); + + memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); + + /* Set the source hardware address. */ + if (saddr) + memcpy(&iph->saddr, saddr, 4); + if (daddr) + memcpy(&iph->daddr, daddr, 4); + if (iph->daddr) + return t->hlen + sizeof(*iph); + + return -(t->hlen + sizeof(*iph)); +} + +static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) +{ + const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); + memcpy(haddr, &iph->saddr, 4); + return 4; +} + +static const struct header_ops ipgre_header_ops = { + .create = ipgre_header, + .parse = ipgre_header_parse, +}; + +static int ipgre_tunnel_init(struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + struct iphdr *iph = &tunnel->parms.iph; + + __gre_tunnel_init(dev); + + memcpy(dev->dev_addr, &iph->saddr, 4); + memcpy(dev->broadcast, &iph->daddr, 4); + + dev->flags = IFF_NOARP; + netif_keep_dst(dev); + dev->addr_len = 4; + + if (!tunnel->collect_md) { + dev->header_ops = &ipgre_header_ops; + } + + return ip_tunnel_init(dev); +} + +static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *tnl_params; + + if (tunnel->collect_md) { + gre_fb_xmit(skb); + return NETDEV_TX_OK; + } + + if (dev->header_ops) { + /* Need space for new headers */ + if (skb_cow_head(skb, dev->needed_headroom - + (tunnel->hlen + sizeof(struct iphdr)))) + goto free_skb; + + tnl_params = (const struct iphdr *)skb->data; + + /* Pull skb since ip_tunnel_xmit() needs skb->data pointing + * to gre header. + */ + skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); + skb_reset_mac_header(skb); + } else { + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; + + tnl_params = &tunnel->parms.iph; + } + + if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) + goto free_skb; + + __gre_xmit(skb, dev, tnl_params, skb->protocol); + return NETDEV_TX_OK; + +free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +} + +static const struct net_device_ops ipgre_netdev_ops = { + .ndo_init = ipgre_tunnel_init, + .ndo_uninit = rpl_ip_tunnel_uninit, + .ndo_start_xmit = ipgre_xmit, + .ndo_change_mtu = ip_tunnel_change_mtu, + .ndo_get_stats64 = ip_tunnel_get_stats64, +#ifdef HAVE_GET_LINK_NET + .ndo_get_iflink = ip_tunnel_get_iflink, +#endif +}; + static const struct net_device_ops gre_tap_netdev_ops = { .ndo_init = gre_tap_init, - .ndo_uninit = ip_tunnel_uninit, + .ndo_uninit = rpl_ip_tunnel_uninit, .ndo_start_xmit = gre_dev_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -492,15 +1125,38 @@ static const struct net_device_ops gre_tap_netdev_ops = { #else .ndo_change_mtu = ip_tunnel_change_mtu, #endif - .ndo_get_stats64 = ip_tunnel_get_stats64, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, #ifdef HAVE_NDO_GET_IFLINK - .ndo_get_iflink = ip_tunnel_get_iflink, + .ndo_get_iflink = rpl_ip_tunnel_get_iflink, #endif #ifdef HAVE_NDO_FILL_METADATA_DST .ndo_fill_metadata_dst = gre_fill_metadata_dst, #endif }; +static const struct net_device_ops erspan_netdev_ops = { + .ndo_init = erspan_tunnel_init, + .ndo_uninit = rpl_ip_tunnel_uninit, + .ndo_start_xmit = erspan_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip_tunnel_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = rpl_ip_tunnel_get_iflink, +#endif +#ifdef HAVE_NDO_FILL_METADATA_DST + .ndo_fill_metadata_dst = gre_fill_metadata_dst, +#endif +}; + +static void ipgre_tunnel_setup(struct net_device *dev) +{ + dev->netdev_ops = &ipgre_netdev_ops; + dev->type = ARPHRD_IPGRE; + ip_tunnel_setup(dev, ipgre_net_id); +} + static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); @@ -509,6 +1165,16 @@ static void ipgre_tap_setup(struct net_device *dev) ip_tunnel_setup(dev, gre_tap_net_id); } +static void erspan_setup(struct net_device *dev) +{ + eth_hw_addr_random(dev); + ether_setup(dev); + dev->netdev_ops = &erspan_netdev_ops; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + ip_tunnel_setup(dev, erspan_net_id); +} + static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { @@ -554,6 +1220,8 @@ static size_t ipgre_get_size(const struct net_device *dev) nla_total_size(2) + /* IFLA_GRE_COLLECT_METADATA */ nla_total_size(0) + + /* IFLA_GRE_ERSPAN_INDEX */ + nla_total_size(4) + 0; } @@ -575,13 +1243,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) !!(p->iph.frag_off & htons(IP_DF)))) goto nla_put_failure; + if (t->index) + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + goto nla_put_failure; + return 0; nla_put_failure: return -EMSGSIZE; } -static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { +static const struct nla_policy ipgre_policy[RPL_IFLA_GRE_MAX + 1] = { [IFLA_GRE_LINK] = { .type = NLA_U32 }, [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, @@ -592,11 +1264,28 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { [IFLA_GRE_TTL] = { .type = NLA_U8 }, [IFLA_GRE_TOS] = { .type = NLA_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, +}; + +static struct rtnl_link_ops ipgre_link_ops __read_mostly = { + .kind = "gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = ipgre_tunnel_setup, + .validate = ipgre_tunnel_validate, + .newlink = ipgre_newlink, + .dellink = ip_tunnel_dellink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip_tunnel_get_link_net, +#endif }; static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { .kind = "ovs_gretap", - .maxtype = IFLA_GRE_MAX, + .maxtype = RPL_IFLA_GRE_MAX, .policy = ipgre_policy, .priv_size = sizeof(struct ip_tunnel), .setup = ipgre_tap_setup, @@ -610,6 +1299,22 @@ static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { #endif }; +static struct rtnl_link_ops erspan_link_ops __read_mostly = { + .kind = "erspan", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = erspan_setup, + .validate = erspan_validate, + .newlink = ipgre_newlink, + .dellink = ip_tunnel_dellink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip_tunnel_get_link_net, +#endif +}; + struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { @@ -650,6 +1355,26 @@ out: } EXPORT_SYMBOL_GPL(rpl_gretap_fb_dev_create); +static int __net_init erspan_init_net(struct net *net) +{ + return ip_tunnel_init_net(net, erspan_net_id, + &erspan_link_ops, NULL); +} + +static void __net_exit erspan_exit_net(struct net *net) +{ + struct ip_tunnel_net *itn = net_generic(net, erspan_net_id); + + ip_tunnel_delete_net(itn, &erspan_link_ops); +} + +static struct pernet_operations erspan_net_ops = { + .init = erspan_init_net, + .exit = erspan_exit_net, + .id = &erspan_net_id, + .size = sizeof(struct ip_tunnel_net), +}; + static int __net_init ipgre_tap_init_net(struct net *net) { return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); @@ -669,6 +1394,158 @@ static struct pernet_operations ipgre_tap_net_ops = { .size = sizeof(struct ip_tunnel_net), }; +static struct net_device *erspan_fb_dev_create(struct net *net, + const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip_tunnel *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &erspan_link_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->collect_md = true; + /* Configure flow based GRE device. */ + err = ipgre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); + if (err) + goto out; + + return dev; +out: + ip_tunnel_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_erspan_vport_ops; + +static struct vport *erspan_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_erspan_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = erspan_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *erspan_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = erspan_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +#ifndef OVS_VPORT_TYPE_ERSPAN +/* Until integration is done... */ +#define OVS_VPORT_TYPE_ERSPAN 107 /* ERSPAN tunnel. */ +#endif +static struct vport_ops ovs_erspan_vport_ops = { + .type = OVS_VPORT_TYPE_ERSPAN, + .create = erspan_create, + .send = __erspan_fb_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + +static struct vport_ops ovs_ipgre_vport_ops; + +static struct vport *ipgre_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_ipgre_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *ipgre_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = ipgre_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +static struct vport_ops ovs_ipgre_vport_ops = { + .type = OVS_VPORT_TYPE_GRE, + .create = ipgre_create, + .send = gre_fb_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + int rpl_ipgre_init(void) { int err; @@ -677,22 +1554,31 @@ int rpl_ipgre_init(void) if (err < 0) goto pnet_tap_faied; + err = register_pernet_device(&erspan_net_ops); + if (err < 0) + goto pnet_erspan_failed; + + err = register_pernet_device(&ipgre_net_ops); + if (err < 0) + goto pnet_ipgre_failed; + err = gre_cisco_register(&ipgre_protocol); if (err < 0) { pr_info("%s: can't add protocol\n", __func__); goto add_proto_failed; } - err = rtnl_link_register(&ipgre_tap_ops); - if (err < 0) - goto tap_ops_failed; - pr_info("GRE over IPv4 tunneling driver\n"); + + ovs_vport_ops_register(&ovs_ipgre_vport_ops); + ovs_vport_ops_register(&ovs_erspan_vport_ops); return 0; -tap_ops_failed: - gre_cisco_unregister(&ipgre_protocol); add_proto_failed: + unregister_pernet_device(&ipgre_net_ops); +pnet_ipgre_failed: + unregister_pernet_device(&erspan_net_ops); +pnet_erspan_failed: unregister_pernet_device(&ipgre_tap_net_ops); pnet_tap_faied: pr_err("Error while initializing GRE %d\n", err); @@ -701,8 +1587,11 @@ pnet_tap_faied: void rpl_ipgre_fini(void) { - rtnl_link_unregister(&ipgre_tap_ops); + ovs_vport_ops_unregister(&ovs_erspan_vport_ops); + ovs_vport_ops_unregister(&ovs_ipgre_vport_ops); gre_cisco_unregister(&ipgre_protocol); + unregister_pernet_device(&ipgre_net_ops); + unregister_pernet_device(&erspan_net_ops); unregister_pernet_device(&ipgre_tap_net_ops); } diff --git a/datapath/linux/compat/ip_tunnel.c b/datapath/linux/compat/ip_tunnel.c index ebd1544..58870bc 100644 --- a/datapath/linux/compat/ip_tunnel.c +++ b/datapath/linux/compat/ip_tunnel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Nicira, Inc. + * Copyright (c) 2013,2018 Nicira, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -52,7 +51,6 @@ #include #include #include -#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -63,18 +61,107 @@ #include "compat.h" #ifndef USE_UPSTREAM_TUNNEL +const struct ip_tunnel_encap_ops __rcu * + rpl_iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly; + +static unsigned int rpl_ip_tunnel_hash(__be32 key, __be32 remote) +{ + return hash_32((__force u32)key ^ (__force u32)remote, + IP_TNL_HASH_BITS); +} + +static bool rpl_ip_tunnel_key_match(const struct ip_tunnel_parm *p, + __be16 flags, __be32 key) +{ + if (p->i_flags & TUNNEL_KEY) { + if (flags & TUNNEL_KEY) + return key == p->i_key; + else + /* key expected, none present */ + return false; + } else + return !(flags & TUNNEL_KEY); +} + +static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, + struct ip_tunnel_parm *parms) +{ + unsigned int h; + __be32 remote; + __be32 i_key = parms->i_key; + + if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) + remote = parms->iph.daddr; + else + remote = 0; + + if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI)) + i_key = 0; + + h = rpl_ip_tunnel_hash(i_key, remote); + return &itn->tunnels[h]; +} + static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t) { + struct hlist_head *head = ip_bucket(itn, &t->parms); + if (t->collect_md) rcu_assign_pointer(itn->collect_md_tun, t); - else - WARN_ONCE(1, "%s: collect md not set\n", t->dev->name); + hlist_add_head_rcu(&t->hash_node, head); } static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t) { if (t->collect_md) rcu_assign_pointer(itn->collect_md_tun, NULL); + hlist_del_init_rcu(&t->hash_node); +} + +static struct net_device *__ip_tunnel_create(struct net *net, + const struct rtnl_link_ops *ops, + struct ip_tunnel_parm *parms) +{ + int err; + struct ip_tunnel *tunnel; + struct net_device *dev; + char name[IFNAMSIZ]; + + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else { + if (strlen(ops->kind) > (IFNAMSIZ - 3)) { + err = -E2BIG; + goto failed; + } + strlcpy(name, ops->kind, IFNAMSIZ); + strncat(name, "%d", 2); + } + + ASSERT_RTNL(); + dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); + if (!dev) { + err = -ENOMEM; + goto failed; + } + dev_net_set(dev, net); + + dev->rtnl_link_ops = ops; + + tunnel = netdev_priv(dev); + tunnel->parms = *parms; + tunnel->net = net; + + err = register_netdevice(dev); + if (err) + goto failed_free; + + return dev; + +failed_free: + free_netdev(dev); +failed: + return ERR_PTR(err); } static inline void init_tunnel_flow(struct flowi4 *fl4, @@ -118,6 +205,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev) } if (dev->type != ARPHRD_ETHER) dev->flags |= IFF_POINTOPOINT; + + dst_cache_reset(&tunnel->dst_cache); } if (!tdev && tunnel->parms.link) @@ -162,6 +251,222 @@ int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) return rpl___ip_tunnel_change_mtu(dev, new_mtu, true); } +static int rpl_tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct rtable *rt, __be16 df, + const struct iphdr *inner_iph) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; + int mtu; + + if (df) + mtu = dst_mtu(&rt->dst) - dev->hard_header_len + - sizeof(struct iphdr) - tunnel->hlen; + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + + if (skb->protocol == htons(ETH_P_IP)) { + if (!skb_is_gso(skb) && + (inner_iph->frag_off & htons(IP_DF)) && + mtu < pkt_size) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + return -E2BIG; + } + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) { + struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); + + if (rt6 && mtu < dst_mtu(skb_dst(skb)) && + mtu >= IPV6_MIN_MTU) { + if ((tunnel->parms.iph.daddr && + !ipv4_is_multicast(tunnel->parms.iph.daddr)) || + rt6->rt6i_dst.plen == 128) { + rt6->rt6i_flags |= RTF_MODIFIED; + dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); + } + } + + if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && + mtu < pkt_size) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -E2BIG; + } + } +#endif + return 0; +} + +void rpl_ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, const u8 protocol) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *inner_iph; + struct flowi4 fl4; + u8 tos, ttl; + __be16 df; + struct rtable *rt; /* Route to the other host */ + unsigned int max_headroom; /* The extra header space needed */ + __be32 dst; + bool connected; + + inner_iph = (const struct iphdr *)skb_inner_network_header(skb); + connected = (tunnel->parms.iph.daddr != 0); + + dst = tnl_params->daddr; + if (dst == 0) { + /* NBMA tunnel */ + + if (skb_dst(skb) == NULL) { + dev->stats.tx_fifo_errors++; + goto tx_error; + } + + if (skb->protocol == htons(ETH_P_IP)) { + rt = skb_rtable(skb); + dst = rt_nexthop(rt, inner_iph->daddr); + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) { + const struct in6_addr *addr6; + struct neighbour *neigh; + bool do_tx_error_icmp; + int addr_type; + + neigh = dst_neigh_lookup(skb_dst(skb), + &ipv6_hdr(skb)->daddr); + if (neigh == NULL) + goto tx_error; + + addr6 = (const struct in6_addr *)&neigh->primary_key; + addr_type = ipv6_addr_type(addr6); + + if (addr_type == IPV6_ADDR_ANY) { + addr6 = &ipv6_hdr(skb)->daddr; + addr_type = ipv6_addr_type(addr6); + } + + if ((addr_type & IPV6_ADDR_COMPATv4) == 0) + do_tx_error_icmp = true; + else { + do_tx_error_icmp = false; + dst = addr6->s6_addr32[3]; + } + neigh_release(neigh); + if (do_tx_error_icmp) + goto tx_error_icmp; + } +#endif + else + goto tx_error; + + connected = false; + } + + tos = tnl_params->tos; + if (tos & 0x1) { + tos &= ~0x1; + if (skb->protocol == htons(ETH_P_IP)) { + tos = inner_iph->tos; + connected = false; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); + connected = false; + } + } + + init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, + tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); + + if (ovs_ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) + goto tx_error; + + rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) : + NULL; + + if (!rt) { + rt = ip_route_output_key(tunnel->net, &fl4); + + if (IS_ERR(rt)) { + dev->stats.tx_carrier_errors++; + goto tx_error; + } + if (connected) + dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, + fl4.saddr); + } + + if (rt->dst.dev == dev) { + ip_rt_put(rt); + dev->stats.collisions++; + goto tx_error; + } + + if (rpl_tnl_update_pmtu(dev, skb, rt, + tnl_params->frag_off, inner_iph)) { + ip_rt_put(rt); + goto tx_error; + } + + if (tunnel->err_count > 0) { + if (time_before(jiffies, + tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { + tunnel->err_count--; + + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + dst_link_failure(skb); + } else + tunnel->err_count = 0; + } + + tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); + ttl = tnl_params->ttl; + if (ttl == 0) { + if (skb->protocol == htons(ETH_P_IP)) + ttl = inner_iph->ttl; +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) + ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; +#endif + else + ttl = ip4_dst_hoplimit(&rt->dst); + } + + df = tnl_params->frag_off; + if (skb->protocol == htons(ETH_P_IP)) + df |= (inner_iph->frag_off&htons(IP_DF)); + + max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + + rt->dst.header_len; + if (max_headroom > dev->needed_headroom) + dev->needed_headroom = max_headroom; + + if (skb_cow_head(skb, dev->needed_headroom)) { + ip_rt_put(rt); + dev->stats.tx_dropped++; + kfree_skb(skb); + return; + } + + iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol, + tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); + + return; + +#if IS_ENABLED(CONFIG_IPV6) +tx_error_icmp: + dst_link_failure(skb); +#endif +tx_error: + dev->stats.tx_errors++; + kfree_skb(skb); +} +EXPORT_SYMBOL_GPL(rpl_ip_tunnel_xmit); + static void ip_tunnel_dev_free(struct net_device *dev) { free_percpu(dev->tstats); @@ -183,24 +488,63 @@ int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, struct rtnl_link_ops *ops, char *devname) { struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); + struct ip_tunnel_parm parms; + unsigned int i; - itn->collect_md_tun = NULL; - itn->rtnl_ops = ops; - return 0; + for (i = 0; i < IP_TNL_HASH_SIZE; i++) + INIT_HLIST_HEAD(&itn->tunnels[i]); + + if (!ops) { + itn->fb_tunnel_dev = NULL; + return 0; + } + + memset(&parms, 0, sizeof(parms)); + if (devname) + strlcpy(parms.name, devname, IFNAMSIZ); + + rtnl_lock(); + itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); + /* FB netdevice is special: we have one, and only one per netns. + * * Allowing to move it to another netns is clearly unsafe. + * */ + if (!IS_ERR(itn->fb_tunnel_dev)) { + itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); + ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); + } + rtnl_unlock(); + + return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev); } static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, struct rtnl_link_ops *ops) { - struct ip_tunnel *t; - - t = rtnl_dereference(itn->collect_md_tun); - if (!t) - return; - unregister_netdevice_queue(t->dev, head); + struct net *net = dev_net(itn->fb_tunnel_dev); + struct net_device *dev, *aux; + int h; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == ops) + unregister_netdevice_queue(dev, head); + + for (h = 0; h < IP_TNL_HASH_SIZE; h++) { + struct ip_tunnel *t; + struct hlist_node *n; + struct hlist_head *thead = &itn->tunnels[h]; + + hlist_for_each_entry_safe(t, n, thead, hash_node) + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, head); + } } -void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops) +void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, + struct rtnl_link_ops *ops) { LIST_HEAD(list); @@ -251,20 +595,41 @@ int rpl_ip_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; + int err; - dev->destructor = ip_tunnel_dev_free; - dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = ip_tunnel_dev_free; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip_tunnel_dev_free; +#endif + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + + err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (err) { + free_percpu(dev->tstats); + return err; + } + + err = gro_cells_init(&tunnel->gro_cells, dev); + if (err) { + dst_cache_destroy(&tunnel->dst_cache); + free_percpu(dev->tstats); + return err; + } + tunnel->dev = dev; tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); iph->version = 4; iph->ihl = 5; - if (tunnel->collect_md) + if (tunnel->collect_md) { dev->features |= NETIF_F_NETNS_LOCAL; - + netif_keep_dst(dev); + } return 0; } @@ -300,4 +665,94 @@ struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev) return tunnel->net; } +struct ip_tunnel *rpl_ip_tunnel_lookup(struct ip_tunnel_net *itn, + int link, __be16 flags, + __be32 remote, __be32 local, + __be32 key) +{ + unsigned int hash; + struct ip_tunnel *t, *cand = NULL; + struct hlist_head *head; + + hash = rpl_ip_tunnel_hash(key, remote); + head = &itn->tunnels[hash]; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (local != t->parms.iph.saddr || + remote != t->parms.iph.daddr || + !(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else + cand = t; + } + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (remote != t->parms.iph.daddr || + t->parms.iph.saddr != 0 || + !(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + + hash = rpl_ip_tunnel_hash(key, 0); + head = &itn->tunnels[hash]; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && + (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) + continue; + + if (!(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + + if (flags & TUNNEL_NO_KEY) + goto skip_key_lookup; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (t->parms.i_key != key || + t->parms.iph.saddr != 0 || + t->parms.iph.daddr != 0 || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + +skip_key_lookup: + if (cand) + return cand; + + if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP) + return netdev_priv(itn->fb_tunnel_dev); + + + return NULL; +} +EXPORT_SYMBOL_GPL(rpl_ip_tunnel_lookup); + #endif diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index 7ade6c1..90e838a 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -129,6 +129,47 @@ error: } EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads); +struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, + bool csum_help, + int gso_type_mask) +{ + int err; + + if (likely(!skb->encapsulation)) { + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } + + if (skb_is_gso(skb)) { + err = skb_unclone(skb, GFP_ATOMIC); + if (unlikely(err)) + goto error; + skb_shinfo(skb)->gso_type |= gso_type_mask; + return skb; + } + + /* If packet is not gso and we are resolving any partial checksum, + * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL + * on the outer header without confusing devices that implement + * NETIF_F_IP_CSUM with encapsulation. + */ + if (csum_help) + skb->encapsulation = 0; + + if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) { + err = skb_checksum_help(skb); + if (unlikely(err)) + goto error; + } else if (skb->ip_summed != CHECKSUM_PARTIAL) + skb->ip_summed = CHECKSUM_NONE; + + return skb; +error: + kfree_skb(skb); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(rpl_iptunnel_handle_offloads); + int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto, bool raw_proto, bool xnet) { From patchwork Sat May 19 00:49:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916680 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mhIYLvAu"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmgS3v0bz9s47 for ; Sat, 19 May 2018 10:51:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 51D9D9D1; Sat, 19 May 2018 00:50:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 2B17FBE1 for ; Sat, 19 May 2018 00:49:57 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f169.google.com (mail-pf0-f169.google.com [209.85.192.169]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A9CBC473 for ; Sat, 19 May 2018 00:49:56 +0000 (UTC) Received: by mail-pf0-f169.google.com with SMTP id j20-v6so4489374pff.10 for ; Fri, 18 May 2018 17:49:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3AhCPdXExstoJPOCSXgFhWRbkNt9zropDNLIUUxWUUY=; b=mhIYLvAurfS4DpP7SfMi/ui5nB9nUMKf0IskroewLly8o8uTiPxcsIqivclF6fI8W7 I0EueGYn+D0/Ps2WE5cJUdp5+ErI9GnYXmJsR8n3uya3To9kg5vPskcEui4vfkxKdAx0 GXelkBuSDNnviYvCY3Xvag66w2Rg8brWSDYzENYKLKG9/2jhOZvD36htaoaEtKqXoi3f V3L9cDwRZsaIRHD+YUak43qjpnnrvLIwvP3XmM7pjQ//1b/uaV+5uoox1FShTMI1duIL F0chKCcnYA2qrkybWC4X70ZxSCiZcABY9+lT6JgB38V1Ar1QEgHtct+7v9db0qxZCqfJ JY2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3AhCPdXExstoJPOCSXgFhWRbkNt9zropDNLIUUxWUUY=; b=Z377pY3KoAx0gAq+tjsWS069iy6sj/lHeQni08e97OU1bkRB0oSH3aKIpCGL677Wfg ejXaAka2gPqQWox5ymcr7VRgQ4BpaoW9Zix6ttYoTEQe06QDZvreAn0yTxb5n+b6+ZxQ obZdqeJFLiqr326dP0RcTo0VJXTzAoKIsKSuV/PFnCQf0qOnipvvWfU9va6WbL7D9Tza uJLLScCyOc8fSpMr9FFl5peKPFM5hRIXWHmm8IwrLCkU2MzKYKJS+w1znPvtij5ttEsO mKgkiuzb5hnan2l6tL2Z1gtM46c5QN2aKts2JqQrItytwwGTXvgsOljcUyHKekxLjRBE l/Zw== X-Gm-Message-State: ALKqPwd150Q4AsVF6XkBG+Gzvtowjn3cUyaEFER0a0PRv0wIFgX8dDLk 7JyyT6HR9zcoRCK6GSFmwmHi7g== X-Google-Smtp-Source: AB8JxZq7FqmziFgGYTG0F+LlI/87AW1D9Tn5M+AXexdhl9FwXE8OTFLa4RB8EB4/jJUz1iOJYW81Bw== X-Received: by 2002:a62:6756:: with SMTP id b83-v6mr11492925pfc.76.1526690996038; Fri, 18 May 2018 17:49:56 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:55 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:11 -0700 Message-Id: <1526690988-29912-4-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 03/40] gre: fix goto statement typo X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit e3d0328c76dde0b957f62f8c407b79f1d8fe3ef8 Author: William Tu Date: Tue Aug 22 17:04:05 2017 -0700 gre: fix goto statement typo Fix typo: pnet_tap_faied. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 3001f3f..3bd6e92 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1552,7 +1552,7 @@ int rpl_ipgre_init(void) err = register_pernet_device(&ipgre_tap_net_ops); if (err < 0) - goto pnet_tap_faied; + goto pnet_tap_failed; err = register_pernet_device(&erspan_net_ops); if (err < 0) @@ -1580,7 +1580,7 @@ pnet_ipgre_failed: unregister_pernet_device(&erspan_net_ops); pnet_erspan_failed: unregister_pernet_device(&ipgre_tap_net_ops); -pnet_tap_faied: +pnet_tap_failed: pr_err("Error while initializing GRE %d\n", err); return err; } From patchwork Sat May 19 00:49:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916681 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mjVuqV3+"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmgz6Mfmz9s4w for ; Sat, 19 May 2018 10:51:27 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 53B83CA0; Sat, 19 May 2018 00:50:03 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id C36EFBE6 for ; Sat, 19 May 2018 00:49:57 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f67.google.com (mail-pg0-f67.google.com [74.125.83.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 81A10473 for ; Sat, 19 May 2018 00:49:57 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id w3-v6so3969763pgv.12 for ; Fri, 18 May 2018 17:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4n0nesw0F3u/hOaK6QQCezt7Am7mNS4v8hfUTzSw1h0=; b=mjVuqV3+ZlDORjXHBHM8fXdcemubIw+EhrDvAOUjC0H+wkXd5NbawZPpYVZBKgxzCM GzP4+TPaUxJ5AQbQx6oVqfs8+OkNt66BSxLPxq5iA158LOYCHf2nUCeGglCwwzqzZz6B emG8p9ze1QeQ4Fem5236U/uK4tn0KBzLF4pVeBBXwGibn90sxpPODAWrUbp6sNyLdWyA EBAEwb3VS/FXH6GfiK5Ty5aWO8wMqtp1LLehfTlluwkkHutJCBNAF3b15AW9SMpPCZPM DT/pDSRGviZXOIHYobDUAFgIUNUDF4k3DAJSGZieMlNV35L0JkcjGvcqplKtXcJUQ0sG A2aQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4n0nesw0F3u/hOaK6QQCezt7Am7mNS4v8hfUTzSw1h0=; b=hFP0AIROYQ6AL6eba7uCcBmNgRtqQaVWDq/YdpiknlH1SP321hrBLUahSWye1PUOB+ mMzkPzEE9YJMP7uZWi6jeLRSAjf+0AlkUCXbwtI3uBTh0SnR1mF5zsrojbce+pfcM6iK WxdNV0T92RX0IQKAmHMmf6PtuZCP5c517rYyaKNZv6+p93pI6X3diN4NIttLucjarqlv TJEl5qsdr47bu1zuuV4fH92QnF83qKbed1d3wR/30LgBohSBiIGS8ZHst+vEJ1TFbQjd 9j4RRkr1MRnDLPuEKqZ/U7cfCM3ffNWdsQRIvJ/F15z3MNdnNvfZHK+NkYqpUbbp/EAX uJ2Q== X-Gm-Message-State: ALKqPweudnBNy4q1Hu9ZxBN/c+h67/EcgX/PWusNgMbBsKwCPkogAulQ eQAImqAz4mwdW4F58170jjYuPA== X-Google-Smtp-Source: AB8JxZrNfb2GJ7XBCVjzw4loij5JCDs0ZmEcCa4uLeJxXT04pGB/i0y5O3QIcIOd5nHJ5I4ho1IG5A== X-Received: by 2002:a62:d8c7:: with SMTP id e190-v6mr11406600pfg.161.1526690996873; Fri, 18 May 2018 17:49:56 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:56 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:12 -0700 Message-Id: <1526690988-29912-5-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 04/40] gre: refactor the gre_fb_xmit X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 862a03c35ed76c50a562f7406ad23315f7862642 Author: William Tu Date: Fri Aug 25 09:21:27 2017 -0700 gre: refactor the gre_fb_xmit The patch refactors the gre_fb_xmit function, by creating prepare_fb_xmit function for later ERSPAN collect_md mode patch. Signed-off-by: William Tu Signed-off-by: David S. Miller Only the prepare_fb_xmit() function is pulled in. Compatibility issues prevent the refactor of gre_fb_xmit() but we need the prepare_fb_xmit() function for the subsequent patch. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 3bd6e92..e30e428 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -488,6 +488,54 @@ static struct rtable *gre_get_rt(struct sk_buff *skb, return ip_route_output_key(net, fl); } +static struct rtable *prepare_fb_xmit(struct sk_buff *skb, + struct net_device *dev, + struct flowi4 *fl, + int tunnel_hlen) +{ + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct rtable *rt = NULL; + int min_headroom; + bool use_cache; + int err; + + tun_info = skb_tunnel_info(skb); + key = &tun_info->key; + use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); + + if (use_cache) + rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr); + if (!rt) { + rt = gre_get_rt(skb, dev, fl, key); + if (IS_ERR(rt)) + goto err_free_skb; + if (use_cache) + dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, + fl->saddr); + } + + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + + tunnel_hlen + sizeof(struct iphdr); + if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { + int head_delta = SKB_DATA_ALIGN(min_headroom - + skb_headroom(skb) + + 16); + err = pskb_expand_head(skb, max_t(int, head_delta, 0), + 0, GFP_ATOMIC); + if (unlikely(err)) + goto err_free_rt; + } + return rt; + +err_free_rt: + ip_rt_put(rt); +err_free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NULL; +} + netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb) { struct net_device *dev = skb->dev; From patchwork Sat May 19 00:49:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916683 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FjpOfW2h"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmhV4j2Dz9s4w for ; Sat, 19 May 2018 10:51:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6BA6BCB0; Sat, 19 May 2018 00:50:05 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 0162FBC1 for ; Sat, 19 May 2018 00:49:59 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 860DD473 for ; Sat, 19 May 2018 00:49:58 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id e9-v6so4501382pfi.4 for ; Fri, 18 May 2018 17:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=edeez9fy38gf9EZLZKIZcll5SBU3o48OpsQqTqCa8i0=; b=FjpOfW2hQZOLo6HsSQLckvD/MCMHneuJvN0XsvwGe5bD1CRKtN1TEdaSuAo+XB6Q+r nrH4b7DDcPa3DOwecFMa7917HNIdUP6+tvbRvIJhLOLtXzh0X1THlv72yN42KourHXRK aWu93MCROhJWiUMTKN6/Y7XsikXa9q4oNW0XMgkeOZwxf7obpn5eaLGKPJVTRL8vYD67 lobF4V6VQavijw53NWhOWVi5mK7ouG5Z9LqLxf0mDEeVwEcFus42+mhrfoGvvr4Y+VYC K7p4QAGXA0UYEjwvmkOXi4bsgr5NhNXXGjXoqKHR00WI1xMI0RtdwKlc3HFVYXLBp6zi KRRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=edeez9fy38gf9EZLZKIZcll5SBU3o48OpsQqTqCa8i0=; b=OFjyjIVP4TOG+EGwPoNizc0TTOu2hlTBqbbSbQFYsqul6hX1EJqQ+4NTf2JGEOwQYl YAHl2dOTMxMXu2oMgDwh39N1rnitgUUBwHvLaPmer+VMTknHd7OlA14EoXtXNcyfxO0U afHha8DyY1GxyBbAD2eMzH1GyLgmeCurHJNrljKO/HWH8qIPzxnwEoNtfmKa8GKV1jxk 0XtUXoeKmqoogg/XkWOV10qNH1yXZ709jqusYbXkAi/DnJ1EsxTkMVGpnOdUfUjR0o4d 4q6MCfFj1oBL73NbPpnTAgivOt+Yr+HbzztxKG2clcQDXhCiWWqBhbtbXWjufP7ogBHe QmIw== X-Gm-Message-State: ALKqPwdEZl+UcgV4BdHs9tytyOLwOqk+AJC56VtwB31nwwU0giCsV0IG WrSnMxzkpyTV4nm8z4LlZ23U+g== X-Google-Smtp-Source: AB8JxZqaAX/vOLcTgCUeyvvKUhp5NVvGkSWolT2DPiJ3CMqSaqH+mIW0gprAmQoB0DG0zSrTk3zDjQ== X-Received: by 2002:a62:5b02:: with SMTP id p2-v6mr11394980pfb.96.1526690997777; Fri, 18 May 2018 17:49:57 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:57 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:13 -0700 Message-Id: <1526690988-29912-6-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 05/40] compat/gre: add collect_md mode X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu commit 1a66a836da630cd70f3639208da549b549ce576b Author: William Tu Date: Fri Aug 25 09:21:28 2017 -0700 gre: add collect_md mode to ERSPAN tunnel Similar to gre, vxlan, geneve, ipip tunnels, allow ERSPAN tunnels to operate in 'collect metadata' mode. bpf_skb_[gs]et_tunnel_key() helpers can make use of it right away. OVS can use it as well in the future. Signed-off-by: William Tu Signed-off-by: David S. Miller With some adjustments for compatibility layer. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/include/net/ip_tunnels.h | 68 +++++++++++++++----------- datapath/linux/compat/ip_gre.c | 23 ++++++--- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 2685de7..ea3fb8d 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -74,14 +74,25 @@ void rpl_ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, #ifndef TUNNEL_CSUM -#define TUNNEL_CSUM __cpu_to_be16(0x01) -#define TUNNEL_ROUTING __cpu_to_be16(0x02) -#define TUNNEL_KEY __cpu_to_be16(0x04) -#define TUNNEL_SEQ __cpu_to_be16(0x08) -#define TUNNEL_STRICT __cpu_to_be16(0x10) -#define TUNNEL_REC __cpu_to_be16(0x20) -#define TUNNEL_VERSION __cpu_to_be16(0x40) -#define TUNNEL_NO_KEY __cpu_to_be16(0x80) +#define TUNNEL_CSUM __cpu_to_be16(0x01) +#define TUNNEL_ROUTING __cpu_to_be16(0x02) +#define TUNNEL_KEY __cpu_to_be16(0x04) +#define TUNNEL_SEQ __cpu_to_be16(0x08) +#define TUNNEL_STRICT __cpu_to_be16(0x10) +#define TUNNEL_REC __cpu_to_be16(0x20) +#define TUNNEL_VERSION __cpu_to_be16(0x40) +#define TUNNEL_NO_KEY __cpu_to_be16(0x80) +#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) +#define TUNNEL_OAM __cpu_to_be16(0x0200) +#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400) +#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800) +#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) +#define TUNNEL_NOCACHE __cpu_to_be16(0x2000) +#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) + +#undef TUNNEL_OPTIONS_PRESENT +#define TUNNEL_OPTIONS_PRESENT \ + (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT) struct tnl_ptk_info { __be16 flags; @@ -99,27 +110,6 @@ struct tnl_ptk_info { #define IP_TNL_HASH_BITS 7 #define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) -#ifndef TUNNEL_DONT_FRAGMENT -#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) -#endif - -#ifndef TUNNEL_OAM -#define TUNNEL_OAM __cpu_to_be16(0x0200) -#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400) -#endif - -#ifndef TUNNEL_GENEVE_OPT -#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800) -#endif - -#ifndef TUNNEL_VXLAN_OPT -#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) -#endif - -/* Older kernels defined TUNNEL_OPTIONS_PRESENT to GENEVE only */ -#undef TUNNEL_OPTIONS_PRESENT -#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT) - /* Keep error state on tunnel for 30 sec */ #define IPTUNNEL_ERR_TIMEO (30*HZ) @@ -242,6 +232,7 @@ static inline void ip_tunnel_key_init(struct ip_tunnel_key *key, #define ip_tunnel_collect_metadata() true #if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) +#undef TUNNEL_NOCACHE #define TUNNEL_NOCACHE 0 static inline bool @@ -419,6 +410,25 @@ static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) } } +static inline __be64 key32_to_tunnel_id(__be32 key) +{ +#ifdef __BIG_ENDIAN + return (__force __be64)key; +#else + return (__force __be64)((__force u64)key << 32); +#endif +} + +/* Returns the least-significant 32 bits of a __be64. */ +static inline __be32 tunnel_id_to_key32(__be64 tun_id) +{ +#ifdef __BIG_ENDIAN + return (__force __be32)tun_id; +#else + return (__force __be32)((__force u64)tun_id >> 32); +#endif +} + #define ip_tunnel_init rpl_ip_tunnel_init int rpl_ip_tunnel_init(struct net_device *dev); diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index e30e428..a5ec59c 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -93,6 +93,9 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, bool truncate); + /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) @@ -187,7 +190,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst *tun_dst = NULL; + struct metadata_dst tun_dst; struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; struct erspanhdr *ershdr; @@ -823,18 +826,17 @@ static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) return ret; /* ERSPAN should only have GRE sequence and key flag */ - flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); - flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); - if (flags != (GRE_SEQ | GRE_KEY)) + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (!data[IFLA_GRE_COLLECT_METADATA] && + flags != (GRE_SEQ | GRE_KEY)) return -EINVAL; /* ERSPAN Session ID only has 10-bit. Since we reuse * 32-bit key field as ID, check it's range. */ - if (data[IFLA_GRE_IKEY] && - (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) - return -EINVAL; - if (data[IFLA_GRE_OKEY] && (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) return -EINVAL; @@ -983,6 +985,11 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, struct ip_tunnel *tunnel = netdev_priv(dev); bool truncate = false; + if (tunnel->collect_md) { + erspan_fb_xmit(skb, dev, skb->protocol); + return NETDEV_TX_OK; + } + if (gre_handle_offloads(skb, false)) goto free_skb; From patchwork Sat May 19 00:49:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916684 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S2UUgkbn"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmhz21ncz9s4w for ; Sat, 19 May 2018 10:52:19 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5144FCDE; Sat, 19 May 2018 00:50:07 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DF8139D1 for ; Sat, 19 May 2018 00:49:59 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f66.google.com (mail-pg0-f66.google.com [74.125.83.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7192D6CE for ; Sat, 19 May 2018 00:49:59 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id n9-v6so3979487pgq.5 for ; Fri, 18 May 2018 17:49:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5ZYWYIQnLYcN5JRanLVr/Od++GuLKbBc+0VVprZvyv0=; b=S2UUgkbn0MfPrVuSUtxxJfDr49ZzAim/utq7jpEWuhl7Dvc6gGnSLOKeTVJGINKjyT /C2Jpm8KoDHoZkJPfrTQFBOrDOqN45n69GF4aJp5wOmDzHFH4lpHIBbg7/4dblRT8U3B rAZCqdNNMRy7oEukrOwm+jrqf8/vnfCbhZrsDrWF/dmpcxOe2JQCB8xPkPRjKnwODDXk Bdmn41WSivTC7Xxhh7YZOdPvdrtfuwvAyTO+pj4lRWWw5zFUs+XYJuB65mCLnc0lfM5J cjjxq6iyBbOwWCpuBERIAYdVBwwtqHr8gSe3M6JMJhSBeJyUO4wnySxl19FXD51l+Tqv elQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5ZYWYIQnLYcN5JRanLVr/Od++GuLKbBc+0VVprZvyv0=; b=V5aP1iyJDXpblkPf1dNz7p98OPG8kAv5LlFj6L5kDuax5A1/ha/jjd7+CD6WD2Pb4o 19tIB9VTFajACQgrvm/azWQTouCVt+aYjlmXhilwIkRsKbd9RAMXoDsvf0izYWKYR/zH Biv2/Y4rshiI+NbURJIew7QQ6ABH7LnffttCwhEPBfMTw8y8wWekxERNmmFnphOjKO+d k5xxWqrKwx9WAE1m73oVoPw1TeQ5N18agXtWIhLux6HY5RhJj/z0hPnbtmbk71H0hqpT 2CqRhYyEVa9x8x9WsLZEeUnpH9dv3PhnQhcJXGs7mSNq9MhMZBL3XFdmAq9s2eIspQ0U jrLQ== X-Gm-Message-State: ALKqPweg6g7odA2Vw3aKh/rYoo3afxxm7dbGLh0bmGdMDyXwlTVHoguU HxgK8VdCm1ewnKbVfNnDeIrILQ== X-Google-Smtp-Source: AB8JxZp2Kme4uanncMWiMNhWwdSjtMZ2Xyo7Q1c07iqwwAlFymwr17ABDhCyJXEmCk3Sy45RmFAyLA== X-Received: by 2002:a63:9f0a:: with SMTP id g10-v6mr9036431pge.39.1526690998732; Fri, 18 May 2018 17:49:58 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:58 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:14 -0700 Message-Id: <1526690988-29912-7-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 06/40] ip_gre: check packet length and mtu correctly in erspan tx X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit f192970de860d3ab90aa9e2a22853201a57bde78 Author: William Tu Date: Thu Oct 5 12:07:12 2017 -0700 ip_gre: check packet length and mtu correctly in erspan tx Similarly to early patch for erspan_xmit(), the ARPHDR_ETHER device is the length of the whole ether packet. So skb->len should subtract the dev->hard_header_len. Fixes: 1a66a836da63 ("gre: add collect_md mode to ERSPAN tunnel") Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Signed-off-by: William Tu Cc: Xin Long Cc: David Laight Reviewed-by: Xin Long Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index a5ec59c..77d430e 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -996,8 +996,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, if (skb_cow_head(skb, dev->needed_headroom)) goto free_skb; - if (skb->len > dev->mtu) { - pskb_trim(skb, dev->mtu); + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); truncate = true; } From patchwork Sat May 19 00:49:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916685 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EuNhwVt6"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmjc0clMz9s4w for ; Sat, 19 May 2018 10:52:52 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 45047C07; Sat, 19 May 2018 00:50:14 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id CB9FDC29 for ; Sat, 19 May 2018 00:50:00 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8CAA06A3 for ; Sat, 19 May 2018 00:50:00 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id w3-v6so3969800pgv.12 for ; Fri, 18 May 2018 17:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+4gwZ/YT8fTkXmnFJi/mh4xs6by5eXesmR5SjzufJb0=; b=EuNhwVt6/P+omE421uRBahVIIApT0JYs0ISNXj6W54UVKCQoCIAi5kzNgwZ6roFxZR qOlQsxKJ6aNUmXt0ibf1kRcnt8IwFl3ofb3JeZIYErvHApQS3GSYiE5i8fTXvNzv5Z5w x5xN0gEgKwhyd8PYCzompn1s7kv4Z+kbpqiIOhQ6dm1h3yQsJ4do8smTF+KoKmvD1rRH VdrOv0J9kdQKKo6+FXxmbq0mG3tS15t/hYaWcKRqpXoAOq9UOcvNHL3d3lrLRamtiC+5 0siaNXd7quMBVVjUU5YWEV7A/lfEEUJMYEPum87aN0utSIEPokfgzboZV2SFF1FJanlV KQMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+4gwZ/YT8fTkXmnFJi/mh4xs6by5eXesmR5SjzufJb0=; b=NtxeBFoqbxi42toO4xYFonbGopQUMz/NaC/m7BNW0VwSw3B/lBmPqy5FjwoWZ0j/px 3eYjIMgswgalgha6EXLEXq2NIXbkZwI+sLxR1U+fUx6x/evGMeZ/lzpsoWnt7TB/qFpB cAuI+fBSaRPQXH836/aE6gBcyIEGOtch2F3GUh20UMiHxCPLRB9fAZOOVqqYvGrhkvOf +0ICMzw7LwmjMHgG5p5maM0CWlfDm8yGoL5oTqMfIBJMqnjy1YFPbBtF4Yp99igr0z1B HSr+iHFJfS8aFpp3aNCEliED8m1an6ECVJ6EM9SEoDEf8UzrbpNhpfITJL6LRewsZdMv RzxQ== X-Gm-Message-State: ALKqPwerc0ZwgqeEb0A8J1iW02Zl00ZivqF6s+ojZMrDKJ7EvhjoOuZq wSrRm6w77rg3IhG5CZjWhkVCtw== X-Google-Smtp-Source: AB8JxZoSTgYBmthwLqXHCeKBZ37nmAPoEHZS4r3evyXvMiqKZ26QEGOQv+3AaFnNIwhHoRvM2Bz57w== X-Received: by 2002:a65:4ac8:: with SMTP id c8-v6mr3992525pgu.246.1526690999927; Fri, 18 May 2018 17:49:59 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:49:59 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:15 -0700 Message-Id: <1526690988-29912-8-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH V3 07/40] ip_gre: get key from session_id correctly in erspan_rcv X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Xin Long Upstream commit: commit 935a9749a36828af0e8be224a5cd4bc758112c34 Author: Xin Long Date: Sun Oct 1 22:00:53 2017 +0800 ip_gre: get key from session_id correctly in erspan_rcv erspan only uses the first 10 bits of session_id as the key to look up the tunnel. But in erspan_rcv, it missed 'session_id & ID_MASK' when getting the key from session_id. If any other flag is also set in session_id in a packet, it would fail to find the tunnel due to incorrect key in erspan_rcv. This patch is to add 'session_id & ID_MASK' there and also remove the unnecessary variable session_id. Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Signed-off-by: Xin Long Signed-off-by: David S. Miller Cc: Xin Long Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 1 - 1 file changed, 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 77d430e..1a8dc76 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -195,7 +195,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, struct ip_tunnel *tunnel; struct erspanhdr *ershdr; const struct iphdr *iph; - __be32 session_id; __be32 index; int len; From patchwork Sat May 19 00:49:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916690 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hYzlHl5v"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmkg4ljMz9s4w for ; Sat, 19 May 2018 10:53:47 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8C96EBBD; Sat, 19 May 2018 00:50:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E5F2CC9A for ; Sat, 19 May 2018 00:50:01 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A95F3473 for ; Sat, 19 May 2018 00:50:01 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id v7-v6so4003261pgs.0 for ; Fri, 18 May 2018 17:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DAP8s1FTQPQd2Sl1OV9NRPCXD6MxrYhzc5r6pMbggc8=; b=hYzlHl5vWU9IgBRMCwkriNCJQ0/0BDsj+cd2PEnN6CvOD5qD4ovuWU2HuzkcVvJnMd JVyySTNaw/BfaNTUFIvUvdFNdrpKQ/9LwbUjkLROHZ+T852TVDTg9uUafCkxN+0dF9I9 2y8caDNDQUWfxmCp9uEFIGjhAeuujHoKbdBsExYe69A6QQLg4lxDB47shuifEBlcjZnj 1Fpk2Xn4ML/+msM3Zd3nNdHKij0tJvn7qD5e/x/wl/sea5Q0AUEPhs4J5YsW/EWDET8J ghrW9TvKrttS1J610o6hd5gEpXjsH+6dNDj6V8+hG9eXFb9a76GNbiunrrblxlFNk3iq NFtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DAP8s1FTQPQd2Sl1OV9NRPCXD6MxrYhzc5r6pMbggc8=; b=hzF+oCkQolNkGzgNd18Mo4ARYLPkqg6cX1x8tvmoMkvMfAHiyAgKLvwQoozKTUlskb OBybd/fuTfy4SV4aJzE+wPoUmj3yKdEzenA7FoaOyunHtAVcxLEfujI7K/xbByFBRXj3 LmAUI8/gOJG4cK2XHTfLiRpg4i1rQ0YbBL2wP0IIzLzz/Op6q0L9gBeDTjYiMSXbOJWP uwCpj9XtDWVe9PdWLwoEUy/3B+I7B2IfNCuykHkKHBnBqTc6xnnt+WzahW6HmWdIUkBR vrQ/RzSoL86gLnS0hX2V8LMRBunSRYHIirzA+o2tNFFXrXRYwpCD6ElyI+p1WlhYVuYj V2Ow== X-Gm-Message-State: ALKqPwf5PmOX+wKT1CNwCrZ9eX0RK6hiq5Wo5Yxa9vT3xTBx6QSQRnSG BX80V/fEspPgldCiAqBosMB8nQ== X-Google-Smtp-Source: AB8JxZpx0AGRVCXz2syM+vPYw5VCmSILLNZaV7gyzHZ0hs9/+GeATnrEIgCjGOMwf8Tph4LikNNPyQ== X-Received: by 2002:a62:9c0d:: with SMTP id f13-v6mr11304563pfe.15.1526691000989; Fri, 18 May 2018 17:50:00 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.49.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:00 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:16 -0700 Message-Id: <1526690988-29912-9-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH V3 08/40] ip_gre: set tunnel hlen properly in erspan_tunnel_init X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Xin Long Upstream commit: commit c122fda271717f4fc618e0a31e833941fd5f1efd Author: Xin Long Date: Sun Oct 1 22:00:55 2017 +0800 ip_gre: set tunnel hlen properly in erspan_tunnel_init According to __gre_tunnel_init, tunnel->hlen should be set as the headers' length between inner packet and outer iphdr. It would be used especially to calculate a proper mtu when updating mtu in tnl_update_pmtu. Now without setting it, a bigger mtu value than expected would be updated, which hurts performance a lot. This patch is to fix it by setting tunnel->hlen with: tunnel->tun_hlen + tunnel->encap_hlen + sizeof(struct erspanhdr) Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Signed-off-by: Xin Long Signed-off-by: David S. Miller Cc: Xin Long Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 1a8dc76..70c6a9f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1044,7 +1044,9 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; - t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr); + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + + sizeof(struct erspanhdr); + t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; dev->mtu = ETH_DATA_LEN - t_hlen - 4; From patchwork Sat May 19 00:49:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916691 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HlTbbZtS"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmlB19H0z9s4w for ; Sat, 19 May 2018 10:54:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4AA8FD58; Sat, 19 May 2018 00:50:18 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 869CCCB2 for ; Sat, 19 May 2018 00:50:03 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7821C6CE for ; Sat, 19 May 2018 00:50:02 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id a22-v6so4494522pfn.6 for ; Fri, 18 May 2018 17:50:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yENfHRcWPB6V05ndWQ5og4kMvSKNSF6aw52F6qH+O4s=; b=HlTbbZtSRqp/FI6IiyzswHkCBeENQ6QMb9PQTIalVU0c8wPX71BwqmQUZrLrt4SPcC LM5rDEVuhe3fckTcgUreRqL0FbCriGu4V5vLWlX3DZNc1jPFJ4xOtTKP4yfKtkJuDImY Jml7WDIAuafCevjpSnRETUL6evhvIEE7kuHroCBOObHLeoYTMD8WhsLr6SY8tS0HAtqN 6LdtmzIEhBtz2GxmVsSGoEU8cimaxTZ7XdO19CTW7llc2cmtAOuSNY+mcFEIJtY4V4RY gLjtTNmh0oH095Mf456RBYmojDqn2uVANtnxdwJXRjFi2kPbWEj8FGfEQBNE4mFOvJtM FZ8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yENfHRcWPB6V05ndWQ5og4kMvSKNSF6aw52F6qH+O4s=; b=bO42hBVgSRx44woB9tjNDrZ5SDCAKGqB3PgToo8VCQXbUcL+Y9dERaR69EyrbdAPNY irouRApVXKcXX5S4tMGcCvcGtoiKu5S52mDfvB8JAorayFIFqzLKPKb0L9bZaEHLShAf vfLaJpePJVngcJ3oHQ9xcv/+iWJlYAFAlwXIj4oinGphKWUL8oLbx3gMMDgYs9hDg6Jm d/ky+P1+O8QsrS/ijlGx27rxRsA405napneh6i9w/cFYjRqD1F65jnimyxU2XoKcTGZZ Ae4s5ew8LHxMohYOc1STRtZJVnwHCj1EQBwmYd6cCVXv1qaurWeG96gMqdClTycfJd1Z EeaQ== X-Gm-Message-State: ALKqPwcTLvSp8Z8R3N7LnsBjWAKnWP3anJ2GBtJQRgiGy8d2X+gY4qq4 KF/Ie8f4PdNMKpMFt2zAL2SrYg== X-Google-Smtp-Source: AB8JxZpbjxPrQwDfYujqYbWB1VLFitiGj4ReFc+5eHIoDFKgs+454/MjqHDVwiT02JZaSFvHgjXK8Q== X-Received: by 2002:a63:731b:: with SMTP id o27-v6mr7608pgc.132.1526691001844; Fri, 18 May 2018 17:50:01 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:01 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:17 -0700 Message-Id: <1526690988-29912-10-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH V3 09/40] ip_gre: erspan device should keep dst X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Xin Long Upstream commit: commit c84bed440e4e11a973e8c0254d0dfaccfca41fb0 Author: Xin Long Date: Sun Oct 1 22:00:56 2017 +0800 ip_gre: erspan device should keep dst The patch 'ip_gre: ipgre_tap device should keep dst' fixed the issue ipgre_tap dev mtu couldn't be updated in tx path. The same fix is needed for erspan as well. Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Signed-off-by: Xin Long Signed-off-by: David S. Miller Cc: Xin Long Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 1 + 1 file changed, 1 insertion(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 70c6a9f..19e78af 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1053,6 +1053,7 @@ static int erspan_tunnel_init(struct net_device *dev) dev->features |= GRE_FEATURES; dev->hw_features |= GRE_FEATURES; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); return ip_tunnel_init(dev); } From patchwork Sat May 19 00:49:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916692 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="WV/OoWJB"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmlm2ntpz9s4w for ; Sat, 19 May 2018 10:54:44 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 75E5ACE8; Sat, 19 May 2018 00:50:19 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DD1E1CAB for ; Sat, 19 May 2018 00:50:03 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f66.google.com (mail-pg0-f66.google.com [74.125.83.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 74AF76A3 for ; Sat, 19 May 2018 00:50:03 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id l2-v6so3977234pgc.7 for ; Fri, 18 May 2018 17:50:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=babftoUnK0pk26h1AJsGLjEqIvzFlZ3FZ7vywR6MyU0=; b=WV/OoWJB9pgamHdXaYEP4shxnIbRSAGu61RIZf86ovAHsYJ8t3Zd456YhkA7xwrWpM zzl48psYxYBPMRBA4ooREf9to28a9prq3AwBlaq1n4WoJbRB1lXjGOEsbVP6GBht3dj1 xACf8qKXWt7K4qzT2H+BSBFl592s/jU/mVB/mrVf/M2VDexsg2a7iXe6gN1hpL1Njhll YlFPqRYwFcIhw3mt3Fw492kyrCp1XuZ/K3u1YgSzkwNlcSJuQEDodYhC5Ie9BVAWg1zx aqrvtkr3DMiKSUe6FFdYRwNMQ47Q6WTccQsKBC2M2Po92pVMCkk2uovDxLXtkqrwMt/N /t8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=babftoUnK0pk26h1AJsGLjEqIvzFlZ3FZ7vywR6MyU0=; b=gHfFcTL8KFBMZIsC9E2H/zI7jqHsjXjZsqdbiZN5HPU7+2TuBzuXiystU+8LbGikWM UO3soQtXJeZpG/6OMlP7FS6bz47CjPUU9UqAkjIa5VnQYPjuoIQTH0Ggr0P9sR4+4Xkl ZMnEyUSnBTqqhDqjbvhzE6RLlclp+odyyCz7YgUQsx0PxZGpr5ezN3R7N7kA6y3/uO72 FDQ7uMsH5Qiu7KJOryt84OejkF0cIRlnGqRJZlIVclqPK5jUkFyW8wQBNK/8v/fir9u5 KV6lVVwoeZ05Xy2kq0VKWTV0yuE8imWUmLBdp+QBTvvVXFicNrXeNO5AAfi908iwKSrM H9sg== X-Gm-Message-State: ALKqPwe/UXEBoejXspl+eutp+/II8VIBoZ+JQtw/1JR/OyQComdtypjj hpw4s2iEdPJpfGOv3gRBYDVY2Q== X-Google-Smtp-Source: AB8JxZo/y5xKibmHjNMrij3AWl1t9/WkH3OrPbTNodkue6SmZZBfIHQwJMPO7b4lZFQvboTnc/m9ng== X-Received: by 2002:a62:b909:: with SMTP id z9-v6mr11483447pfe.254.1526691002680; Fri, 18 May 2018 17:50:02 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:02 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:18 -0700 Message-Id: <1526690988-29912-11-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 10/40] ip_gre: Refactor the erpsan tunnel code. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit a3222dc95ca751cdc5f6ac3c9b092b160b73ed9f Author: William Tu Date: Thu Nov 30 11:51:27 2017 -0800 ip_gre: Refector the erpsan tunnel code. Move two erspan functions to header file, erspan.h, so ipv6 erspan implementation can use it. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/include/net/erspan.h | 51 +++++++++++++++++++++++++++ datapath/linux/compat/ip_gre.c | 55 +++--------------------------- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h index 6c5d3a7..b4f13e6 100644 --- a/datapath/linux/compat/include/net/erspan.h +++ b/datapath/linux/compat/include/net/erspan.h @@ -59,6 +59,57 @@ struct erspanhdr { struct erspan_metadata md; }; +static inline u8 tos_to_cos(u8 tos) +{ + u8 dscp, cos; + + dscp = tos >> 2; + cos = dscp >> 3; + return cos; +} + +static inline void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = eth_hdr(skb); + enum erspan_encap_type enc_type; + struct erspanhdr *ershdr; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u8 tos; + + tos = is_ipv4 ? ip_hdr(skb)->tos : + (ipv6_hdr(skb)->priority << 4) + + (ipv6_hdr(skb)->flow_lbl[0] >> 4); + + enc_type = ERSPAN_ENCAP_NOVLAN; + + /* If mirrored packet has vlan tag, extract tci and + * perserve vlan header in the mirrored frame. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + enc_type = ERSPAN_ENCAP_INFRAME; + } + + skb_push(skb, sizeof(*ershdr)); + ershdr = (struct erspanhdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr)); + + ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION << VER_OFFSET)); + ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | + (enc_type << EN_OFFSET & EN_MASK) | + ((truncate << T_OFFSET) & T_MASK)); + ershdr->md.index = htonl(index & INDEX_MASK); +} + #endif #else #include_next diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 19e78af..7160e37 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -66,6 +66,9 @@ static int gre_tap_net_id __read_mostly; static int ipgre_net_id __read_mostly; static unsigned int erspan_net_id __read_mostly; +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, + bool truncate, bool is_ipv4); static struct rtnl_link_ops ipgre_link_ops __read_mostly; @@ -93,9 +96,6 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } -static void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, bool truncate); - /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) @@ -932,52 +932,6 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline u8 tos_to_cos(u8 tos) -{ - u8 dscp, cos; - - dscp = tos >> 2; - cos = dscp >> 3; - return cos; -} - -static void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, bool truncate) -{ - struct iphdr *iphdr = ip_hdr(skb); - struct ethhdr *eth = eth_hdr(skb); - enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; - struct qtag_prefix { - __be16 eth_type; - __be16 tci; - } *qp; - u16 vlan_tci = 0; - - enc_type = ERSPAN_ENCAP_NOVLAN; - - /* If mirrored packet has vlan tag, extract tci and - * perserve vlan header in the mirrored frame. - */ - if (eth->h_proto == htons(ETH_P_8021Q)) { - qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); - vlan_tci = ntohs(qp->tci); - enc_type = ERSPAN_ENCAP_INFRAME; - } - - skb_push(skb, sizeof(*ershdr)); - ershdr = (struct erspanhdr *)skb->data; - memset(ershdr, 0, sizeof(*ershdr)); - - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION << VER_OFFSET)); - ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) | - (enc_type << EN_OFFSET & EN_MASK) | - ((truncate << T_OFFSET) & T_MASK)); - ershdr->md.index = htonl(index & INDEX_MASK); -} - static netdev_tx_t erspan_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1001,7 +955,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, } /* Push ERSPAN header */ - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate); + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + truncate, true); tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); return NETDEV_TX_OK; From patchwork Sat May 19 00:49:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916693 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mM4in5vC"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmmK0NkXz9s4w for ; Sat, 19 May 2018 10:55:12 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0169CD65; Sat, 19 May 2018 00:50:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8C6EDCB3 for ; Sat, 19 May 2018 00:50:04 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 4005E674 for ; Sat, 19 May 2018 00:50:04 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id v24-v6so5504110plo.3 for ; Fri, 18 May 2018 17:50:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=VZz/zuNPtgeUnXbCsL0xG7uI3C3TsChxgcO2OJIDHk0=; b=mM4in5vCL77pc4lE9acpd07VEhjTt70b0+EHm10kvMozLdQMobarlQuHKv4xx/qRb2 HLSHuM2Viy3asAXnw1TN3DvAinGIDxVfEyohFEngkkH31Hs9vbx45QWRrO1AMPwKK830 /LeE3iqi0ztbO6Xi0kKk5zv0VZs44GC065mtrIdjnmtFj0AAtPtBvVsQ4rCPMvUJZqQH faGtHgtHcYlU7kA0pjQSYqW9j8TMLRWa1tgcmdVFZYMOOQ6gYu3FbhcHUJo1nN1Zoozr u1pl7C19fD8IdDKEaZrxWXrbajR0Ht+EFqeQyjb+Fj8ivHSE8eAbjcU55SFnY+2bmTDW M5KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=VZz/zuNPtgeUnXbCsL0xG7uI3C3TsChxgcO2OJIDHk0=; b=IFn2+e1YCP4VjdgD5jkVJVnEI5cxAUfjVN3UGUTfQ5CNUI6zKAKRmInLiMId/EjCSQ M2yqJGQ2rSp4V8oX8DQAvhV8BF0q/JGwjwBdmaJiGU/YQ2UHkHWUzRPWLKXyMPtSit/o kf/kv6F0nKy27n6aPGMT6NlisFCRDMmsUOdnhqgF5SqSNGhVdAsAxco53ichRUoV/jh2 VoudLfoaejX8nZvv1w30tCNRYze8TmFSyjrA+IC2xq6ZryIn1E5USLVd9yb5yZEWS+Pi ahfv5qbWao9RyFoIFHV8zsDo8jxUpxMWAItpHlF2Spy6qSqKgdp/sSTtto/HOFnJXvBU TdXg== X-Gm-Message-State: ALKqPwda05w2zPIj09Y/DPSleGYAcklBIXSpV6arXq74XFT3LULvltV3 Ov4YhsETsqH5TygVjCJb7Jl/VA== X-Google-Smtp-Source: AB8JxZr3LTdaIzBlULFTz3LtTCng8xdq7JATr/EbRH6qBecQxFiE9wfnWtCBICNl0RZBmd602QOqzA== X-Received: by 2002:a17:902:205:: with SMTP id 5-v6mr8048913plc.301.1526691003593; Fri, 18 May 2018 17:50:03 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:03 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:19 -0700 Message-Id: <1526690988-29912-12-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 11/40] compat/erspan: refactor existing erspan code X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 1d7e2ed22f8d9171fa8b629754022f22115b3f03 Author: William Tu Date: Wed Dec 13 16:38:55 2017 -0800 net: erspan: refactor existing erspan code The patch refactors the existing erspan implementation in order to support erspan version 2, which has additional metadata. So, in stead of having one 'struct erspanhdr' holding erspan version 1, breaks it into 'struct erspan_base_hdr' and 'struct erspan_metadata'. Signed-off-by: William Tu Signed-off-by: David S. Miller Partial of the upstream commit. While doing backports it is pretty much impossible to fully reconstitute all upstream commits but we're doing our best. Other parts of this commit are introduced in the upcoming monster patch for ip6 gre support. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 7160e37..dbe86c4 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -190,23 +190,26 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst; + struct metadata_dst tun_dst = NULL; + struct erspan_base_hdr *ershdr; + struct erspan_metadata *pkt_md; struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; - struct erspanhdr *ershdr; const struct iphdr *iph; - __be32 index; + int ver; int len; itn = net_generic(net, erspan_net_id); iph = ip_hdr(skb); len = gre_hdr_len + sizeof(*ershdr); + /* Check based hdr len */ if (unlikely(!pskb_may_pull(skb, len))) return -ENOMEM; iph = ip_hdr(skb); - ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len); + ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); + ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; /* The original GRE header does not have key field, * Use ERSPAN 10-bit session ID as key. @@ -218,8 +221,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, iph->saddr, iph->daddr, 0); if (tunnel) { + len = gre_hdr_len + erspan_hdr_len(ver); + if (unlikely(!pskb_may_pull(skb, len))) + return -ENOMEM; + if (__iptunnel_pull_header(skb, - gre_hdr_len + sizeof(*ershdr), + len, htons(ETH_P_TEB), false, false) < 0) goto drop; @@ -1000,7 +1007,7 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + - sizeof(struct erspanhdr); + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; From patchwork Sat May 19 00:49:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916694 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="sJELgwtz"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmmr4GqYz9s4w for ; Sat, 19 May 2018 10:55:40 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 36E8DD70; Sat, 19 May 2018 00:50:22 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id F2B21BD0 for ; Sat, 19 May 2018 00:50:05 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 80DF46CE for ; Sat, 19 May 2018 00:50:05 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id az12-v6so5496139plb.8 for ; Fri, 18 May 2018 17:50:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ch/Ijbyju0qXNruIlO9+hqUVEfO2KACK90ZRNPjX/x8=; b=sJELgwtz7X8+0HyouV389K7OkknmxpFfMtPs1bukLg1SaxLRa0qVl/NnBtuLCaGPZx 6eoBhhiDe6rAREDHZlbFwRWZsbEdLqTaMSRSZpqMLUrynHEpF1pHLP41BkdSKNkNVfui OUMTnUzur+8wkuUoLTxrjKGB7WP/VfFZjlZOcggIrjiPRuU3mymzDuHEQEma7ElYz/do NZJpfSVxQy66N/DQRJ8Rm8thlkLFOdvRPnKmkQvcvIvhUI38ch8+Rc33YwShZ0Jo6Q6F 6x2G5zLszcEqCoiU4ol11fMlnaZHQ3hCg/chgL8RDS5PDyeBdZ8YAX7ZkNJOdaTnjLji /MkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ch/Ijbyju0qXNruIlO9+hqUVEfO2KACK90ZRNPjX/x8=; b=NGSs1jZsoCEhVuD1q6UGJtaRsrz8W99phxe9+P2phyrPujjam6VraQLl1MUpE6FZ9G BcxR4RK0RaoC6sH5k2FWYh8gK9TATJnger3Gy+xXvKSpUgujWuMkMCZkckGRCOmPiFrH QsB5UwM3I7Je08bDV8doy6Tn5dwg2vyLVvVHEhVC7HmSkr1L96qb9FRry1m8Ba7xt3+p 0MwZcLOCI0Rc93cPCE/qSqL+pRVge8aavD50EUG6GT6p5j8Gzx6Rsx01aMr0iH4yN2Hc A4EcwFM+Km7iIQ/XOe3wl7R4M5ffgLlWfGTS5y2+ZOvuNT3ZunCNnTofEjW8bJcDIyT8 HG4A== X-Gm-Message-State: ALKqPwcD6pSRVJeHxvmJgkfTaaSjdpQqv9j+MBePtYlucjfLeMZjhaUr FI4dUrls6ZVmQnYX+GMkidHg0g== X-Google-Smtp-Source: AB8JxZqf7Bo+co4o69Jxx8OXLRq4XobT3AVflLp7K6VIVTqCtvw9Wt/EmYkod9qQXcXUoYUbQUZDIQ== X-Received: by 2002:a17:902:9686:: with SMTP id n6-v6mr11338795plp.136.1526691004524; Fri, 18 May 2018 17:50:04 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:03 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:20 -0700 Message-Id: <1526690988-29912-13-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Haishuang Yan Subject: [ovs-dev] [PATCH V3 12/40] ip_gre: fix wrong return value of erspan_rcv X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Haishuang Yan Upstream commit: commit c05fad5713b81b049ec6ac4eb2d304030b1efdce Author: Haishuang Yan Date: Fri Dec 15 10:46:16 2017 +0800 ip_gre: fix wrong return value of erspan_rcv If pskb_may_pull return failed, return PACKET_REJECT instead of -ENOMEM. Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Cc: William Tu Signed-off-by: Haishuang Yan Acked-by: William Tu Signed-off-by: David S. Miller Cc: Haishuang Yan Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index dbe86c4..c7912cf 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -223,7 +223,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, if (tunnel) { len = gre_hdr_len + erspan_hdr_len(ver); if (unlikely(!pskb_may_pull(skb, len))) - return -ENOMEM; + return PACKET_REJECT; if (__iptunnel_pull_header(skb, len, From patchwork Sat May 19 00:49:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916695 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bBCUuzuw"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmnP069cz9s4w for ; Sat, 19 May 2018 10:56:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 17177C64; Sat, 19 May 2018 00:50:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 3FAC9C22 for ; Sat, 19 May 2018 00:50:06 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f68.google.com (mail-pg0-f68.google.com [74.125.83.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 047866CE for ; Sat, 19 May 2018 00:50:05 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id c22-v6so3313643pgn.11 for ; Fri, 18 May 2018 17:50:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WSq9UNQii/GCudQpDqunj6VsmutUNUv34agFnRFVc2I=; b=bBCUuzuw9mTcjxAi8kMxymZaDQG4pWWY5yocIKkCBmyKSahk3+KinSRUWh28hina0A 2CUKJEV9tfkKgJ25ktKE+bEmtzG6yzLqB6ZcKAwqAbAd3tT010qOOfZ/oLrxdu6AgcDZ s9xn+ef9R/gPBQTwk0ZbRWmJMCsHfDGFboaT5CZOioFn0rmVdGotgJ6Jwy5jpy1b1TIe HVSEK1DcLQ7U/rGO+/RNHlChXgYIk/elgmb9X3dlpt88CISZNGI3aJJGlShafe7rjr48 jXP+K0OzDk32DmL+rw//6xTgSJWTye/6NtGEQu3u05ddo9q7orK20oOSzKW7MVVMPqcX VWRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WSq9UNQii/GCudQpDqunj6VsmutUNUv34agFnRFVc2I=; b=VvrWFJ+oYjXjYMwtjCSWl/XCwJFDc+VZ9kcwcsuFg94I+ABwLbkrvhPuZxdqmeuPbL 4xCIL68x/kN18ZFYE8Gq4iqlogHO7jyiqiIql+PMYhdu08m4OeDteQd8tm71rTvaWo1k ewzNTi+YzuuIE1sLRJIFi8G/RBHozGN486O5Gx7U43lkqjfaYgVw+mZN0KsbWtwPFiIf Ag8Dv5VZO9XTYtDtfY/S68cciajITwICPWOEbWVi8/LpPn009Q+g+5THOig2vBCRU7aM 2JjM/wmuZjVPa/whAPC73EpIOzAMf2DvMsF34OZVsiXJax5gcpccdTPMBiRGApPFwHJR UFiQ== X-Gm-Message-State: ALKqPwfd5dCF5ON72cnWs70k2WKtuvi1KH7dq555TPTtAaXpgqNQnCsS +AI9r8UbPPqYEHTDqBMjK83vmw== X-Google-Smtp-Source: AB8JxZp00+ShIFxfHKh8JUQsIw79c9MwwnnLQd6T759Lw0XHEKjHF4BXQIrC8uWSv7xaPcajbMEMNg== X-Received: by 2002:a63:ac44:: with SMTP id z4-v6mr243267pgn.291.1526691005311; Fri, 18 May 2018 17:50:05 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:04 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:21 -0700 Message-Id: <1526690988-29912-14-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 13/40] ip_gre: erspan: reload pointer after pskb_may_pull X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d91e8db5b629a3c8c81db4dc317a66c7b5591821 Author: William Tu Date: Fri Dec 15 14:27:44 2017 -0800 net: erspan: reload pointer after pskb_may_pull pskb_may_pull() can change skb->data, so we need to re-load pkt_md and ershdr at the right place. Fixes: 94d7d8f29287 ("ip6_gre: add erspan v2 support") Fixes: f551c91de262 ("net: erspan: introduce erspan v2 for ip_gre") Signed-off-by: William Tu Cc: Haishuang Yan Signed-off-by: David S. Miller Only the ip_gre portion of the upstream commit. The ipv6 portion is pulled in with later patch in series. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index c7912cf..028586c 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -225,6 +225,9 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, if (unlikely(!pskb_may_pull(skb, len))) return PACKET_REJECT; + ershdr = (struct erspan_base_hdr *)skb->data; + pkt_md = (struct erspan_metadata *)(ershdr + 1); + if (__iptunnel_pull_header(skb, len, htons(ETH_P_TEB), From patchwork Sat May 19 00:49:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916696 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gHQL35lJ"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmnx3PkHz9s4w for ; Sat, 19 May 2018 10:56:37 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 99E96D54; Sat, 19 May 2018 00:50:25 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 11BE9CD8 for ; Sat, 19 May 2018 00:50:07 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com [209.85.160.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id C35F6473 for ; Sat, 19 May 2018 00:50:06 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id az12-v6so5496156plb.8 for ; Fri, 18 May 2018 17:50:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=kquidjQ5Vnu6ceI5R0QyNVt1ojyw0m3pIIJCds7JAoQ=; b=gHQL35lJ2PqacDCkSfrMv5Qf35xskWHOgaqvYyNoZ6x9lXNAdCDpSwocXBp6z2O8/c FCbfa36C6xgqHpHG+vNwV/10dZRRmEtB/8+T5di0MNcO8Cnn0+VCYmAlXXfbBVVsYKY3 UqqVQgqZ/xhP8elgnuBZaE0U1KA3O1XV3x7Dr2/BecyCsob2YnD/2/i+mn8HyjkYbt4p ZIf2QJgccot6gxmq0DEUrvSsTpS23uyr+9LpB/xBRxZRl8M6EK4CScUgKZCiyd+Sdxeq bMC0e74R15y7bPAMz/0debFhu+GsZZoj4wLcqEu+/HjC7EkpNlki013mCIPPlPFRPukY QtTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=kquidjQ5Vnu6ceI5R0QyNVt1ojyw0m3pIIJCds7JAoQ=; b=krmJHDjNf88BFXTTBYVTFLHnVlKZi5t7oKj8ZrA5xymTafyZrplVA4h3zPSOCKk+PA 1N3B5z7/Rn0FTF9ksMA4tlgQMfRDFg3tAxklK6n75Owgac498W99+QMniaOUWOE2m6eT d8MD8F/HxS4tUEDGcP1bwPhZsAmTOkbm/xL1jWFJhxvurKVMro1SzkdeTxeGOqhBYK2h lvYnnkPHHdZ9LL1yHX66uU0PAWmRSeh9k1og4xX1FW5Di6UNBJtFyGDSBobJQAAu5zUU MxVHvdkEDCvBATGEfuAPX0cxR9dsB4aLCHEFwJoSdaIZXyQInNUMJyCq8oZ3GPRkrsKt ijlQ== X-Gm-Message-State: ALKqPwc6s30We4UtMM31sCvLr5suiJhGF+JZBw7Le/CQzJYtALfIW2rv l5ib0Nf7uCxEGcaTv6o/iPk+mg== X-Google-Smtp-Source: AB8JxZrnpC/qRqWzPYxB2GftUnas5E7sOe1Ver/5xn8QWbQn0ti3My/eVYMdoOLsLiBbuNN/8joFSA== X-Received: by 2002:a17:902:8:: with SMTP id 8-v6mr11351065pla.287.1526691006152; Fri, 18 May 2018 17:50:06 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:05 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:22 -0700 Message-Id: <1526690988-29912-15-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH V3 14/40] ip_gre: remove the incorrect mtu limit for ipgre tap X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Xin Long Upstream commit: commit cfddd4c33c254954927942599d299b3865743146 Author: Xin Long Date: Mon Dec 18 14:24:35 2017 +0800 ip_gre: remove the incorrect mtu limit for ipgre tap ipgre tap driver calls ether_setup(), after commit 61e84623ace3 ("net: centralize net_device min/max MTU checking"), the range of mtu is [min_mtu, max_mtu], which is [68, 1500] by default. It causes the dev mtu of the ipgre tap device to not be greater than 1500, this limit value is not correct for ipgre tap device. Besides, it's .change_mtu already does the right check. So this patch is just to set max_mtu as 0, and leave the check to it's .change_mtu. Fixes: 61e84623ace3 ("net: centralize net_device min/max MTU checking") Reported-by: Jianlin Shi Signed-off-by: Xin Long Signed-off-by: David S. Miller Cc: Xin Long Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 028586c..f849971 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -367,6 +367,7 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) return 0; + goto drop; } if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) @@ -390,7 +391,6 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *__tpi) if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD) return 0; - drop: kfree_skb(skb); @@ -1182,6 +1182,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); + dev->max_mtu = 0; dev->netdev_ops = &gre_tap_netdev_ops; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ip_tunnel_setup(dev, gre_tap_net_id); From patchwork Sat May 19 00:49:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916697 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="L7evgsoi"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmpW0cnwz9s4w for ; Sat, 19 May 2018 10:57:07 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1EF16D96; Sat, 19 May 2018 00:50:27 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 357D1CEE for ; Sat, 19 May 2018 00:50:08 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f68.google.com (mail-pl0-f68.google.com [209.85.160.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 00B186D6 for ; Sat, 19 May 2018 00:50:07 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id bi12-v6so5480993plb.12 for ; Fri, 18 May 2018 17:50:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HZK7C8YNQRG2Iqi/YKxcnbsTb2OFcwVj0I4V6oqEb7s=; b=L7evgsoiVvJ0mszl9ujUTyC0DlNovdzAmXVR3TDj9wlan94D6DD6RXPlDrsx9u2zOD 1dTU2i+7UXxp5uvFEs8nxPQAILQ8HPG5lDqBu/FjT7XSqEvbVaW0S7iuYkbAQDdYfchF uQ6fvDd/tYENDWfEidmPwXuXYewuH5v4uiIQUnTYlHVMW5lKPBT+drPt+KAQLEOYw1MH POMhmBKUpLD42P8tKwMadaYpBI/T+XY8gj0eMOshbHG2rY5MF+mQMGXXY1gRe0Ap9zO2 cB1/+bA9CqLlYn5DggcNvsr95isNMXkX7Z1UL7v3qYQycMHy58Z4dlKZW6MGMdv8FwCi WN7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HZK7C8YNQRG2Iqi/YKxcnbsTb2OFcwVj0I4V6oqEb7s=; b=CV82Wa6/zG7LlEGzyWoxhXuXnnnTikTqeSI3OfI1m05diGJM0sKWb0j74G9yF0Iu0L jHShl5WM5QKnUhAdu9xsUQZSkX4KOFFopLxLDopEMi47TRGvYPfBqIXG39VxiTfjdz83 I041q3pn9n8HnqQTaIcLR35JDTLwOjBFfnawFaTnGzm6poeYYvmQ+ajLq/YcwQhoKZ7w r4pbCJRrsn1iORUSEOj+njGFfeMLEa0TW6P0naH9DltcHFHXcJUNPOutLuM462yfgQgJ BsbkuFJeJs3r/SD/Cabx7iMADCMOtYL593v0ef//n0UBwxidj0yAVWgEuum9eUvxxrIo lJ7A== X-Gm-Message-State: ALKqPwc1vkYeZd06XPL8Rp13fyzV57uraRHiK5Sq7eVYX4pfX3+XgYm8 z191O2j25nTtyeQPLm5wbRhOkQ== X-Google-Smtp-Source: AB8JxZoCHxKk9aQrH7bFIYhHRo0GxsPcOw8pc3C9iJ1HpKznfoSc91vEsqUUZt+NTzwPk5UU0KebSA== X-Received: by 2002:a17:902:8bc5:: with SMTP id r5-v6mr11736299plo.182.1526691007235; Fri, 18 May 2018 17:50:07 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:06 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:23 -0700 Message-Id: <1526690988-29912-16-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 15/40] compat: Move function to header X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org tnl_flags_to_gre_flags is also needed in both ip_gre.c and gre.c on some kernels. Move it from ip_gre.c to the common header. Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/include/net/gre.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index ead86f6..e2473f2 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -30,6 +30,29 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #else #include_next +#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags +static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) +{ + __be16 flags = 0; + + if (tflags & TUNNEL_CSUM) + flags |= GRE_CSUM; + if (tflags & TUNNEL_ROUTING) + flags |= GRE_ROUTING; + if (tflags & TUNNEL_KEY) + flags |= GRE_KEY; + if (tflags & TUNNEL_SEQ) + flags |= GRE_SEQ; + if (tflags & TUNNEL_STRICT) + flags |= GRE_STRICT; + if (tflags & TUNNEL_REC) + flags |= GRE_REC; + if (tflags & TUNNEL_VERSION) + flags |= GRE_VERSION; + + return flags; +} + #ifndef HAVE_GRE_CISCO_REGISTER /* GRE demux not available, implement our own demux. */ From patchwork Sat May 19 00:49:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916698 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="P0oOzbeX"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmps72vdz9s4w for ; Sat, 19 May 2018 10:57:25 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 78942DB5; Sat, 19 May 2018 00:50:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 04FAAC16 for ; Sat, 19 May 2018 00:50:09 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B8B806D8 for ; Sat, 19 May 2018 00:50:08 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id p12-v6so4481799pff.13 for ; Fri, 18 May 2018 17:50:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=k8SS6rLrg1/UxR9buY/DiXW/ZoM9crVB3ENXraxhDWk=; b=P0oOzbeXSR4mBoX6XAnFoi1QOLt8TCgxEqujFYNTQnQk471+uQNv4/4AVnRONvGIUP DXgMFIJKcw7aXqzl1P49SV7usESuMsgYTfpTP9mNg+nNML9CZTnIiDxuOxfliwbL8/Xx 3V3tKSTvafrJnsBQ6j2oHyB0hLbosMZ5Hjt8jpYkifDrR0GCKIPTeQlfkP4p5AcQRbRF 9Tz8KzGUSUuqm18D0NnMJY+JV7MaKVNu9Y4pNWTLl/lYuOTcKZcbKbkLfSAvFrBRh+j9 77zN2Al+1vwEU556h7okCuMKaguym/if4yS7Q7Gc4PPKjWmNT1mUa8WN9AKUYlpBAFiv Mk9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=k8SS6rLrg1/UxR9buY/DiXW/ZoM9crVB3ENXraxhDWk=; b=QqKyaz3pvnOiBJNdh00p9JL332385P3Kgm98r4kxNHrM05r2K4AHgcVTC6jIwzYOt2 JJlL1k3pJE6F+sl25MjOFxbU6ZE+kjI++LCiGe/EszusSMyAcJTJP8Lj9MiKSgaxruvp KLxb7J3DqHRKS6VxR26yUO/HPe9mAMsjJ00oyIPE0WSykvUTFmB0EWJJCeltEqhcKxnK UA0+lbNDoz/5Gf7zDGK2HTUR5ioXIlE6KIvlTeYv0bnMb9uM4md6VgrG9GiC6+1zLtY8 SIAww6vpyj2qO/aAotkmqMT7YTW1JoQJHnGL/kbKOfSNQpd/XqoI/HlUiOfhetwXxWX6 cAxw== X-Gm-Message-State: ALKqPwc41yDg9t1YkWXYrdO61GEEmIRbFizCCm6yTQff/1jvhFI/y894 W99nag3ykAg687l4m5xXHUqezA== X-Google-Smtp-Source: AB8JxZor4ngycNI95nsUASTO3Fj4/1v87mhGXhwXFUfC41VOlepbbZnqVOgZrQlTafAgALRp+3lhag== X-Received: by 2002:a63:798d:: with SMTP id u135-v6mr9224763pgc.112.1526691008120; Fri, 18 May 2018 17:50:08 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:07 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:24 -0700 Message-Id: <1526690988-29912-17-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 16/40] compat: Add #define for gre_handle_offloads X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Fixes compile errors on some 4.x kernels. Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 1 + 1 file changed, 1 insertion(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index f849971..b1493e0 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -421,6 +421,7 @@ static bool is_gre_gso(struct sk_buff *skb) return skb_is_gso(skb); } +#define gre_handle_offloads rpl_gre_handle_offloads static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) { int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; From patchwork Sat May 19 00:49:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916699 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kvdK/5bC"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmqc5t4yz9s4w for ; Sat, 19 May 2018 10:58:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E187EDB3; Sat, 19 May 2018 00:50:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7AB57CF7 for ; Sat, 19 May 2018 00:50:10 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f196.google.com (mail-pf0-f196.google.com [209.85.192.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id C69F9473 for ; Sat, 19 May 2018 00:50:09 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id v63-v6so4490887pfk.8 for ; Fri, 18 May 2018 17:50:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CmaZO21AUFpxKJpglNW4aNaKQGz/lP0ouLyKOF1IR/w=; b=kvdK/5bCArsfcSCFVcLtIHrqUU+CfP2wz87IfJtIIFWdHdGp3riNUEVTWykwRs7gKd usUz+PaJhe5yBtsMiBjuaFJoUFAefFgKB+k9D8jva0ozOU6hwChXoZCrB2wVOyiCCFon ejW0iGY5qHUN897IBM29MGz3zB3Blb4XsyjXedZCM2Pno8Tx2Il4cJ2xrdMFoNXZ+t/k gaCnuTOSF6l6tCGn6YV2ItUvs3/y3Sa5j9RFRRigN1IGnKLWQmjlOibfE74h+QYKN1Z7 maPcFBMqNfvzVgLnRiLeySuVdhOh1t/p6cMfjeWRrpZBZpBLjEEZar1TrudeVQfVfr/w LGYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CmaZO21AUFpxKJpglNW4aNaKQGz/lP0ouLyKOF1IR/w=; b=TExKbvMFXy1v/WwLfKWCGS3p9M9QVQRDG2X3YxvUqOeLCntB0DAzmK8x+917aB8+Is 58RhfcJZQWAUl8q5B8cOHR+aUrI3CPhLnv4u+QS5t2y1gCTscNilaszH8COOXCSCbbV/ TLiFvI87M7/xHYJEnh15ISbb16ly5sP/+EAEDFfONJfn+HXJgPTq3zgAI0bNIx7AtsGt KEfEJhkMb6GLLpfNjIT0eYOKFgxnDkRlZVwQmrQlwxTM2vp/KOlAXm+Ftn/jwAf0esvO 4p/L3FAgruxvCZ/GFm2Jd00gEDpS1vWbuQEu23zBvQfs0O4OyW/F+iDwZzLWYu/6xsCa kF/g== X-Gm-Message-State: ALKqPweB81BMRbrK3Y7Zw1au7G4jPG+uzGwuKH/WBAkXSfafTK4E70Aj DpXApFdylR4Jwo+exzGBDpgJkg== X-Google-Smtp-Source: AB8JxZrcg14M+I/0UKLXvQ0LFCpRnK3f76Hm6dKfTFnSYvcQwnCzvb75Ivr+jFneyfzbMLs8/0F3hQ== X-Received: by 2002:aa7:8305:: with SMTP id t5-v6mr11384780pfm.198.1526691009105; Fri, 18 May 2018 17:50:09 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:08 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:25 -0700 Message-Id: <1526690988-29912-18-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 17/40] compat: Fixups for some compile warnings and errors X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org A lot of code has been pulled in. Fix it up to make sure it compiles correctly. Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/gre.c | 23 ---------------- datapath/linux/compat/include/net/gre.h | 47 ++++++++++++++++++++++++++++++++- datapath/linux/compat/ip_gre.c | 9 ++++--- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index 08a5a30..7d16aee 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -82,29 +82,6 @@ static __sum16 check_checksum(struct sk_buff *skb) return csum; } -#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags -static __be16 gre_flags_to_tnl_flags(__be16 flags) -{ - __be16 tflags = 0; - - if (flags & GRE_CSUM) - tflags |= TUNNEL_CSUM; - if (flags & GRE_ROUTING) - tflags |= TUNNEL_ROUTING; - if (flags & GRE_KEY) - tflags |= TUNNEL_KEY; - if (flags & GRE_SEQ) - tflags |= TUNNEL_SEQ; - if (flags & GRE_STRICT) - tflags |= TUNNEL_STRICT; - if (flags & GRE_REC) - tflags |= TUNNEL_REC; - if (flags & GRE_VERSION) - tflags |= TUNNEL_VERSION; - - return tflags; -} - static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, bool *csum_err) { diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index e2473f2..78422c8 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -31,7 +31,52 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #include_next #define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags -static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) +static inline __be16 rpl_tnl_flags_to_gre_flags(__be16 tflags) +{ + __be16 flags = 0; + + if (tflags & TUNNEL_CSUM) + flags |= GRE_CSUM; + if (tflags & TUNNEL_ROUTING) + flags |= GRE_ROUTING; + if (tflags & TUNNEL_KEY) + flags |= GRE_KEY; + if (tflags & TUNNEL_SEQ) + flags |= GRE_SEQ; + if (tflags & TUNNEL_STRICT) + flags |= GRE_STRICT; + if (tflags & TUNNEL_REC) + flags |= GRE_REC; + if (tflags & TUNNEL_VERSION) + flags |= GRE_VERSION; + + return flags; +} + +#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags +static inline __be16 rpl_gre_flags_to_tnl_flags(__be16 flags) +{ + __be16 tflags = 0; + + if (flags & GRE_CSUM) + tflags |= TUNNEL_CSUM; + if (flags & GRE_ROUTING) + tflags |= TUNNEL_ROUTING; + if (flags & GRE_KEY) + tflags |= TUNNEL_KEY; + if (flags & GRE_SEQ) + tflags |= TUNNEL_SEQ; + if (flags & GRE_STRICT) + tflags |= TUNNEL_STRICT; + if (flags & GRE_REC) + tflags |= TUNNEL_REC; + if (flags & GRE_VERSION) + tflags |= TUNNEL_VERSION; + + return tflags; +} +#define gre_tnl_flags_to_gre_flags rpl_gre_tnl_flags_to_gre_flags +static inline __be16 rpl_gre_tnl_flags_to_gre_flags(__be16 tflags) { __be16 flags = 0; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index b1493e0..8060097 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -190,7 +190,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst = NULL; + struct metadata_dst *tun_dst = NULL; struct erspan_base_hdr *ershdr; struct erspan_metadata *pkt_md; struct ip_tunnel_net *itn; @@ -200,16 +200,15 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int len; itn = net_generic(net, erspan_net_id); - iph = ip_hdr(skb); len = gre_hdr_len + sizeof(*ershdr); /* Check based hdr len */ if (unlikely(!pskb_may_pull(skb, len))) - return -ENOMEM; + return PACKET_REJECT; iph = ip_hdr(skb); ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); - ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; + ver = ershdr->ver; /* The original GRE header does not have key field, * Use ERSPAN 10-bit session ID as key. @@ -1183,7 +1182,9 @@ static void ipgre_tunnel_setup(struct net_device *dev) static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); +#ifdef HAVE_NET_DEVICE_MAX_MTU dev->max_mtu = 0; +#endif dev->netdev_ops = &gre_tap_netdev_ops; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ip_tunnel_setup(dev, gre_tap_net_id); From patchwork Sat May 19 00:49:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916706 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="buriyQMx"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmvp45Kwz9s52 for ; Sat, 19 May 2018 11:01:42 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 33CF3C41; Sat, 19 May 2018 00:50:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E720CD67 for ; Sat, 19 May 2018 00:50:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f67.google.com (mail-pg0-f67.google.com [74.125.83.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 1C9216CF for ; Sat, 19 May 2018 00:50:14 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id a13-v6so3981820pgu.4 for ; Fri, 18 May 2018 17:50:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yBSB7PvY9lNl+8JrBbU5fOUeK8GrEBy6Ics62w7zOpM=; b=buriyQMxAi/Kpu8UJznE4cw0qh8szktkSiu18zPKdAON/Ab0EBDFR1aG0hXNMxgO0O jeJmv1dZHaR/6ww16+vdo53cr8Q00ABE7hIg2VOvydvVED1cdn8CSNzvw/3axvXPkR0q 7nqy26SHppOez+j3KwqYBQZ2SZpXtH4jPLOymisoTx2MolLzLaO/SzlTsU0HCPhObGN+ y106Kt7Rm0DgVabcIEkEfXyKhz5gq6I8YVCs6JTAGIQHyET1cphYBNSSFmu4jYwv2T4/ eMt2wQnMzruLM5SyyfAT7VT8H0Ayb8Cpf2CObn30lJcoMMdlOMv9GvcveMTJ/DyG90LO Leuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yBSB7PvY9lNl+8JrBbU5fOUeK8GrEBy6Ics62w7zOpM=; b=p8k41DPFeFO1TPHJeTatqY8z7SA4cpbQ/E3G9xj3emB+TYuqOjHShudV39MW45XuYu Tc6iipwICXNtlIGfGCOijdy6/FA5b2fmkH08aOhOLtHSN9HVDN148Z8HhOOJzhLgFyDu TUEbDDVqksywXJl18iwZCZJIqsPs5uLnHckP/PGnlRARRMxb0UdQWv4CvvQZwKgna4bt RGF0bg05AyGk/rA4NO/n5vReNAeSt3wySnZeKpUUSu4a/n+P7HSoEHlME22QYIFvzdow LT4l6yHIRQMh28SKmAzfZFm45/ZOAkhb4Xyo+th0N0siLX8Izwk5Fg/FZgp9fU7JEL3x TJbA== X-Gm-Message-State: ALKqPwd6Ovc82gccBsKzuHp+HbW+Ecm1XUvIobW17Z6csDevN0c9+fp0 T8xeMX+tTfQRU91UWk5mbQt9mA== X-Google-Smtp-Source: AB8JxZomMRvpg7EQNhFqVDNU9aDYnNrQ3fYVrLjihIB2kPg0Ye2Tyix575ofwm/iNbdXQZbRxKXd6A== X-Received: by 2002:a63:8dca:: with SMTP id z193-v6mr9039207pgd.418.1526691010853; Fri, 18 May 2018 17:50:10 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:10 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:26 -0700 Message-Id: <1526690988-29912-19-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-0.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, FREEMAIL_REPLY,RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 18/40] compat: Add ipv6 GRE and IPV6 Tunneling X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch backports upstream ipv6 GRE and tunneling into the OVS OOT (Out of Tree) datapath drivers. The primary reason for this is to support the ERSPAN feature. Because there is no previous history of ipv6 GRE and tunneling it is not possible to exactly reproduce the history of all the files in the patch. The two newly added files - ip6_gre.c and ip6_tunnel.c - are cut from whole cloth out of the upstream Linux 4.15 kernel and then modified as necessary with compatibility layer fixups. These two files already included parts of several other upstream commits that also touched other upstream files. As such, this patch may incorporate parts or all of the following commits: d350a82 net: erspan: create erspan metadata uapi header c69de58 net: erspan: use bitfield instead of mask and offset b423d13 net: erspan: fix use-after-free 214bb1c net: erspan: remove md NULL check afb4c97 ip6_gre: fix potential memory leak in ip6erspan_rcv 50670b6 ip_gre: fix potential memory leak in erspan_rcv a734321 ip6_gre: fix error path when ip6erspan_rcv failed dd8d5b8 ip_gre: fix error path when erspan_rcv failed 293a199 ip6_gre: fix a pontential issue in ip6erspan_rcv d91e8db5 net: erspan: reload pointer after pskb_may_pull ae3e133 net: erspan: fix wrong return value c05fad5 ip_gre: fix wrong return value of erspan_rcv 94d7d8f ip6_gre: add erspan v2 support f551c91 net: erspan: introduce erspan v2 for ip_gre 1d7e2ed net: erspan: refactor existing erspan code ef7baf5 ip6_gre: add ip6 erspan collect_md mode 5a963eb ip6_gre: Add ERSPAN native tunnel support ceaa001 openvswitch: Add erspan tunnel support. f192970 ip_gre: check packet length and mtu correctly in erspan tx c84bed4 ip_gre: erspan device should keep dst c122fda ip_gre: set tunnel hlen properly in erspan_tunnel_init 5513d08 ip_gre: check packet length and mtu correctly in erspan_xmit 935a974 ip_gre: get key from session_id correctly in erspan_rcv 1a66a83 gre: add collect_md mode to ERSPAN tunnel 84e54fe gre: introduce native tunnel support for ERSPAN In cases where the listed commits also touched other source code files then the patches are also listed separately within this patch series. Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/Modules.mk | 2 + datapath/linux/compat/include/linux/compiler.h | 4 + datapath/linux/compat/include/linux/if_ether.h | 4 + datapath/linux/compat/include/linux/netdevice.h | 7 + datapath/linux/compat/include/linux/openvswitch.h | 3 + datapath/linux/compat/include/linux/skbuff.h | 11 + datapath/linux/compat/include/net/erspan.h | 254 +- datapath/linux/compat/include/net/gre.h | 25 + datapath/linux/compat/include/net/ip6_tunnel.h | 206 +- datapath/linux/compat/include/net/ipv6.h | 29 + datapath/linux/compat/ip6_gre.c | 2578 +++++++++++++++++++++ datapath/linux/compat/ip6_tunnel.c | 2199 ++++++++++++++++++ datapath/linux/compat/ip_gre.c | 1 + datapath/vport.c | 12 + lib/dpif-netlink-rtnl.c | 12 + lib/dpif-netlink.c | 5 + ofproto/ofproto-dpif-xlate.c | 3 + 17 files changed, 5321 insertions(+), 34 deletions(-) create mode 100644 datapath/linux/compat/ip6_gre.c create mode 100644 datapath/linux/compat/ip6_tunnel.c diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index e0a90c3..104c32f 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -13,6 +13,8 @@ openvswitch_sources += \ linux/compat/ip_tunnel.c \ linux/compat/ip_tunnels_core.c \ linux/compat/ip6_output.c \ + linux/compat/ip6_gre.c \ + linux/compat/ip6_tunnel.c \ linux/compat/lisp.c \ linux/compat/netdevice.c \ linux/compat/nf_conntrack_core.c \ diff --git a/datapath/linux/compat/include/linux/compiler.h b/datapath/linux/compat/include/linux/compiler.h index dbe3ca7..65f3ba6 100644 --- a/datapath/linux/compat/include/linux/compiler.h +++ b/datapath/linux/compat/include/linux/compiler.h @@ -11,4 +11,8 @@ #define __rcu #endif +#ifndef READ_ONCE +#define READ_ONCE(x) (x) +#endif + #endif diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h index aaa88db..8dff938 100644 --- a/datapath/linux/compat/include/linux/if_ether.h +++ b/datapath/linux/compat/include/linux/if_ether.h @@ -27,6 +27,10 @@ #define ETH_P_ERSPAN 0x88BE /* ERSPAN TYPE II */ #endif +#ifndef ETH_P_ERSPAN2 +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ +#endif + #define inner_eth_hdr rpl_inner_eth_hdr static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 29ef6c7..cf68ed5 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -316,4 +316,11 @@ static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol, skb->mac_len = mac_len; } #endif + +#ifndef HAVE_NETIF_KEEP_DST +static inline void netif_keep_dst(struct net_device *dev) +{ +} +#endif + #endif /* __LINUX_NETDEVICE_WRAPPER_H */ diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 84ebcaf..771220b 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -238,6 +238,9 @@ enum ovs_vport_type { OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */ OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */ OVS_VPORT_TYPE_STT = 106, /* STT tunnel */ + OVS_VPORT_TYPE_ERSPAN = 107, /* ERSPAN tunnel. */ + OVS_VPORT_TYPE_IP6ERSPAN = 108, /* ERSPAN tunnel. */ + OVS_VPORT_TYPE_IP6GRE = 109, __OVS_VPORT_TYPE_MAX }; diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 45778bd..63ffcaa 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -421,4 +421,15 @@ static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len) } #endif +#ifndef HAVE_SKB_GSO_IPXIP6 +#define SKB_GSO_IPXIP6 (1 << 10) +#endif + +#ifndef HAVE_SKB_SET_INNER_IPPROTO +static inline void skb_set_inner_ipproto(struct sk_buff *skb, + __u8 ipproto) +{ +} +#endif + #endif diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h index b4f13e6..813a9c5 100644 --- a/datapath/linux/compat/include/net/erspan.h +++ b/datapath/linux/compat/include/net/erspan.h @@ -1,4 +1,4 @@ -#ifndef USE_UPSTREAM_TUNNEL +#ifndef HAVE_LINUX_ERSPAN_H #ifndef __LINUX_ERSPAN_H #define __LINUX_ERSPAN_H @@ -16,7 +16,7 @@ * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The * other fields are set to zero, so only a sequence number follows. * - * ERSPAN Type II header (8 octets [42:49]) + * ERSPAN Version 1 (Type II) header (8 octets [42:49]) * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -25,11 +25,66 @@ * | Reserved | Index | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * + * + * ERSPAN Version 2 (Type III) header (12 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS |BSO|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Timestamp | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SGT |P| FT | Hw ID |D|Gra|O| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Platform Specific SubHeader (8 octets, optional) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platf ID | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ -#define ERSPAN_VERSION 0x1 +/* #include */ +/* Just insert uapi/linux/erspan.h here since + * we don't pull in uapi to compat + */ +/* ERSPAN version 2 metadata header */ +struct erspan_md2 { + __be32 timestamp; + __be16 sgt; /* security group tag */ +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 hwid_upper:2, + ft:5, + p:1; + __u8 o:1, + gra:2, + dir:1, + hwid:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 p:1, + ft:5, + hwid_upper:2; + __u8 hwid:4, + dir:1, + gra:2, + o:1; +#else +#error "Please fix " +#endif +}; + +struct erspan_metadata { + int version; + union { + __be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ + } u; +}; +#define ERSPAN_VERSION 0x1 /* ERSPAN type II */ #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff #define COS_MASK 0xe000 @@ -38,6 +93,19 @@ #define ID_MASK 0x03ff #define INDEX_MASK 0xfffff +#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/ +#define BSO_MASK EN_MASK +#define SGT_MASK 0xffff0000 +#define P_MASK 0x8000 +#define FT_MASK 0x7c00 +#define HWID_MASK 0x03f0 +#define DIR_MASK 0x0008 +#define GRA_MASK 0x0006 +#define O_MASK 0x0001 + +#define HWID_OFFSET 4 +#define DIR_OFFSET 3 + enum erspan_encap_type { ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ @@ -45,20 +113,72 @@ enum erspan_encap_type { ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ }; -struct erspan_metadata { - __be32 index; /* type II */ -}; +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 -struct erspanhdr { - __be16 ver_vlan; -#define VER_OFFSET 12 - __be16 session_id; -#define COS_OFFSET 13 -#define EN_OFFSET 11 -#define T_OFFSET 10 - struct erspan_metadata md; +struct erspan_base_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 vlan_upper:4, + ver:4; + __u8 vlan:8; + __u8 session_id_upper:2, + t:1, + en:2, + cos:3; + __u8 session_id:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 ver: 4, + vlan_upper:4; + __u8 vlan:8; + __u8 cos:3, + en:2, + t:1, + session_id_upper:2; + __u8 session_id:8; +#else +#error "Please fix " +#endif }; +static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id) +{ + ershdr->session_id = id & 0xff; + ershdr->session_id_upper = (id >> 8) & 0x3; +} + +static inline u16 get_session_id(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->session_id_upper << 8) + ershdr->session_id; +} + +static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan) +{ + ershdr->vlan = vlan & 0xff; + ershdr->vlan_upper = (vlan >> 8) & 0xf; +} + +static inline u16 get_vlan(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->vlan_upper << 8) + ershdr->vlan; +} + +static inline void set_hwid(struct erspan_md2 *md2, u8 hwid) +{ + md2->hwid = hwid & 0xf; + md2->hwid_upper = (hwid >> 4) & 0x3; +} + +static inline u8 get_hwid(const struct erspan_md2 *md2) +{ + return (md2->hwid_upper << 4) + md2->hwid; +} + +static inline int erspan_hdr_len(int version) +{ + return sizeof(struct erspan_base_hdr) + + (version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE); +} + static inline u8 tos_to_cos(u8 tos) { u8 dscp, cos; @@ -69,18 +189,19 @@ static inline u8 tos_to_cos(u8 tos) } static inline void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, + u32 id, u32 index, bool truncate, bool is_ipv4) { - struct ethhdr *eth = eth_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb->data; enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; + struct erspan_base_hdr *ershdr; struct qtag_prefix { __be16 eth_type; __be16 tci; } *qp; u16 vlan_tci = 0; u8 tos; + __be32 *idx; tos = is_ipv4 ? ip_hdr(skb)->tos : (ipv6_hdr(skb)->priority << 4) + @@ -97,17 +218,94 @@ static inline void erspan_build_header(struct sk_buff *skb, enc_type = ERSPAN_ENCAP_INFRAME; } - skb_push(skb, sizeof(*ershdr)); - ershdr = (struct erspanhdr *)skb->data; - memset(ershdr, 0, sizeof(*ershdr)); - - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION << VER_OFFSET)); - ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | - (enc_type << EN_OFFSET & EN_MASK) | - ((truncate << T_OFFSET) & T_MASK)); - ershdr->md.index = htonl(index & INDEX_MASK); + skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + + /* Build base header */ + ershdr->ver = ERSPAN_VERSION; + ershdr->cos = tos_to_cos(tos); + ershdr->en = enc_type; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + set_session_id(ershdr, id); + + /* Build metadata */ + idx = (__be32 *)(ershdr + 1); + *idx = htonl(index & INDEX_MASK); +} + +/* ERSPAN GRA: timestamp granularity + * 00b --> granularity = 100 microseconds + * 01b --> granularity = 100 nanoseconds + * 10b --> granularity = IEEE 1588 + * Here we only support 100 microseconds. + */ +static inline __be32 erspan_get_timestamp(void) +{ + u64 h_usecs; + ktime_t kt; + + kt = ktime_get_real(); + h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC); + + /* ERSPAN base header only has 32-bit, + * so it wraps around 4 days. + */ + return htonl((u32)h_usecs); +} + +static inline void erspan_build_header_v2(struct sk_buff *skb, + u32 id, u8 direction, u16 hwid, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = (struct ethhdr *)skb->data; + struct erspan_base_hdr *ershdr; + struct erspan_md2 *md2; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u8 gra = 0; /* 100 usec */ + u8 bso = 0; /* Bad/Short/Oversized */ + u8 sgt = 0; + u8 tos; + + tos = is_ipv4 ? ip_hdr(skb)->tos : + (ipv6_hdr(skb)->priority << 4) + + (ipv6_hdr(skb)->flow_lbl[0] >> 4); + + /* Unlike v1, v2 does not have En field, + * so only extract vlan tci field. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + } + + skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + + /* Build base header */ + ershdr->ver = ERSPAN_VERSION2; + ershdr->cos = tos_to_cos(tos); + ershdr->en = bso; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + set_session_id(ershdr, id); + + /* Build metadata */ + md2 = (struct erspan_md2 *)(ershdr + 1); + md2->timestamp = erspan_get_timestamp(); + md2->sgt = htons(sgt); + md2->p = 1; + md2->ft = 0; + md2->dir = direction; + md2->gra = gra; + md2->o = 0; + set_hwid(md2, hwid); } #endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 78422c8..11a95a5 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -15,6 +15,23 @@ static inline int rpl_ipgre_init(void) static inline void rpl_ipgre_fini(void) {} +static inline int rpl_ip6gre_init(void) +{ + return 0; +} + +static inline void rpl_ip6gre_fini(void) +{} + +static inline int rpl_ip6_tunnel_init(void) +{ + return 0; +} + +static inline void rpl_ip6_tunnel_cleanup(void) +{ +} + #define gre_fb_xmit dev_queue_xmit #ifdef CONFIG_INET @@ -132,6 +149,10 @@ void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, int rpl_ipgre_init(void); void rpl_ipgre_fini(void); +int rpl_ip6gre_init(void); +void rpl_ip6gre_fini(void); +int rpl_ip6_tunnel_init(void); +void rpl_ip6_tunnel_cleanup(void); #define gretap_fb_dev_create rpl_gretap_fb_dev_create struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, @@ -147,6 +168,10 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define ipgre_init rpl_ipgre_init #define ipgre_fini rpl_ipgre_fini +#define ip6gre_init rpl_ip6gre_init +#define ip6gre_fini rpl_ip6gre_fini +#define ip6_tunnel_init rpl_ip6_tunnel_init +#define ip6_tunnel_cleanup rpl_ip6_tunnel_cleanup #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); diff --git a/datapath/linux/compat/include/net/ip6_tunnel.h b/datapath/linux/compat/include/net/ip6_tunnel.h index b0917d8..e0a33a6 100644 --- a/datapath/linux/compat/include/net/ip6_tunnel.h +++ b/datapath/linux/compat/include/net/ip6_tunnel.h @@ -1,14 +1,208 @@ -#ifndef _NET_IP6_TUNNEL_WRAPER_H -#define _NET_IP6_TUNNEL_WRAPER_H +#ifndef NET_IP6_TUNNEL_WRAPPER_H +#define NET_IP6_TUNNEL_WRAPPER_H 1 + +#ifdef HAVE_IP6_TNL_PARM_ERSPAN_VER +#include_next +#else #include #include #include #include -#include_next +#include +#include +#include +#include "gso.h" + +#define IP6TUNNEL_ERR_TIMEO (30*HZ) + +/* capable of sending packets */ +#define IP6_TNL_F_CAP_XMIT 0x10000 +/* capable of receiving packets */ +#define IP6_TNL_F_CAP_RCV 0x20000 +/* determine capability on a per-packet basis */ +#define IP6_TNL_F_CAP_PER_PACKET 0x40000 + +#ifndef IP6_TNL_F_ALLOW_LOCAL_REMOTE +#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0 +#endif + +struct rpl__ip6_tnl_parm { + char name[IFNAMSIZ]; /* name of tunnel device */ + int link; /* ifindex of underlying L2 interface */ + __u8 proto; /* tunnel protocol */ + __u8 encap_limit; /* encapsulation limit for tunnel */ + __u8 hop_limit; /* hop limit for tunnel */ + bool collect_md; + __be32 flowinfo; /* traffic class and flowlabel for tunnel */ + __u32 flags; /* tunnel flags */ + struct in6_addr laddr; /* local tunnel end-point address */ + struct in6_addr raddr; /* remote tunnel end-point address */ + + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; + + __u32 fwmark; + __u32 index; /* ERSPAN type II index */ + __u8 erspan_ver; /* ERSPAN version */ + __u8 dir; /* direction */ + __u16 hwid; /* hwid */ +}; + +#define __ip6_tnl_parm rpl__ip6_tnl_parm + +/* IPv6 tunnel */ +struct rpl_ip6_tnl { + struct rpl_ip6_tnl __rcu *next; /* next tunnel in list */ + struct net_device *dev; /* virtual device associated with tunnel */ + struct net *net; /* netns for packet i/o */ + struct __ip6_tnl_parm parms; /* tunnel configuration parameters */ + struct flowi fl; /* flowi template for xmit */ + struct dst_cache dst_cache; /* cached dst */ + struct gro_cells gro_cells; + + int err_count; + unsigned long err_time; + + /* These fields used only by GRE */ + __u32 i_seqno; /* The last seen seqno */ + __u32 o_seqno; /* The last output seqno */ + int hlen; /* tun_hlen + encap_hlen */ + int tun_hlen; /* Precalculated header length */ + int encap_hlen; /* Encap header length (FOU,GUE) */ + struct ip_tunnel_encap encap; + int mlink; +}; + +#define ip6_tnl rpl_ip6_tnl + +struct rpl_ip6_tnl_encap_ops { + size_t (*encap_hlen)(struct ip_tunnel_encap *e); + int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, + u8 *protocol, struct flowi6 *fl6); +}; + +#define ip6_tnl_encap_ops rpl_ip6_tnl_encap_ops + +#ifdef CONFIG_INET + +#ifndef MAX_IPTUN_ENCAP_OPS +#define MAX_IPTUN_ENCAP_OPS 8 +#endif + +extern const struct ip6_tnl_encap_ops __rcu * + rpl_ip6tun_encaps[MAX_IPTUN_ENCAP_OPS]; + +int rpl_ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num); +#define ip6_tnl_encap_add_ops rpl_ip6_tnl_encap_add_ops +int rpl_ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num); +#define ip6_tnl_encap_del_ops rpl_ip6_tnl_encap_del_ops +int rpl_ip6_tnl_encap_setup(struct ip6_tnl *t, + struct ip_tunnel_encap *ipencap); +#define ip6_tnl_encap_setup rpl_ip6_tnl_encap_setup + +#ifndef HAVE_TUNNEL_ENCAP_TYPES +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, +}; + +#endif +static inline int ip6_encap_hlen(struct ip_tunnel_encap *e) +{ + const struct ip6_tnl_encap_ops *ops; + int hlen = -EINVAL; + + if (e->type == TUNNEL_ENCAP_NONE) + return 0; + + if (e->type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_ip6tun_encaps[e->type]); + if (likely(ops && ops->encap_hlen)) + hlen = ops->encap_hlen(e); + rcu_read_unlock(); + + return hlen; +} + +static inline int ip6_tnl_encap(struct sk_buff *skb, struct ip6_tnl *t, + u8 *protocol, struct flowi6 *fl6) +{ + const struct ip6_tnl_encap_ops *ops; + int ret = -EINVAL; + + if (t->encap.type == TUNNEL_ENCAP_NONE) + return 0; + + if (t->encap.type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_ip6tun_encaps[t->encap.type]); + if (likely(ops && ops->build_header)) + ret = ops->build_header(skb, &t->encap, protocol, fl6); + rcu_read_unlock(); + + return ret; +} + +/* Tunnel encapsulation limit destination sub-option */ + +struct ipv6_tlv_tnl_enc_lim { + __u8 type; /* type-code for option */ + __u8 length; /* option length */ + __u8 encap_limit; /* tunnel encapsulation limit */ +} __packed; + +int rpl_ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_rcv_ctl rpl_ip6_tnl_rcv_ctl +int rpl_ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + bool log_ecn_error); +#define ip6_tnl_rcv rpl_ip6_tnl_rcv +int rpl_ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_xmit_ctl rpl_ip6_tnl_xmit_ctl +int rpl_ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, __u32 *pmtu, + __u8 proto); +#define ip6_tnl_xmit rpl_ip6_tnl_xmit +__u16 rpl_ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw); +#define ip6_tnl_parse_tlv_enc_lim rpl_ip6_tnl_parse_tlv_enc_lim +__u32 rpl_ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_get_cap rpl_ip6_tnl_get_cap +struct net *rpl_ip6_tnl_get_link_net(const struct net_device *dev); +#define ip6_tnl_get_link_net rpl_ip6_tnl_get_link_net +int rpl_ip6_tnl_get_iflink(const struct net_device *dev); +#define ip6_tnl_get_iflink rpl_ip6_tnl_get_iflink +int rpl_ip6_tnl_change_mtu(struct net_device *dev, int new_mtu); +#define ip6_tnl_change_mtu rpl_ip6_tnl_change_mtu + +static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, + struct net_device *dev) +{ + int pkt_len, err; + + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + pkt_len = skb->len - skb_inner_network_offset(skb); + err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); + if (unlikely(net_xmit_eval(err))) + pkt_len = -1; + iptunnel_xmit_stats(dev, pkt_len); +} +#endif -#define ip6tunnel_xmit rpl_ip6tunnel_xmit -void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, - struct net_device *dev); +#endif /* HAVE_IP6_TNL_PARM_ERSPAN_VER */ #endif diff --git a/datapath/linux/compat/include/net/ipv6.h b/datapath/linux/compat/include/net/ipv6.h index 7fc0339..6379457 100644 --- a/datapath/linux/compat/include/net/ipv6.h +++ b/datapath/linux/compat/include/net/ipv6.h @@ -39,6 +39,35 @@ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; } +#ifndef HAVE_IP6_MAKE_FLOWLABEL_FL6 +#define ip6_make_flowlabel rpl_ip6_make_flowlabel +static inline __be32 rpl_ip6_make_flowlabel(struct net *net, + struct sk_buff *skb, + __be32 flowlabel, bool autolabel, + struct flowi6 *fl6) +{ +#ifndef HAVE_NETNS_SYSCTL_IPV6_AUTO_FLOWLABELS + if (!flowlabel && autolabel) { +#else + if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) { +#endif + u32 hash; + + hash = skb_get_hash(skb); + + /* Since this is being sent on the wire obfuscate hash a bit + * to minimize possbility that any useful information to an + * attacker is leaked. Only lower 20 bits are relevant. + */ + hash ^= hash >> 12; + + flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK; + } + + return flowlabel; +} +#endif + #ifndef IPV6_TCLASS_SHIFT #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) #define IPV6_TCLASS_SHIFT 20 diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c new file mode 100644 index 0000000..23b1c83 --- /dev/null +++ b/datapath/linux/compat/ip6_gre.c @@ -0,0 +1,2578 @@ +/* + * GRE over IPv6 protocol decoder. + * + * Authors: Dmitry Kozlov (xeb@mail.ru) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#ifndef USE_UPSTREAM_TUNNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "vport-netdev.h" + +#define IP6_GRE_HASH_SIZE_SHIFT 5 +#define IP6_GRE_HASH_SIZE (1 << IP6_GRE_HASH_SIZE_SHIFT) + +static unsigned int ip6gre_net_id __read_mostly; +struct ip6gre_net { + struct ip6_tnl __rcu *tunnels[4][IP6_GRE_HASH_SIZE]; + + struct ip6_tnl __rcu *collect_md_tun; + struct net_device *fb_tunnel_dev; +}; + +static struct rtnl_link_ops ip6gre_link_ops __read_mostly; +static struct rtnl_link_ops ip6gre_tap_ops __read_mostly; +static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly; +static int ip6gre_tunnel_init(struct net_device *dev); +static void ip6gre_tunnel_setup(struct net_device *dev); +static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); +static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); + +#define gre_calc_hlen rpl_ip_gre_calc_hlen +static int rpl_ip_gre_calc_hlen(__be16 o_flags) +{ + int addend = 4; + + if (o_flags & TUNNEL_CSUM) + addend += 4; + if (o_flags & TUNNEL_KEY) + addend += 4; + if (o_flags & TUNNEL_SEQ) + addend += 4; + return addend; +} + +/* Tunnel hash table */ + +/* + 4 hash tables: + + 3: (remote,local) + 2: (remote,*) + 1: (*,local) + 0: (*,*) + + We require exact key match i.e. if a key is present in packet + it will match only tunnel with the same key; if it is not present, + it will match only keyless tunnel. + + All keysless packets, if not matched configured keyless tunnels + will match fallback tunnel. + */ + +#define HASH_KEY(key) (((__force u32)key^((__force u32)key>>4))&(IP6_GRE_HASH_SIZE - 1)) +static u32 HASH_ADDR(const struct in6_addr *addr) +{ + u32 hash = ipv6_addr_hash(addr); + + return hash_32(hash, IP6_GRE_HASH_SIZE_SHIFT); +} + +#define tunnels_r_l tunnels[3] +#define tunnels_r tunnels[2] +#define tunnels_l tunnels[1] +#define tunnels_wc tunnels[0] + +/* Given src, dst and key, find appropriate for input tunnel. */ + +static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, + const struct in6_addr *remote, const struct in6_addr *local, + __be32 key, __be16 gre_proto) +{ + struct net *net = dev_net(dev); + int link = dev->ifindex; + unsigned int h0 = HASH_ADDR(remote); + unsigned int h1 = HASH_KEY(key); + struct ip6_tnl *t, *cand = NULL; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + int dev_type = (gre_proto == htons(ETH_P_TEB) || + gre_proto == htons(ETH_P_ERSPAN)) ? + ARPHRD_ETHER : ARPHRD_IP6GRE; + int score, cand_score = 4; + + for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || + !ipv6_addr_equal(remote, &t->parms.raddr) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) { + if (!ipv6_addr_equal(remote, &t->parms.raddr) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) { + if ((!ipv6_addr_equal(local, &t->parms.laddr) && + (!ipv6_addr_equal(local, &t->parms.raddr) || + !ipv6_addr_is_multicast(local))) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) { + if (t->parms.i_key != key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + if (cand) + return cand; + + t = rcu_dereference(ign->collect_md_tun); + if (t && t->dev->flags & IFF_UP) + return t; + + dev = ign->fb_tunnel_dev; + if (dev->flags & IFF_UP) + return netdev_priv(dev); + + return NULL; +} + +static struct ip6_tnl __rcu **__ip6gre_bucket(struct ip6gre_net *ign, + const struct __ip6_tnl_parm *p) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + unsigned int h = HASH_KEY(p->i_key); + int prio = 0; + + if (!ipv6_addr_any(local)) + prio |= 1; + if (!ipv6_addr_any(remote) && !ipv6_addr_is_multicast(remote)) { + prio |= 2; + h ^= HASH_ADDR(remote); + } + + return &ign->tunnels[prio][h]; +} + +static inline struct ip6_tnl __rcu **ip6gre_bucket(struct ip6gre_net *ign, + const struct ip6_tnl *t) +{ + return __ip6gre_bucket(ign, &t->parms); +} + +static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp = ip6gre_bucket(ign, t); + + if (t->parms.collect_md) + rcu_assign_pointer(ign->collect_md_tun, t); + + rcu_assign_pointer(t->next, rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); +} + +static void ip6gre_tunnel_unlink(struct ip6gre_net *ign, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp; + struct ip6_tnl *iter; + + if (t->parms.collect_md) + rcu_assign_pointer(ign->collect_md_tun, NULL); + + for (tp = ip6gre_bucket(ign, t); + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { + rcu_assign_pointer(*tp, t->next); + break; + } + } +} + +static struct ip6_tnl *ip6gre_tunnel_find(struct net *net, + const struct __ip6_tnl_parm *parms, + int type) +{ + const struct in6_addr *remote = &parms->raddr; + const struct in6_addr *local = &parms->laddr; + __be32 key = parms->i_key; + int link = parms->link; + struct ip6_tnl *t; + struct ip6_tnl __rcu **tp; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + for (tp = __ip6gre_bucket(ign, parms); + (t = rtnl_dereference(*tp)) != NULL; + tp = &t->next) + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr) && + key == t->parms.i_key && + link == t->parms.link && + type == t->dev->type) + break; + + return t; +} + +static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, + const struct __ip6_tnl_parm *parms, int create) +{ + struct ip6_tnl *t, *nt; + struct net_device *dev; + char name[IFNAMSIZ]; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); + if (t && create) + return NULL; + if (t || !create) + return t; + + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else + strcpy(name, "ip6gre%d"); + + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, + ip6gre_tunnel_setup); + if (!dev) + return NULL; + + dev_net_set(dev, net); + + nt = netdev_priv(dev); + nt->parms = *parms; + dev->rtnl_link_ops = &ip6gre_link_ops; + + nt->dev = dev; + nt->net = dev_net(dev); + + if (register_netdevice(dev) < 0) + goto failed_free; + + ip6gre_tnl_link_config(nt, 1); + + /* Can use a lockless transmit, unless we generate output sequences */ + if (!(nt->parms.o_flags & TUNNEL_SEQ)) + dev->features |= NETIF_F_LLTX; + + dev_hold(dev); + ip6gre_tunnel_link(ign, nt); + return nt; + +failed_free: + free_netdev(dev); + return NULL; +} + +static void ip6gre_tunnel_uninit(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); + + ip6gre_tunnel_unlink(ign, t); + dst_cache_reset(&t->dst_cache); + dev_put(dev); +} + + +static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ +#if 0 + struct net *net = dev_net(skb->dev); + const struct gre_base_hdr *greh; + const struct ipv6hdr *ipv6h; + int grehlen = sizeof(*greh); + struct ip6_tnl *t; + int key_off = 0; + __be16 flags; + __be32 key; + + if (!pskb_may_pull(skb, offset + grehlen)) + return; + greh = (const struct gre_base_hdr *)(skb->data + offset); + flags = greh->flags; + if (flags & (GRE_VERSION | GRE_ROUTING)) + return; + if (flags & GRE_CSUM) + grehlen += 4; + if (flags & GRE_KEY) { + key_off = grehlen + offset; + grehlen += 4; + } + + if (!pskb_may_pull(skb, offset + grehlen)) + return; + ipv6h = (const struct ipv6hdr *)skb->data; + greh = (const struct gre_base_hdr *)(skb->data + offset); + key = key_off ? *(__be32 *)(skb->data + key_off) : 0; + + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, + key, greh->protocol); + if (!t) + return; + + switch (type) { + struct ipv6_tlv_tnl_enc_lim *tel; + __u32 teli; + case ICMPV6_DEST_UNREACH: + net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", + t->parms.name); + if (code != ICMPV6_PORT_UNREACH) + break; + return; + case ICMPV6_TIME_EXCEED: + if (code == ICMPV6_EXC_HOPLIMIT) { + net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", + t->parms.name); + break; + } + return; + case ICMPV6_PARAMPROB: + teli = 0; + if (code == ICMPV6_HDR_FIELD) + teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); + + if (teli && teli == be32_to_cpu(info) - 2) { + tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; + if (tel->encap_limit == 0) { + net_dbg_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", + t->parms.name); + } + } else { + net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", + t->parms.name); + } + return; + case ICMPV6_PKT_TOOBIG: + ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + return; + case NDISC_REDIRECT: + ip6_redirect(skb, net, skb->dev->ifindex, 0, + sock_net_uid(net, NULL)); + return; + } + + if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) + t->err_count++; + else + t->err_count = 1; + t->err_time = jiffies; +#endif +} + +static struct dst_ops md_dst_ops = { + .family = AF_UNSPEC, +}; + +#ifndef DST_METADATA +#define DST_METADATA 0x0080 +#endif + +static void rpl__metadata_dst_init(struct metadata_dst *md_dst, + enum metadata_type type, u8 optslen) + +{ + struct dst_entry *dst; + + dst = &md_dst->dst; + dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, + DST_METADATA | DST_NOCOUNT); + +#if 0 + /* unused in OVS */ + dst->input = dst_md_discard; + dst->output = dst_md_discard_out; +#endif + memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst)); + md_dst->type = type; +} + +static struct metadata_dst *erspan_rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, + gfp_t flags) +{ + struct metadata_dst *md_dst; + + md_dst = kmalloc(sizeof(*md_dst) + optslen, flags); + if (!md_dst) + return NULL; + + rpl__metadata_dst_init(md_dst, type, optslen); + + return md_dst; +} +static inline struct metadata_dst *rpl_tun_rx_dst(int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = erspan_rpl_metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC); + if (!tun_dst) + return NULL; + + tun_dst->u.tun_info.options_len = 0; + tun_dst->u.tun_info.mode = 0; + return tun_dst; +} +static inline +struct metadata_dst *rpl__ipv6_tun_set_dst(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u8 tos, __u8 ttl, + __be16 tp_dst, + __be32 label, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + struct metadata_dst *tun_dst; + struct ip_tunnel_info *info; + + tun_dst = rpl_tun_rx_dst(md_size); + if (!tun_dst) + return NULL; + + info = &tun_dst->u.tun_info; + info->mode = IP_TUNNEL_INFO_IPV6; + info->key.tun_flags = flags; + info->key.tun_id = tunnel_id; + info->key.tp_src = 0; + info->key.tp_dst = tp_dst; + + info->key.u.ipv6.src = *saddr; + info->key.u.ipv6.dst = *daddr; + + info->key.tos = tos; + info->key.ttl = ttl; + info->key.label = label; + + return tun_dst; +} + +static inline struct metadata_dst *rpl_ipv6_tun_rx_dst(struct sk_buff *skb, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + const struct ipv6hdr *ip6h = ipv6_hdr(skb); + + return rpl__ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr, + ipv6_get_dsfield(ip6h), ip6h->hop_limit, + 0, ip6_flowlabel(ip6h), flags, tunnel_id, + md_size); +} + +static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +{ + const struct ipv6hdr *ipv6h; + struct ip6_tnl *tunnel; + + ipv6h = ipv6_hdr(skb); + tunnel = ip6gre_tunnel_lookup(skb->dev, + &ipv6h->saddr, &ipv6h->daddr, tpi->key, + tpi->proto); + if (tunnel) { + struct metadata_dst *tun_dst = NULL; + if (tunnel->parms.collect_md) { + __be64 tun_id; + __be16 flags; + + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ipv6_tun_rx_dst(skb, flags, tun_id, 0); + if (!tun_dst) + return PACKET_REJECT; + + } + + skb_reset_mac_header(skb); + ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + kfree(tun_dst); + return PACKET_RCVD; + } + + return PACKET_RCVD; +} + +static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, + struct tnl_ptk_info *tpi) +{ + struct erspan_base_hdr *ershdr; + struct erspan_metadata *pkt_md; + const struct ipv6hdr *ipv6h; + struct erspan_md2 *md2; + struct ip6_tnl *tunnel; + u8 ver; + + if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) + return PACKET_REJECT; + + ipv6h = ipv6_hdr(skb); + ershdr = (struct erspan_base_hdr *)skb->data; + ver = ershdr->ver; + tpi->key = cpu_to_be32(get_session_id(ershdr)); + + tunnel = ip6gre_tunnel_lookup(skb->dev, + &ipv6h->saddr, &ipv6h->daddr, 0, + tpi->proto); + if (tunnel) { + struct metadata_dst *tun_dst = NULL; + int len = erspan_hdr_len(ver); + + if (unlikely(!pskb_may_pull(skb, len))) + return PACKET_REJECT; + + ershdr = (struct erspan_base_hdr *)skb->data; + pkt_md = (struct erspan_metadata *)(ershdr + 1); + + if (__iptunnel_pull_header(skb, len, + htons(ETH_P_TEB), + false, false) < 0) + return PACKET_REJECT; + + if (tunnel->parms.collect_md) { + struct ip_tunnel_info *info; + struct erspan_metadata *md; + __be64 tun_id; + __be16 flags; + + tpi->flags |= TUNNEL_KEY; + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ipv6_tun_rx_dst(skb, flags, tun_id, + sizeof(*md)); + if (!tun_dst) + return PACKET_REJECT; + + info = &tun_dst->u.tun_info; + md = ip_tunnel_info_opts(info); + md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); + info->key.tun_flags |= TUNNEL_ERSPAN_OPT; + info->options_len = sizeof(*md); + } + + ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, false); + kfree(tun_dst); + return PACKET_RCVD; + } + + kfree(skb); + return PACKET_RCVD; +} + +static int gre_rcv(struct sk_buff *skb) +{ + struct tnl_ptk_info tpi; + bool csum_err = false; + int hdr_len; + + hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IPV6), 0); + if (hdr_len < 0) + goto drop; + + if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) + goto drop; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { + if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD) + return 0; + goto out; + } + + if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD) + return 0; + +out: + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); +drop: + kfree_skb(skb); + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#include "gso.h" +/* gre_handle_offloads() has different return type on older kernsl. */ +static void gre_nop_fix(struct sk_buff *skb) { } + +static void gre_csum_fix(struct sk_buff *skb) +{ + struct gre_base_hdr *greh; + __be32 *options; + int gre_offset = skb_transport_offset(skb); + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + options = ((__be32 *)greh + 1); + + *options = 0; + *(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset, + skb->len - gre_offset, 0)); +} + +#define gre_handle_offloads rpl_gre_handle_offloads +static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; + gso_fix_segment_t fix_segment; + + if (gre_csum) + fix_segment = gre_csum_fix; + else + fix_segment = gre_nop_fix; + + return ovs_iptunnel_handle_offloads(skb, type, fix_segment); +} +#else +static int gre_handle_offloads(struct sk_buff *skb, bool csum) +{ + return iptunnel_handle_offloads(skb, + csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); + +#endif + +static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, __u8 *dsfield, + int *encap_limit) +{ + const struct iphdr *iph = ip_hdr(skb); + struct ip6_tnl *t = netdev_priv(dev); + + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + *encap_limit = t->parms.encap_limit; + + memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6)); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + *dsfield = ipv4_get_dsfield(iph); + else + *dsfield = ip6_tclass(t->parms.flowinfo); + +#ifndef IP6_TNL_F_USE_ORIG_FWMARK + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6->flowi6_mark = skb->mark; + else + fl6->flowi6_mark = t->parms.fwmark; + + fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); +#endif +} + +static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, __u8 *dsfield, + int *encap_limit) +{ + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + struct ip6_tnl *t = netdev_priv(dev); + __u16 offset; + + offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); + /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ + + if (offset > 0) { + struct ipv6_tlv_tnl_enc_lim *tel; + + tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; + if (tel->encap_limit == 0) { + icmpv6_send(skb, ICMPV6_PARAMPROB, + ICMPV6_HDR_FIELD, offset + 2); + return -1; + } + *encap_limit = tel->encap_limit - 1; + } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { + *encap_limit = t->parms.encap_limit; + } + + memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6)); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + *dsfield = ipv6_get_dsfield(ipv6h); + else + *dsfield = ip6_tclass(t->parms.flowinfo); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) + fl6->flowlabel |= ip6_flowlabel(ipv6h); + +#ifndef IP6_TNL_F_USE_ORIG_FWMARK + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6->flowi6_mark = skb->mark; + else + fl6->flowi6_mark = t->parms.fwmark; + + fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); +#endif + + return 0; +} + +static netdev_tx_t __gre6_xmit(struct sk_buff *skb, + struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, + __u32 *pmtu, __be16 proto) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + struct tnl_ptk_info tpi; + __be16 protocol; + + if (dev->type == ARPHRD_ETHER) + IPCB(skb)->flags = 0; + + if (dev->header_ops && dev->type == ARPHRD_IP6GRE) + fl6->daddr = ((struct ipv6hdr *)skb->data)->daddr; + else + fl6->daddr = tunnel->parms.raddr; + + if (tunnel->parms.o_flags & TUNNEL_SEQ) + tunnel->o_seqno++; + + /* Push GRE header. */ + protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto; + + if (tunnel->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + __be16 flags; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || + !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -EINVAL; + + key = &tun_info->key; + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_proto = IPPROTO_GRE; + fl6->daddr = key->u.ipv6.dst; + fl6->flowlabel = key->label; +// FIX ME! +// fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + dsfield = key->tos; + flags = key->tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); + tunnel->tun_hlen = gre_calc_hlen(flags); + + tpi.flags = flags; + tpi.proto = protocol; + tpi.key = tunnel_id_to_key32(key->tun_id); + tpi.seq = htonl(tunnel->o_seqno++); + tpi.hdr_len = tunnel->tun_hlen; + + gre_build_header(skb, &tpi, 8); + } else { + tpi.flags = tunnel->parms.o_flags; + tpi.proto = protocol; + tpi.key = tunnel->parms.o_key; + tpi.seq = htonl(tunnel->o_seqno++); + tpi.hdr_len = tunnel->tun_hlen; + + gre_build_header(skb, &tpi, 8); + } + + return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, + NEXTHDR_GRE); +} + +static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield = 0; + __u32 mtu; + int err; + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + + if (!t->parms.collect_md) + prepare_ip6gre_xmit_ipv4(skb, dev, &fl6, + &dsfield, &encap_limit); + + err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); + if (err) + return -1; + + err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + skb->protocol); + if (err != 0) { + /* XXX: send ICMP error even if DF is not set. */ + if (err == -EMSGSIZE) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + return -1; + } + + return 0; +} + +static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield = 0; + __u32 mtu; + int err; + + if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr)) + return -1; + + if (!t->parms.collect_md && + prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit)) + return -1; + + if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM))) + return -1; + + err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, + &mtu, skb->protocol); + if (err != 0) { + if (err == -EMSGSIZE) + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -1; + } + + return 0; +} + +/** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device + * @hdr: IPv6 header from the incoming packet + * + * Description: + * Avoid trivial tunneling loop by checking that tunnel exit-point + * doesn't match source of incoming packet. + * + * Return: + * 1 if conflict, + * 0 else + **/ + +static inline bool ip6gre_tnl_addr_conflict(const struct ip6_tnl *t, + const struct ipv6hdr *hdr) +{ + return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); +} + +static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int encap_limit = -1; + struct flowi6 fl6; + __u32 mtu; + int err; + + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + encap_limit = t->parms.encap_limit; + + if (!t->parms.collect_md) + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + + err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); + if (err) + return err; + + err = __gre6_xmit(skb, dev, 0, &fl6, encap_limit, &mtu, skb->protocol); + + return err; +} + +static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net_device_stats *stats = &t->dev->stats; + int ret; + + if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) + goto tx_err; + + switch (skb->protocol) { + case htons(ETH_P_IP): + ret = ip6gre_xmit_ipv4(skb, dev); + break; + case htons(ETH_P_IPV6): + ret = ip6gre_xmit_ipv6(skb, dev); + break; + default: + ret = ip6gre_xmit_other(skb, dev); + break; + } + + if (ret < 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static netdev_tx_t __ip6gre_tunnel_xmit(struct sk_buff *skb) +{ + return ip6gre_tunnel_xmit(skb, skb->dev); +} + +static bool erspan_skb_would_panic(struct sk_buff *skb, int erspan_md_size) +{ + /* check if there is enough headroom in packet, if not + * drop it. Checking for 8 bytes of gre header space + + * erspan base hdr and erspan type specific header. + */ + if (skb_headroom(skb) < (8 + sizeof(struct erspan_base_hdr) + + erspan_md_size)) + return true; + + return false; +} + +static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct dst_entry *dst = skb_dst(skb); + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct net_device_stats *stats; + struct erspan_metadata *md; + struct tnl_ptk_info tpi; + bool truncate = false; + int encap_limit = -1; + __u8 dsfield = false; + struct flowi6 fl6; + int err = -EINVAL; + __be32 tun_id; + __u32 mtu; + + + /* OVS doesn't support native mode ip6 tunnel traffic so + * take an early exit in that case. */ + if (!t->parms.collect_md) + goto tx_err; + + if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) + goto tx_err; + + if (gre_handle_offloads(skb, false)) + goto tx_err; + + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); + truncate = true; + } + + t->parms.o_flags &= ~TUNNEL_KEY; + IPCB(skb)->flags = 0; + + tun_info = ovs_skb_tunnel_info(skb); + if (unlikely(!tun_info || + !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -EINVAL; + + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_GRE; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + // fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + dsfield = key->tos; + md = ip_tunnel_info_opts(tun_info); + if (!md) + goto tx_err; + + if (erspan_skb_would_panic(skb, + md->version == 1 ? + ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE)) + goto tx_err; + + tun_id = tunnel_id_to_key32(key->tun_id); + if (md->version == 1) { + erspan_build_header(skb, + ntohl(tun_id), + ntohl(md->u.index), truncate, + false); + tpi.hdr_len = ERSPAN_V1_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN); + } else if (md->version == 2) { + erspan_build_header_v2(skb, + ntohl(tun_id), + md->u.md2.dir, + get_hwid(&md->u.md2), + truncate, false); + tpi.hdr_len = ERSPAN_V2_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN2); + } + + tpi.flags = TUNNEL_SEQ; + tpi.key = 0; + tpi.seq = htonl(t->o_seqno++); + + /* Push GRE header. */ + gre_build_header(skb, &tpi, 8); + + /* TooBig packet may have updated dst->dev's mtu */ + if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) + dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + NEXTHDR_GRE); + if (err != 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats = &t->dev->stats; + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static netdev_tx_t __ip6erspan_tunnel_xmit(struct sk_buff *skb) +{ + return ip6erspan_tunnel_xmit(skb, skb->dev); +} + +static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) +{ + struct net_device *dev = t->dev; + struct __ip6_tnl_parm *p = &t->parms; + struct flowi6 *fl6 = &t->fl.u.ip6; + int t_hlen; + + if (dev->type != ARPHRD_ETHER) { + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + } + + /* Set up flowi template */ + fl6->saddr = p->laddr; + fl6->daddr = p->raddr; + fl6->flowi6_oif = p->link; + fl6->flowlabel = 0; + fl6->flowi6_proto = IPPROTO_GRE; + + if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) + fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; + if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) + fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; + + p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV|IP6_TNL_F_CAP_PER_PACKET); + p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr); + + if (p->flags&IP6_TNL_F_CAP_XMIT && + p->flags&IP6_TNL_F_CAP_RCV && dev->type != ARPHRD_ETHER) + dev->flags |= IFF_POINTOPOINT; + else + dev->flags &= ~IFF_POINTOPOINT; + + t->tun_hlen = gre_calc_hlen(t->parms.o_flags); + + t->hlen = t->encap_hlen + t->tun_hlen; + + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); + + struct rt6_info *rt = rt6_lookup(t->net, + &p->raddr, &p->laddr, + p->link, strict); + + if (!rt) + return; + + if (rt->dst.dev) { + dev->hard_header_len = rt->dst.dev->hard_header_len + + t_hlen; + + if (set_mtu) { + dev->mtu = rt->dst.dev->mtu - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + + if (dev->mtu < IPV6_MIN_MTU) + dev->mtu = IPV6_MIN_MTU; + } + } + ip6_rt_put(rt); + } +} + +static int ip6gre_tnl_change(struct ip6_tnl *t, + const struct __ip6_tnl_parm *p, int set_mtu) +{ + t->parms.laddr = p->laddr; + t->parms.raddr = p->raddr; + t->parms.flags = p->flags; + t->parms.hop_limit = p->hop_limit; + t->parms.encap_limit = p->encap_limit; + t->parms.flowinfo = p->flowinfo; + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.i_key = p->i_key; + t->parms.o_key = p->o_key; + t->parms.i_flags = p->i_flags; + t->parms.o_flags = p->o_flags; + t->parms.fwmark = p->fwmark; + dst_cache_reset(&t->dst_cache); + ip6gre_tnl_link_config(t, set_mtu); + return 0; +} + +static void ip6gre_tnl_parm_from_user(struct __ip6_tnl_parm *p, + const struct ip6_tnl_parm2 *u) +{ + p->laddr = u->laddr; + p->raddr = u->raddr; + p->flags = u->flags; + p->hop_limit = u->hop_limit; + p->encap_limit = u->encap_limit; + p->flowinfo = u->flowinfo; + p->link = u->link; + p->i_key = u->i_key; + p->o_key = u->o_key; + p->i_flags = gre_flags_to_tnl_flags(u->i_flags); + p->o_flags = gre_flags_to_tnl_flags(u->o_flags); + memcpy(p->name, u->name, sizeof(u->name)); +} + +static void ip6gre_tnl_parm_to_user(struct ip6_tnl_parm2 *u, + const struct __ip6_tnl_parm *p) +{ + u->proto = IPPROTO_GRE; + u->laddr = p->laddr; + u->raddr = p->raddr; + u->flags = p->flags; + u->hop_limit = p->hop_limit; + u->encap_limit = p->encap_limit; + u->flowinfo = p->flowinfo; + u->link = p->link; + u->i_key = p->i_key; + u->o_key = p->o_key; + u->i_flags = gre_tnl_flags_to_gre_flags(p->i_flags); + u->o_flags = gre_tnl_flags_to_gre_flags(p->o_flags); + memcpy(u->name, p->name, sizeof(u->name)); +} + +static int ip6gre_tunnel_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) +{ + int err = 0; + struct ip6_tnl_parm2 p; + struct __ip6_tnl_parm p1; + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + memset(&p1, 0, sizeof(p1)); + + switch (cmd) { + case SIOCGETTUNNEL: + if (dev == ign->fb_tunnel_dev) { + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { + err = -EFAULT; + break; + } + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, 0); + if (!t) + t = netdev_priv(dev); + } + memset(&p, 0, sizeof(p)); + ip6gre_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + break; + + case SIOCADDTUNNEL: + case SIOCCHGTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + goto done; + + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + goto done; + + err = -EINVAL; + if ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)) + goto done; + + if (!(p.i_flags&GRE_KEY)) + p.i_key = 0; + if (!(p.o_flags&GRE_KEY)) + p.o_key = 0; + + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, cmd == SIOCADDTUNNEL); + + if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { + if (t) { + if (t->dev != dev) { + err = -EEXIST; + break; + } + } else { + t = netdev_priv(dev); + + ip6gre_tunnel_unlink(ign, t); + synchronize_net(); + ip6gre_tnl_change(t, &p1, 1); + ip6gre_tunnel_link(ign, t); + netdev_state_change(dev); + } + } + + if (t) { + err = 0; + + memset(&p, 0, sizeof(p)); + ip6gre_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + } else + err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); + break; + + case SIOCDELTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + goto done; + + if (dev == ign->fb_tunnel_dev) { + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + goto done; + err = -ENOENT; + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, 0); + if (!t) + goto done; + err = -EPERM; + if (t == netdev_priv(ign->fb_tunnel_dev)) + goto done; + dev = t->dev; + } + unregister_netdevice(dev); + err = 0; + break; + + default: + err = -EINVAL; + } + +done: + return err; +} + +static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h; + __be16 *p; + + ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); + ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, + t->fl.u.ip6.flowlabel, + true, &t->fl.u.ip6)); + ipv6h->hop_limit = t->parms.hop_limit; + ipv6h->nexthdr = NEXTHDR_GRE; + ipv6h->saddr = t->parms.laddr; + ipv6h->daddr = t->parms.raddr; + + p = (__be16 *)(ipv6h + 1); + p[0] = t->parms.o_flags; + p[1] = htons(type); + + /* + * Set the source hardware address. + */ + + if (saddr) + memcpy(&ipv6h->saddr, saddr, sizeof(struct in6_addr)); + if (daddr) + memcpy(&ipv6h->daddr, daddr, sizeof(struct in6_addr)); + if (!ipv6_addr_any(&ipv6h->daddr)) + return t->hlen; + + return -t->hlen; +} + +static const struct header_ops ip6gre_header_ops = { + .create = ip6gre_header, +}; + +static const struct net_device_ops ip6gre_netdev_ops = { + .ndo_init = ip6gre_tunnel_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6gre_tunnel_xmit, + .ndo_do_ioctl = ip6gre_tunnel_ioctl, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +#ifdef HAVE_NEEDS_FREE_NETDEV +static void ip6gre_dev_free(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +} + +#endif +static void ip6gre_tunnel_setup(struct net_device *dev) +{ + dev->netdev_ops = &ip6gre_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->type = ARPHRD_IP6GRE; + + dev->flags |= IFF_NOARP; + dev->addr_len = sizeof(struct in6_addr); + netif_keep_dst(dev); + /* This perm addr will be used as interface identifier by IPv6 */ + dev->addr_assign_type = NET_ADDR_RANDOM; + eth_random_addr(dev->perm_addr); +} + +#define GRE6_FEATURES (NETIF_F_SG | \ + NETIF_F_FRAGLIST | \ + NETIF_F_HIGHDMA | \ + NETIF_F_HW_CSUM) + +static void ip6gre_tnl_init_features(struct net_device *dev) +{ + struct ip6_tnl *nt = netdev_priv(dev); + + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + + if (!(nt->parms.o_flags & TUNNEL_SEQ)) { + /* TCP offload with GRE SEQ is not supported, nor + * can we support 2 levels of outer headers requiring + * an update. + */ + if (!(nt->parms.o_flags & TUNNEL_CSUM) || + nt->encap.type == TUNNEL_ENCAP_NONE) { + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; + } + + /* Can use a lockless transmit, unless we generate + * output sequences + */ + dev->features |= NETIF_F_LLTX; + } +} + +static int ip6gre_tunnel_init_common(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int ret; + int t_hlen; + + tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (ret) { + free_percpu(dev->tstats); + dev->tstats = NULL; + return ret; + } + + tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; + t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); + + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + if (tunnel->parms.collect_md) { + dev->features |= NETIF_F_NETNS_LOCAL; + netif_keep_dst(dev); + } + ip6gre_tnl_init_features(dev); + + return 0; +} + +static int ip6gre_tunnel_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int ret; + + ret = ip6gre_tunnel_init_common(dev); + if (ret) + return ret; + + tunnel = netdev_priv(dev); + + if (tunnel->parms.collect_md) + return 0; + + memcpy(dev->dev_addr, &tunnel->parms.laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &tunnel->parms.raddr, sizeof(struct in6_addr)); + + if (ipv6_addr_any(&tunnel->parms.raddr)) + dev->header_ops = &ip6gre_header_ops; + + return 0; +} + +static void ip6gre_fb_tunnel_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + tunnel->hlen = sizeof(struct ipv6hdr) + 4; + + dev_hold(dev); +} + +static struct inet6_protocol ip6gre_protocol __read_mostly = { + .handler = gre_rcv, + .err_handler = ip6gre_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) +{ + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct net_device *dev, *aux; + int prio; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == &ip6gre_link_ops || + dev->rtnl_link_ops == &ip6gre_tap_ops || + dev->rtnl_link_ops == &ip6erspan_tap_ops) + unregister_netdevice_queue(dev, head); + + for (prio = 0; prio < 4; prio++) { + int h; + for (h = 0; h < IP6_GRE_HASH_SIZE; h++) { + struct ip6_tnl *t; + + t = rtnl_dereference(ign->tunnels[prio][h]); + + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, + head); + t = rtnl_dereference(t->next); + } + } + } +} + +static int __net_init ip6gre_init_net(struct net *net) +{ + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + int err; + + ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", + NET_NAME_UNKNOWN, + ip6gre_tunnel_setup); + if (!ign->fb_tunnel_dev) { + err = -ENOMEM; + goto err_alloc_dev; + } + dev_net_set(ign->fb_tunnel_dev, net); + /* FB netdevice is special: we have one, and only one per netns. + * Allowing to move it to another netns is clearly unsafe. + */ + ign->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + + + ip6gre_fb_tunnel_init(ign->fb_tunnel_dev); + ign->fb_tunnel_dev->rtnl_link_ops = &ip6gre_link_ops; + + err = register_netdev(ign->fb_tunnel_dev); + if (err) + goto err_reg_dev; + + rcu_assign_pointer(ign->tunnels_wc[0], + netdev_priv(ign->fb_tunnel_dev)); + return 0; + +err_reg_dev: + free_netdev(ign->fb_tunnel_dev); +err_alloc_dev: + return err; +} + +static void __net_exit ip6gre_exit_batch_net(struct list_head *net_list) +{ + struct net *net; + LIST_HEAD(list); + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) + ip6gre_destroy_tunnels(net, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); +} + +enum { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) + IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) + IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) + IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) + IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) + IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, +#endif + +}; + +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) + +static struct pernet_operations ip6gre_net_ops = { + .init = ip6gre_init_net, + .exit_batch = ip6gre_exit_batch_net, + .id = &ip6gre_net_id, + .size = sizeof(struct ip6gre_net), +}; +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + __be16 flags; + + if (!data) + return 0; + + flags = 0; + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (flags & (GRE_VERSION|GRE_ROUTING)) + return -EINVAL; + + return 0; +} +#define ip6gre_tunnel_validate rpl_ip6gre_tunnel_validate + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct in6_addr daddr; + + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + + if (!data) + goto out; + + if (data[IFLA_GRE_REMOTE]) { + daddr = nla_get_in6_addr(data[IFLA_GRE_REMOTE]); + if (ipv6_addr_any(&daddr)) + return -EINVAL; + } + +out: +#ifdef HAVE_IP6GRE_EXTACK + return ip6gre_tunnel_validate(tb, data, extack); +#else + return ip6gre_tunnel_validate(tb, data); +#endif +} +#define ip6gre_tap_validate rpl_ip6gre_tap_validate + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6erspan_tap_validate(struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6erspan_tap_validate(struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + __be16 flags = 0; + int ret, ver = 0; + + if (!data) + return 0; + +#ifdef HAVE_IP6GRE_EXTACK + ret = ip6gre_tap_validate(tb, data, extack); +#else + ret = ip6gre_tap_validate(tb, data); +#endif + if (ret) + return ret; + + /* ERSPAN should only have GRE sequence and key flag */ + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (!data[IFLA_GRE_COLLECT_METADATA] && + flags != (GRE_SEQ | GRE_KEY)) + return -EINVAL; + + /* ERSPAN Session ID only has 10-bit. Since we reuse + * 32-bit key field as ID, check it's range. + */ + if (data[IFLA_GRE_IKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_OKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_ERSPAN_VER]) { + ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); + if (ver != 1 && ver != 2) + return -EINVAL; + } + + if (ver == 1) { + if (data[IFLA_GRE_ERSPAN_INDEX]) { + u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + + if (index & ~INDEX_MASK) + return -EINVAL; + } + } else if (ver == 2) { + if (data[IFLA_GRE_ERSPAN_DIR]) { + u16 dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); + + if (dir & ~(DIR_MASK >> DIR_OFFSET)) + return -EINVAL; + } + + if (data[IFLA_GRE_ERSPAN_HWID]) { + u16 hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); + + if (hwid & ~(HWID_MASK >> HWID_OFFSET)) + return -EINVAL; + } + } + + return 0; +} +#define ip6erspan_tap_validate rpl_ip6erspan_tap_validate + +static void ip6gre_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) +{ +#if 0 + /* Do not use in case of OVS - our vport needs to set a parm + * directly and this erases it + */ + memset(parms, 0, sizeof(*parms)); + +#endif + if (!data) + return; + + if (data[IFLA_GRE_LINK]) + parms->link = nla_get_u32(data[IFLA_GRE_LINK]); + + if (data[IFLA_GRE_IFLAGS]) + parms->i_flags = gre_flags_to_tnl_flags( + nla_get_be16(data[IFLA_GRE_IFLAGS])); + + if (data[IFLA_GRE_OFLAGS]) + parms->o_flags = gre_flags_to_tnl_flags( + nla_get_be16(data[IFLA_GRE_OFLAGS])); + + if (data[IFLA_GRE_IKEY]) + parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); + + if (data[IFLA_GRE_OKEY]) + parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); + + if (data[IFLA_GRE_LOCAL]) + parms->laddr = nla_get_in6_addr(data[IFLA_GRE_LOCAL]); + + if (data[IFLA_GRE_REMOTE]) + parms->raddr = nla_get_in6_addr(data[IFLA_GRE_REMOTE]); + + if (data[IFLA_GRE_TTL]) + parms->hop_limit = nla_get_u8(data[IFLA_GRE_TTL]); + + if (data[IFLA_GRE_ENCAP_LIMIT]) + parms->encap_limit = nla_get_u8(data[IFLA_GRE_ENCAP_LIMIT]); + + if (data[IFLA_GRE_FLOWINFO]) + parms->flowinfo = nla_get_be32(data[IFLA_GRE_FLOWINFO]); + + if (data[IFLA_GRE_FLAGS]) + parms->flags = nla_get_u32(data[IFLA_GRE_FLAGS]); + + if (data[IFLA_GRE_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); + + if (data[IFLA_GRE_COLLECT_METADATA]) + parms->collect_md = true; + + if (data[IFLA_GRE_ERSPAN_VER]) + parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); + + if (parms->erspan_ver == 1) { + if (data[IFLA_GRE_ERSPAN_INDEX]) + parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + } else if (parms->erspan_ver == 2) { + if (data[IFLA_GRE_ERSPAN_DIR]) + parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); + if (data[IFLA_GRE_ERSPAN_HWID]) + parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); + } +} + +static int ip6gre_tap_init(struct net_device *dev) +{ + int ret; + + ret = ip6gre_tunnel_init_common(dev); + if (ret) + return ret; + + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + return 0; +} + +static const struct net_device_ops ip6gre_tap_netdev_ops = { + .ndo_init = ip6gre_tap_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6gre_tunnel_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +static int ip6erspan_tap_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int t_hlen; + int ret; + + tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (ret) { + free_percpu(dev->tstats); + dev->tstats = NULL; + return ret; + } + + tunnel->tun_hlen = 8; + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + + erspan_hdr_len(tunnel->parms.erspan_ver); + t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); + + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + tunnel = netdev_priv(dev); + ip6gre_tnl_link_config(tunnel, 1); + + return 0; +} + +static const struct net_device_ops ip6erspan_netdev_ops = { + .ndo_init = ip6erspan_tap_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6erspan_tunnel_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +static void ip6gre_tap_setup(struct net_device *dev) +{ + + ether_setup(dev); +#ifdef HAVE_NET_DEVICE_MAX_MTU + dev->max_mtu = 0; +#endif + dev->netdev_ops = &ip6gre_tap_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); +} + +static bool ip6gre_netlink_encap_parms(struct nlattr *data[], + struct ip_tunnel_encap *ipencap) +{ + bool ret = false; + + memset(ipencap, 0, sizeof(*ipencap)); + + if (!data) + return ret; + + if (data[IFLA_GRE_ENCAP_TYPE]) { + ret = true; + ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); + } + + if (data[IFLA_GRE_ENCAP_FLAGS]) { + ret = true; + ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); + } + + if (data[IFLA_GRE_ENCAP_SPORT]) { + ret = true; + ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); + } + + if (data[IFLA_GRE_ENCAP_DPORT]) { + ret = true; + ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); + } + + return ret; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct ip6_tnl *nt; + struct net *net = dev_net(dev); + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct ip_tunnel_encap ipencap; + int err; + + nt = netdev_priv(dev); + + if (ip6gre_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(nt, &ipencap); + + if (err < 0) + return err; + } + + ip6gre_netlink_parms(data, &nt->parms); + + if (nt->parms.collect_md) { + if (rtnl_dereference(ign->collect_md_tun)) + return -EEXIST; + } else { + if (ip6gre_tunnel_find(net, &nt->parms, dev->type)) + return -EEXIST; + } + + if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) + eth_hw_addr_random(dev); + + nt->dev = dev; + nt->net = dev_net(dev); + + err = register_netdevice(dev); + if (err) + goto out; + + ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); + + if (tb[IFLA_MTU]) + ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU])); + + dev_hold(dev); + ip6gre_tunnel_link(ign, nt); + +out: + return err; +} +#define ip6gre_newlink rpl_ip6gre_newlink + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + struct ip6_tnl *t, *nt = netdev_priv(dev); + struct net *net = nt->net; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct __ip6_tnl_parm p; + struct ip_tunnel_encap ipencap; + + if (dev == ign->fb_tunnel_dev) + return -EINVAL; + + if (ip6gre_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(nt, &ipencap); + + if (err < 0) + return err; + } + + ip6gre_netlink_parms(data, &p); + + t = ip6gre_tunnel_locate(net, &p, 0); + + if (t) { + if (t->dev != dev) + return -EEXIST; + } else { + t = nt; + } + + ip6gre_tunnel_unlink(ign, t); + ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); + ip6gre_tunnel_link(ign, t); + return 0; +} +#define ip6gre_changelink rpl_ip6gre_changelink + +static void ip6gre_dellink(struct net_device *dev, struct list_head *head) +{ + struct net *net = dev_net(dev); + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + if (dev != ign->fb_tunnel_dev) + unregister_netdevice_queue(dev, head); +} + +static size_t ip6gre_get_size(const struct net_device *dev) +{ + return + /* IFLA_GRE_LINK */ + nla_total_size(4) + + /* IFLA_GRE_IFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_OFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_IKEY */ + nla_total_size(4) + + /* IFLA_GRE_OKEY */ + nla_total_size(4) + + /* IFLA_GRE_LOCAL */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_GRE_REMOTE */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_GRE_TTL */ + nla_total_size(1) + + /* IFLA_GRE_ENCAP_LIMIT */ + nla_total_size(1) + + /* IFLA_GRE_FLOWINFO */ + nla_total_size(4) + + /* IFLA_GRE_FLAGS */ + nla_total_size(4) + + /* IFLA_GRE_ENCAP_TYPE */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_FLAGS */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_SPORT */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_DPORT */ + nla_total_size(2) + + /* IFLA_GRE_COLLECT_METADATA */ + nla_total_size(0) + + /* IFLA_GRE_FWMARK */ + nla_total_size(4) + + /* IFLA_GRE_ERSPAN_INDEX */ + nla_total_size(4) + + 0; +} + +static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm *p = &t->parms; + + if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || + nla_put_be16(skb, IFLA_GRE_IFLAGS, + gre_tnl_flags_to_gre_flags(p->i_flags)) || + nla_put_be16(skb, IFLA_GRE_OFLAGS, + gre_tnl_flags_to_gre_flags(p->o_flags)) || + nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || + nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || + nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || + nla_put_in6_addr(skb, IFLA_GRE_REMOTE, &p->raddr) || + nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) || + nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || + nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) || + nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) || + nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) || + nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) + goto nla_put_failure; + + if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, + t->encap.type) || + nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, + t->encap.sport) || + nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, + t->encap.dport) || + nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, + t->encap.flags)) + goto nla_put_failure; + + if (p->collect_md) { + if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) + goto nla_put_failure; + } + + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver)) + goto nla_put_failure; + + if (p->erspan_ver == 1) { + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) + goto nla_put_failure; + } else if (p->erspan_ver == 2) { + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir)) + goto nla_put_failure; + if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid)) + goto nla_put_failure; + } + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static const struct nla_policy ip6gre_policy[RPL_IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) }, + [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, + [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, +}; + +static void ip6erspan_tap_setup(struct net_device *dev) +{ + ether_setup(dev); + + dev->netdev_ops = &ip6erspan_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); +} + +static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { + .kind = "ip6gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6gre_tunnel_setup, + .validate = ip6gre_tunnel_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { + .kind = "ip6gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6gre_tap_setup, + .validate = ip6gre_tap_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = { + .kind = "ip6erspan", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6erspan_tap_setup, + .validate = ip6erspan_tap_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +struct net_device *ip6erspan_fb_dev_create(struct net *net, const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip6_tnl *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &ip6erspan_tap_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->parms.collect_md = true; + + err = ip6gre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = ip6_tnl_change_mtu(dev, 64000); + if (err) + goto out; + + return dev; +out: + ip6gre_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_erspan6_vport_ops; + +static struct vport *erspan6_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_erspan6_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = ip6erspan_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *erspan6_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = erspan6_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +#ifndef OVS_VPORT_TYPE_IP6ERSPAN +/* Just until integration */ +#define OVS_VPORT_TYPE_IP6ERSPAN 108 +#endif +static struct vport_ops ovs_erspan6_vport_ops = { + .type = OVS_VPORT_TYPE_IP6ERSPAN, + .create = erspan6_create, + .send = __ip6erspan_tunnel_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + +struct net_device *ip6gre_fb_dev_create(struct net *net, const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip6_tnl *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &ip6gre_tap_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->parms.collect_md = true; + + err = ip6gre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = ip6_tnl_change_mtu(dev, 64000); + if (err) + goto out; + + return dev; +out: + ip6gre_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_ip6gre_vport_ops; + +static struct vport *ip6gre_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_ip6gre_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = ip6gre_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *ip6gre_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = ip6gre_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +static struct vport_ops ovs_ip6gre_vport_ops = { + .type = OVS_VPORT_TYPE_IP6GRE, + .create = ip6gre_create, + .send = __ip6gre_tunnel_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + + +/* + * And now the modules code and kernel interface. + */ + +int rpl_ip6gre_init(void) +{ + int err; + + err = register_pernet_device(&ip6gre_net_ops); + if (err < 0) + return err; + + err = inet6_add_protocol(&ip6gre_protocol, IPPROTO_GRE); + if (err < 0) { + pr_info("%s: can't add protocol\n", __func__); + goto add_proto_failed; + } + + pr_info("GRE over IPv6 tunneling driver\n"); + ovs_vport_ops_register(&ovs_ip6gre_vport_ops); + ovs_vport_ops_register(&ovs_erspan6_vport_ops); + return 0; +out: + return err; + +add_proto_failed: + unregister_pernet_device(&ip6gre_net_ops); + goto out; +} + +void rpl_ip6gre_fini(void) +{ + ovs_vport_ops_unregister(&ovs_erspan6_vport_ops); + ovs_vport_ops_unregister(&ovs_ip6gre_vport_ops); + inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE); + unregister_pernet_device(&ip6gre_net_ops); +} +#endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/ip6_tunnel.c b/datapath/linux/compat/ip6_tunnel.c new file mode 100644 index 0000000..f9720a3 --- /dev/null +++ b/datapath/linux/compat/ip6_tunnel.c @@ -0,0 +1,2199 @@ +/* + * IPv6 tunneling device + * Linux INET6 implementation + * + * Authors: + * Ville Nuorvala + * Yasuyuki Kozakai + * + * Based on: + * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c + * + * RFC 2473 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#ifndef USE_UPSTREAM_TUNNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gso.h" +#include + +#include "vport-netdev.h" + +#define IP6_TUNNEL_HASH_SIZE_SHIFT 5 +#define IP6_TUNNEL_HASH_SIZE (1 << IP6_TUNNEL_HASH_SIZE_SHIFT) + +enum { +#ifndef HAVE_IFLA_IPTUN_ENCAP_TYPE + IFLA_IPTUN_ENCAP_TYPE = IFLA_IPTUN_6RD_RELAY_PREFIXLEN + 1, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT, +#endif +#ifndef HAVE_IFLA_IPTUN_COLLECT_METADTA + IFLA_IPTUN_COLLECT_METADATA = IFLA_IPTUN_ENCAP_DPORT + 1, + IFLA_IPTUN_FWMARK, +#endif + RPL__IFLA_IPTUN_MAX = IFLA_IPTUN_FWMARK + 1, +}; + +#define RPL_IFLA_IPTUN_MAX RPL__IFLA_IPTUN_MAX + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +/* Undef the one from ip_tunnels.h - we need a different one here */ +/* At least I think... */ +#undef iptunnel_handle_offloads +/* gre_handle_offloads() has different return type on older kernsl. */ +static void gre_nop_fix(struct sk_buff *skb) { } + +static void gre_csum_fix(struct sk_buff *skb) +{ + struct gre_base_hdr *greh; + __be32 *options; + int gre_offset = skb_transport_offset(skb); + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + options = ((__be32 *)greh + 1); + + *options = 0; + *(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset, + skb->len - gre_offset, 0)); +} + +#define iptunnel_handle_offloads rpl__iptunnel_handle_offloads +static int rpl__iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; + gso_fix_segment_t fix_segment; + + if (gre_csum) + fix_segment = gre_csum_fix; + else + fix_segment = gre_nop_fix; + + return ovs_iptunnel_handle_offloads(skb, type, fix_segment); +} + +#endif +static bool log_ecn_error = true; + +static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) +{ + u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); + + return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); +} + +static int ip6_tnl_dev_init(struct net_device *dev); +static void ip6_tnl_dev_setup(struct net_device *dev); +static struct rtnl_link_ops ip6_link_ops __read_mostly; + +static unsigned int ip6_tnl_net_id __read_mostly; +struct ip6_tnl_net { + /* the IPv6 tunnel fallback device */ + struct net_device *fb_tnl_dev; + /* lists for storing tunnels in use */ + struct ip6_tnl __rcu *tnls_r_l[IP6_TUNNEL_HASH_SIZE]; + struct ip6_tnl __rcu *tnls_wc[1]; + struct ip6_tnl __rcu **tnls[2]; + struct ip6_tnl __rcu *collect_md_tun; +}; + +static struct net_device_stats *ip6_get_stats(struct net_device *dev) +{ + struct pcpu_sw_netstats tmp, sum = { 0 }; + int i; + + for_each_possible_cpu(i) { + unsigned int start; + const struct pcpu_sw_netstats *tstats = + per_cpu_ptr(dev->tstats, i); + + do { + start = u64_stats_fetch_begin_irq(&tstats->syncp); + tmp.rx_packets = tstats->rx_packets; + tmp.rx_bytes = tstats->rx_bytes; + tmp.tx_packets = tstats->tx_packets; + tmp.tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); + + sum.rx_packets += tmp.rx_packets; + sum.rx_bytes += tmp.rx_bytes; + sum.tx_packets += tmp.tx_packets; + sum.tx_bytes += tmp.tx_bytes; + } + dev->stats.rx_packets = sum.rx_packets; + dev->stats.rx_bytes = sum.rx_bytes; + dev->stats.tx_packets = sum.tx_packets; + dev->stats.tx_bytes = sum.tx_bytes; + return &dev->stats; +} + +/** + * ip6_tnl_lookup - fetch tunnel matching the end-point addresses + * @remote: the address of the tunnel exit-point + * @local: the address of the tunnel entry-point + * + * Return: + * tunnel matching given end-points if found, + * else fallback tunnel if its device is up, + * else %NULL + **/ + +#define for_each_ip6_tunnel_rcu(start) \ + for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) + +static struct ip6_tnl * +ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local) +{ + unsigned int hash = HASH(remote, local); + struct ip6_tnl *t; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct in6_addr any; + + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + memset(&any, 0, sizeof(any)); + hash = HASH(&any, local); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_any(&t->parms.raddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + hash = HASH(remote, &any); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(remote, &t->parms.raddr) && + ipv6_addr_any(&t->parms.laddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + t = rcu_dereference(ip6n->collect_md_tun); + if (t && t->dev->flags & IFF_UP) + return t; + + t = rcu_dereference(ip6n->tnls_wc[0]); + if (t && (t->dev->flags & IFF_UP)) + return t; + + return NULL; +} + +/** + * ip6_tnl_bucket - get head of list matching given tunnel parameters + * @p: parameters containing tunnel end-points + * + * Description: + * ip6_tnl_bucket() returns the head of the list matching the + * &struct in6_addr entries laddr and raddr in @p. + * + * Return: head of IPv6 tunnel list + **/ + +static struct ip6_tnl __rcu ** +ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + unsigned int h = 0; + int prio = 0; + + if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { + prio = 1; + h = HASH(remote, local); + } + return &ip6n->tnls[prio][h]; +} + +/** + * ip6_tnl_link - add tunnel to hash table + * @t: tunnel to be added + **/ + +static void +ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); + + if (t->parms.collect_md) + rcu_assign_pointer(ip6n->collect_md_tun, t); + rcu_assign_pointer(t->next , rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); +} + +/** + * ip6_tnl_unlink - remove tunnel from hash table + * @t: tunnel to be removed + **/ + +static void +ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp; + struct ip6_tnl *iter; + + if (t->parms.collect_md) + rcu_assign_pointer(ip6n->collect_md_tun, NULL); + + for (tp = ip6_tnl_bucket(ip6n, &t->parms); + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { + rcu_assign_pointer(*tp, t->next); + break; + } + } +} + +#ifdef HAVE_NEEDS_FREE_NETDEV +static void ip6_dev_free(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + gro_cells_destroy(&t->gro_cells); + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +} + +#endif +static int ip6_tnl_create2(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + int err; + + t = netdev_priv(dev); + + dev->rtnl_link_ops = &ip6_link_ops; + err = register_netdevice(dev); + if (err < 0) + goto out; + + strcpy(t->parms.name, dev->name); + + dev_hold(dev); + ip6_tnl_link(ip6n, t); + return 0; + +out: + return err; +} + +/** + * ip6_tnl_create - create a new tunnel + * @p: tunnel parameters + * @pt: pointer to new tunnel + * + * Description: + * Create tunnel matching given parameters. + * + * Return: + * created tunnel or error pointer + **/ + +static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) +{ + struct net_device *dev; + struct ip6_tnl *t; + char name[IFNAMSIZ]; + int err = -ENOMEM; + + if (p->name[0]) + strlcpy(name, p->name, IFNAMSIZ); + else + sprintf(name, "ip6tnl%%d"); + + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, + ip6_tnl_dev_setup); + if (!dev) + goto failed; + + dev_net_set(dev, net); + + t = netdev_priv(dev); + t->parms = *p; + t->net = dev_net(dev); + err = ip6_tnl_create2(dev); + if (err < 0) + goto failed_free; + + return t; + +failed_free: + free_netdev(dev); +failed: + return ERR_PTR(err); +} + +/** + * ip6_tnl_locate - find or create tunnel matching given parameters + * @p: tunnel parameters + * @create: != 0 if allowed to create new tunnel if no match found + * + * Description: + * ip6_tnl_locate() first tries to locate an existing tunnel + * based on @parms. If this is unsuccessful, but @create is set a new + * tunnel device is created and registered for use. + * + * Return: + * matching tunnel or error pointer + **/ + +static struct ip6_tnl *ip6_tnl_locate(struct net *net, + struct __ip6_tnl_parm *p, int create) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + struct ip6_tnl __rcu **tp; + struct ip6_tnl *t; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + for (tp = ip6_tnl_bucket(ip6n, p); + (t = rtnl_dereference(*tp)) != NULL; + tp = &t->next) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr)) { + if (create) + return ERR_PTR(-EEXIST); + + return t; + } + } + if (!create) + return ERR_PTR(-ENODEV); + return ip6_tnl_create(net, p); +} + +/** + * ip6_tnl_dev_uninit - tunnel device uninitializer + * @dev: the device to be destroyed + * + * Description: + * ip6_tnl_dev_uninit() removes tunnel from its list + **/ + +static void +ip6_tnl_dev_uninit(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + if (dev == ip6n->fb_tnl_dev) + RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); + else + ip6_tnl_unlink(ip6n, t); + dst_cache_reset(&t->dst_cache); + dev_put(dev); +} + +/** + * parse_tvl_tnl_enc_lim - handle encapsulation limit option + * @skb: received socket buffer + * + * Return: + * 0 if none was found, + * else index to encapsulation limit + **/ + +__u16 rpl_ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) +{ + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; + unsigned int nhoff = raw - skb->data; + unsigned int off = nhoff + sizeof(*ipv6h); + u8 next, nexthdr = ipv6h->nexthdr; + + while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { + struct ipv6_opt_hdr *hdr; + u16 optlen; + + if (!pskb_may_pull(skb, off + sizeof(*hdr))) + break; + + hdr = (struct ipv6_opt_hdr *)(skb->data + off); + if (nexthdr == NEXTHDR_FRAGMENT) { + struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; + if (frag_hdr->frag_off) + break; + optlen = 8; + } else if (nexthdr == NEXTHDR_AUTH) { + optlen = (hdr->hdrlen + 2) << 2; + } else { + optlen = ipv6_optlen(hdr); + } + /* cache hdr->nexthdr, since pskb_may_pull() might + * invalidate hdr + */ + next = hdr->nexthdr; + if (nexthdr == NEXTHDR_DEST) { + u16 i = 2; + + /* Remember : hdr is no longer valid at this point. */ + if (!pskb_may_pull(skb, off + optlen)) + break; + + while (1) { + struct ipv6_tlv_tnl_enc_lim *tel; + + /* No more room for encapsulation limit */ + if (i + sizeof(*tel) > optlen) + break; + + tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i); + /* return index of option if found and valid */ + if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT && + tel->length == 1) + return i + off - nhoff; + /* else jump to next option */ + if (tel->type) + i += tel->length + 2; + else + i++; + } + } + nexthdr = next; + off += optlen; + } + return 0; +} + +static int +ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return PACKET_REJECT; +} + +static int +ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return PACKET_REJECT; +} + +static int ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb) +{ + __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; + + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); + + return IP6_ECN_decapsulate(ipv6h, skb); +} + +static int ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb) +{ + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); + + return IP6_ECN_decapsulate(ipv6h, skb); +} + +__u32 rpl_ip6_tnl_get_cap(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ltype = ipv6_addr_type(laddr); + int rtype = ipv6_addr_type(raddr); + __u32 flags = 0; + + if (ltype == IPV6_ADDR_ANY || rtype == IPV6_ADDR_ANY) { + flags = IP6_TNL_F_CAP_PER_PACKET; + } else if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + !((ltype|rtype) & IPV6_ADDR_LOOPBACK) && + (!((ltype|rtype) & IPV6_ADDR_LINKLOCAL) || p->link)) { + if (ltype&IPV6_ADDR_UNICAST) + flags |= IP6_TNL_F_CAP_XMIT; + if (rtype&IPV6_ADDR_UNICAST) + flags |= IP6_TNL_F_CAP_RCV; + } + return flags; +} + +/* called with rcu_read_lock() */ +int rpl_ip6_tnl_rcv_ctl(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ret = 0; + struct net *net = t->net; + + if ((p->flags & IP6_TNL_F_CAP_RCV) || + ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && + (rpl_ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_RCV))) { + struct net_device *ldev = NULL; + + if (p->link) + ldev = dev_get_by_index_rcu(net, p->link); + + if ((ipv6_addr_is_multicast(laddr) || + likely(ipv6_chk_addr(net, laddr, ldev, 0))) && + ((p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) || + likely(!ipv6_chk_addr(net, raddr, NULL, 0)))) + ret = 1; + } + return ret; +} + +static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb), + bool log_ecn_err) +{ + struct pcpu_sw_netstats *tstats; + + if ((!(tpi->flags & TUNNEL_CSUM) && + (tunnel->parms.i_flags & TUNNEL_CSUM)) || + ((tpi->flags & TUNNEL_CSUM) && + !(tunnel->parms.i_flags & TUNNEL_CSUM))) { + tunnel->dev->stats.rx_crc_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + + if (tunnel->parms.i_flags & TUNNEL_SEQ) { + if (!(tpi->flags & TUNNEL_SEQ) || + (tunnel->i_seqno && + (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) { + tunnel->dev->stats.rx_fifo_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + tunnel->i_seqno = ntohl(tpi->seq) + 1; + } + +#if 0 + /* Warning: All skb pointers will be invalidated! */ + if (tunnel->dev->type == ARPHRD_ETHER) { + if (!pskb_may_pull(skb, ETH_HLEN)) { + tunnel->dev->stats.rx_length_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + + ipv6h = ipv6_hdr(skb); + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + } else { + skb->dev = tunnel->dev; + } + + skb_reset_network_header(skb); + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + + __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); + + err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); + if (unlikely(err)) { + if (log_ecn_err) + net_info_ratelimited("non-ECT from %pI6 with DS=%#x\n", + &ipv6h->saddr, + ipv6_get_dsfield(ipv6h)); + if (err > 1) { + ++tunnel->dev->stats.rx_frame_errors; + ++tunnel->dev->stats.rx_errors; + goto drop; + } + } + +#endif + tstats = this_cpu_ptr(tunnel->dev->tstats); + u64_stats_update_begin(&tstats->syncp); + tstats->rx_packets++; + tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); + + skb_reset_mac_header(skb); + skb_scrub_packet(skb, false); + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + ovs_skb_dst_set(skb, (struct dst_entry *)tun_dst); + netdev_port_receive(skb, &tun_dst->u.tun_info); + return 0; + +drop: + /* In OVS case caller will free tun_dst and skb */ +#if 0 + if (tun_dst) + dst_release((struct dst_entry *)tun_dst); + kfree_skb(skb); +#endif + return 0; +} + +int rpl_ip6_tnl_rcv(struct ip6_tnl *t, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + bool log_ecn_err) +{ + return __ip6_tnl_rcv(t, skb, tpi, tun_dst, ip6ip6_dscp_ecn_decapsulate, + log_ecn_err); +} + +static const struct tnl_ptk_info tpi_v6 = { + /* no tunnel info required for ipxip6. */ + .proto = htons(ETH_P_IPV6), +}; + +static const struct tnl_ptk_info tpi_v4 = { + /* no tunnel info required for ipxip6. */ + .proto = htons(ETH_P_IP), +}; + +static int ipxip6_rcv(struct sk_buff *skb, u8 ipproto, + const struct tnl_ptk_info *tpi, + int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb)) +{ + struct ip6_tnl *t; + const struct ipv6hdr *ipv6h = ipv6_hdr(skb); + struct metadata_dst *tun_dst = NULL; + int ret = -1; + + rcu_read_lock(); + t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, &ipv6h->daddr); + + if (t) { + u8 tproto = READ_ONCE(t->parms.proto); + + if (tproto != ipproto && tproto != 0) + goto drop; + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto drop; + if (!rpl_ip6_tnl_rcv_ctl(t, &ipv6h->daddr, &ipv6h->saddr)) + goto drop; + if (iptunnel_pull_header(skb, 0, tpi->proto, false)) + goto drop; + if (t->parms.collect_md) { + ovs_ipv6_tun_rx_dst(tun_dst, skb, 0, 0, 0); + if (!tun_dst) + goto drop; + } + ret = __ip6_tnl_rcv(t, skb, tpi, tun_dst, dscp_ecn_decapsulate, + log_ecn_error); + } + + rcu_read_unlock(); + + return ret; + +drop: + rcu_read_unlock(); + kfree_skb(skb); + return 0; +} + +static int ip4ip6_rcv(struct sk_buff *skb) +{ + return ipxip6_rcv(skb, IPPROTO_IPIP, &tpi_v4, + ip4ip6_dscp_ecn_decapsulate); +} + +static int ip6ip6_rcv(struct sk_buff *skb) +{ + return ipxip6_rcv(skb, IPPROTO_IPV6, &tpi_v6, + ip6ip6_dscp_ecn_decapsulate); +} + +struct ipv6_tel_txoption { + struct ipv6_txoptions ops; + __u8 dst_opt[8]; +}; + +static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) +{ + memset(opt, 0, sizeof(struct ipv6_tel_txoption)); + + opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT; + opt->dst_opt[3] = 1; + opt->dst_opt[4] = encap_limit; + opt->dst_opt[5] = IPV6_TLV_PADN; + opt->dst_opt[6] = 1; + + opt->ops.dst1opt = (struct ipv6_opt_hdr *) opt->dst_opt; + opt->ops.opt_nflen = 8; +} + +/** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device + * @hdr: IPv6 header from the incoming packet + * + * Description: + * Avoid trivial tunneling loop by checking that tunnel exit-point + * doesn't match source of incoming packet. + * + * Return: + * 1 if conflict, + * 0 else + **/ + +static inline bool +ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) +{ + return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); +} + +int rpl_ip6_tnl_xmit_ctl(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ret = 0; + struct net *net = t->net; + + if (t->parms.collect_md) + return 1; + + if ((p->flags & IP6_TNL_F_CAP_XMIT) || + ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && + (rpl_ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_XMIT))) { + struct net_device *ldev = NULL; + + rcu_read_lock(); + if (p->link) + ldev = dev_get_by_index_rcu(net, p->link); + + if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0))) + pr_warn("%s xmit: Local address not yet configured!\n", + p->name); + else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) && + !ipv6_addr_is_multicast(raddr) && + unlikely(ipv6_chk_addr(net, raddr, NULL, 0))) + pr_warn("%s xmit: Routing loop! Remote address found on this node!\n", + p->name); + else + ret = 1; + rcu_read_unlock(); + } + return ret; +} + +static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, + u8 type, struct ipv6_opt_hdr *opt) +{ + struct ipv6_opt_hdr *h = + (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt)); + + memcpy(h, opt, ipv6_optlen(opt)); + h->nexthdr = *proto; + *proto = type; +} + +void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, + u8 *proto) +{ + if (opt->dst1opt) + ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt); +} + +/** + * ip6_tnl_xmit - encapsulate packet and send + * @skb: the outgoing socket buffer + * @dev: the outgoing tunnel device + * @dsfield: dscp code for outer header + * @fl6: flow of tunneled packet + * @encap_limit: encapsulation limit + * @pmtu: Path MTU is stored if packet is too big + * @proto: next header value + * + * Description: + * Build new header and do some sanity checks on the packet before sending + * it. + * + * Return: + * 0 on success + * -1 fail + * %-EMSGSIZE message too big. return mtu in this case. + **/ + +int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, __u32 *pmtu, + __u8 proto) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct net_device_stats *stats = &t->dev->stats; + struct ipv6hdr *ipv6h; + struct ipv6_tel_txoption opt; + struct dst_entry *dst = NULL, *ndst = NULL; + struct net_device *tdev; + int mtu; + unsigned int eth_hlen = t->dev->type == ARPHRD_ETHER ? ETH_HLEN : 0; + unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen; + unsigned int max_headroom = psh_hlen; + bool use_cache = false; + u8 hop_limit; + int err = -1; + + if (t->parms.collect_md) { + hop_limit = skb_tunnel_info(skb)->key.ttl; + goto route_lookup; + } else { + hop_limit = t->parms.hop_limit; + } + + /* NBMA tunnel */ + if (ipv6_addr_any(&t->parms.raddr)) { + if (skb->protocol == htons(ETH_P_IPV6)) { + struct in6_addr *addr6; + struct neighbour *neigh; + int addr_type; + + if (!skb_dst(skb)) + goto tx_err_link_failure; + + neigh = dst_neigh_lookup(skb_dst(skb), + &ipv6_hdr(skb)->daddr); + if (!neigh) + goto tx_err_link_failure; + + addr6 = (struct in6_addr *)&neigh->primary_key; + addr_type = ipv6_addr_type(addr6); + + if (addr_type == IPV6_ADDR_ANY) + addr6 = &ipv6_hdr(skb)->daddr; + + memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr)); + neigh_release(neigh); + } + } else if (t->parms.proto != 0 && !(t->parms.flags & + (IP6_TNL_F_USE_ORIG_TCLASS | + IP6_TNL_F_USE_ORIG_FWMARK))) { + /* enable the cache only if neither the outer protocol nor the + * routing decision depends on the current inner header value + */ + use_cache = true; + } + + if (use_cache) + dst = dst_cache_get(&t->dst_cache); + + if (!rpl_ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) + goto tx_err_link_failure; + + if (!dst) { +route_lookup: + /* add dsfield to flowlabel for route lookup */ + fl6->flowlabel = ip6_make_flowinfo(dsfield, fl6->flowlabel); + + dst = ip6_route_output(net, NULL, fl6); + + if (dst->error) + goto tx_err_link_failure; + dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0); + if (IS_ERR(dst)) { + err = PTR_ERR(dst); + dst = NULL; + goto tx_err_link_failure; + } + if (t->parms.collect_md && + ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev, + &fl6->daddr, 0, &fl6->saddr)) + goto tx_err_link_failure; + ndst = dst; + } + + tdev = dst->dev; + + if (tdev == dev) { + stats->collisions++; + net_warn_ratelimited("%s: Local routing loop detected!\n", + t->parms.name); + goto tx_err_dst_release; + } + mtu = dst_mtu(dst) - eth_hlen - psh_hlen - t->tun_hlen; + if (encap_limit >= 0) { + max_headroom += 8; + mtu -= 8; + } + if (skb->protocol == htons(ETH_P_IPV6)) { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + } else if (mtu < 576) { + mtu = 576; + } + +// FIX ME +// skb_dst_update_pmtu(skb, mtu); + if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) { + *pmtu = mtu; + err = -EMSGSIZE; + goto tx_err_dst_release; + } + + if (t->err_count > 0) { + if (time_before(jiffies, + t->err_time + IP6TUNNEL_ERR_TIMEO)) { + t->err_count--; + + dst_link_failure(skb); + } else { + t->err_count = 0; + } + } + + skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); + + /* + * Okay, now see if we can stuff it in the buffer as-is. + */ + max_headroom += LL_RESERVED_SPACE(tdev); + + if (skb_headroom(skb) < max_headroom || skb_shared(skb) || + (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { + struct sk_buff *new_skb; + + new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) + goto tx_err_dst_release; + + if (skb->sk) + skb_set_owner_w(new_skb, skb->sk); + consume_skb(skb); + skb = new_skb; + } + + if (t->parms.collect_md) { + if (t->encap.type != TUNNEL_ENCAP_NONE) + goto tx_err_dst_release; + } else { + if (use_cache && ndst) + dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr); + } + skb_dst_set(skb, dst); + + if (encap_limit >= 0) { + init_tel_txopt(&opt, encap_limit); + ipv6_push_frag_opts(skb, &opt.ops, &proto); + } + hop_limit = hop_limit ? : ip6_dst_hoplimit(dst); + + /* Calculate max headroom for all the headers and adjust + * needed_headroom if necessary. + */ + max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr) + + dst->header_len + t->hlen; + if (max_headroom > dev->needed_headroom) + dev->needed_headroom = max_headroom; + + err = ip6_tnl_encap(skb, t, &proto, fl6); + if (err) + return err; + + skb_push(skb, sizeof(struct ipv6hdr)); + skb_reset_network_header(skb); + ipv6h = ipv6_hdr(skb); + ip6_flow_hdr(ipv6h, dsfield, + ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6)); + ipv6h->hop_limit = hop_limit; + ipv6h->nexthdr = proto; + ipv6h->saddr = fl6->saddr; + ipv6h->daddr = fl6->daddr; + ip6tunnel_xmit(NULL, skb, dev); + return 0; +tx_err_link_failure: + stats->tx_carrier_errors++; + dst_link_failure(skb); +tx_err_dst_release: + dst_release(dst); + return err; +} +EXPORT_SYMBOL(ip6_tnl_xmit); + +static inline int +ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + const struct iphdr *iph = ip_hdr(skb); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield; + __u32 mtu; + u8 tproto; + int err; + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + + tproto = READ_ONCE(t->parms.proto); + if (tproto != IPPROTO_IPIP && tproto != 0) + return -1; + + if (t->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -1; + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPIP; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + dsfield = key->tos; + } else { + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPIP; + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + dsfield = ipv4_get_dsfield(iph); + else + dsfield = ip6_tclass(t->parms.flowinfo); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6.flowi6_mark = skb->mark; + else + fl6.flowi6_mark = t->parms.fwmark; + } + +// FIX ME +// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + + dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph)); + + skb_set_inner_ipproto(skb, IPPROTO_IPIP); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + IPPROTO_IPIP); + if (err != 0) { + /* XXX: send ICMP error even if DF is not set. */ + if (err == -EMSGSIZE) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + return -1; + } + + return 0; +} + +static inline int +ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + int encap_limit = -1; + __u16 offset; + struct flowi6 fl6; + __u8 dsfield; + __u32 mtu; + u8 tproto; + int err; + + tproto = READ_ONCE(t->parms.proto); + if ((tproto != IPPROTO_IPV6 && tproto != 0) || + ip6_tnl_addr_conflict(t, ipv6h)) + return -1; + + if (t->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -1; + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPV6; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + dsfield = key->tos; + } else { + offset = rpl_ip6_tnl_parse_tlv_enc_lim(skb, + skb_network_header(skb)); + /* + * ip6_tnl_parse_tlv_enc_lim() might + * have reallocated skb->head + */ + ipv6h = ipv6_hdr(skb); + if (offset > 0) { + struct ipv6_tlv_tnl_enc_lim *tel; + + tel = (void *)&skb_network_header(skb)[offset]; + if (tel->encap_limit == 0) { + icmpv6_send(skb, ICMPV6_PARAMPROB, + ICMPV6_HDR_FIELD, offset + 2); + return -1; + } + encap_limit = tel->encap_limit - 1; + } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { + encap_limit = t->parms.encap_limit; + } + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPV6; + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + dsfield = ipv6_get_dsfield(ipv6h); + else + dsfield = ip6_tclass(t->parms.flowinfo); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) + fl6.flowlabel |= ip6_flowlabel(ipv6h); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6.flowi6_mark = skb->mark; + else + fl6.flowi6_mark = t->parms.fwmark; + } + +// FIX ME +// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + + dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); + + skb_set_inner_ipproto(skb, IPPROTO_IPV6); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + IPPROTO_IPV6); + if (err != 0) { + if (err == -EMSGSIZE) + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -1; + } + + return 0; +} + +static netdev_tx_t +ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net_device_stats *stats = &t->dev->stats; + int ret; + + switch (skb->protocol) { + case htons(ETH_P_IP): + ret = ip4ip6_tnl_xmit(skb, dev); + break; + case htons(ETH_P_IPV6): + ret = ip6ip6_tnl_xmit(skb, dev); + break; + default: + goto tx_err; + } + + if (ret < 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static void ip6_tnl_link_config(struct ip6_tnl *t) +{ + struct net_device *dev = t->dev; + struct __ip6_tnl_parm *p = &t->parms; + struct flowi6 *fl6 = &t->fl.u.ip6; + int t_hlen; + + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + + /* Set up flowi template */ + fl6->saddr = p->laddr; + fl6->daddr = p->raddr; + fl6->flowi6_oif = p->link; + fl6->flowlabel = 0; + + if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) + fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; + if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) + fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; + + p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV|IP6_TNL_F_CAP_PER_PACKET); + p->flags |= rpl_ip6_tnl_get_cap(t, &p->laddr, &p->raddr); + + if (p->flags&IP6_TNL_F_CAP_XMIT && p->flags&IP6_TNL_F_CAP_RCV) + dev->flags |= IFF_POINTOPOINT; + else + dev->flags &= ~IFF_POINTOPOINT; + + t->tun_hlen = 0; + t->hlen = t->encap_hlen + t->tun_hlen; + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); + + struct rt6_info *rt = rt6_lookup(t->net, + &p->raddr, &p->laddr, + p->link, strict); + + if (!rt) + return; + + if (rt->dst.dev) { + dev->hard_header_len = rt->dst.dev->hard_header_len + + t_hlen; + + dev->mtu = rt->dst.dev->mtu - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + if (dev->mtu < IPV6_MIN_MTU) + dev->mtu = IPV6_MIN_MTU; + } + ip6_rt_put(rt); + } +} + +/** + * ip6_tnl_change - update the tunnel parameters + * @t: tunnel to be changed + * @p: tunnel configuration parameters + * + * Description: + * ip6_tnl_change() updates the tunnel parameters + **/ + +static int +ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) +{ + t->parms.laddr = p->laddr; + t->parms.raddr = p->raddr; + t->parms.flags = p->flags; + t->parms.hop_limit = p->hop_limit; + t->parms.encap_limit = p->encap_limit; + t->parms.flowinfo = p->flowinfo; + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.fwmark = p->fwmark; + dst_cache_reset(&t->dst_cache); + ip6_tnl_link_config(t); + return 0; +} + +static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +{ + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + int err; + + ip6_tnl_unlink(ip6n, t); + synchronize_net(); + err = ip6_tnl_change(t, p); + ip6_tnl_link(ip6n, t); + netdev_state_change(t->dev); + return err; +} + +static int ip6_tnl0_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +{ + /* for default tnl0 device allow to change only the proto */ + t->parms.proto = p->proto; + netdev_state_change(t->dev); + return 0; +} + +static void +ip6_tnl_parm_from_user(struct __ip6_tnl_parm *p, const struct ip6_tnl_parm *u) +{ + p->laddr = u->laddr; + p->raddr = u->raddr; + p->flags = u->flags; + p->hop_limit = u->hop_limit; + p->encap_limit = u->encap_limit; + p->flowinfo = u->flowinfo; + p->link = u->link; + p->proto = u->proto; + memcpy(p->name, u->name, sizeof(u->name)); +} + +static void +ip6_tnl_parm_to_user(struct ip6_tnl_parm *u, const struct __ip6_tnl_parm *p) +{ + u->laddr = p->laddr; + u->raddr = p->raddr; + u->flags = p->flags; + u->hop_limit = p->hop_limit; + u->encap_limit = p->encap_limit; + u->flowinfo = p->flowinfo; + u->link = p->link; + u->proto = p->proto; + memcpy(u->name, p->name, sizeof(u->name)); +} + +/** + * ip6_tnl_ioctl - configure ipv6 tunnels from userspace + * @dev: virtual device associated with tunnel + * @ifr: parameters passed from userspace + * @cmd: command to be performed + * + * Description: + * ip6_tnl_ioctl() is used for managing IPv6 tunnels + * from userspace. + * + * The possible commands are the following: + * %SIOCGETTUNNEL: get tunnel parameters for device + * %SIOCADDTUNNEL: add tunnel matching given tunnel parameters + * %SIOCCHGTUNNEL: change tunnel parameters to those given + * %SIOCDELTUNNEL: delete tunnel + * + * The fallback device "ip6tnl0", created during module + * initialization, can be used for creating other tunnel devices. + * + * Return: + * 0 on success, + * %-EFAULT if unable to copy data to or from userspace, + * %-EPERM if current process hasn't %CAP_NET_ADMIN set + * %-EINVAL if passed tunnel parameters are invalid, + * %-EEXIST if changing a tunnel's parameters would cause a conflict + * %-ENODEV if attempting to change or delete a nonexisting device + **/ + +static int +ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + int err = 0; + struct ip6_tnl_parm p; + struct __ip6_tnl_parm p1; + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + memset(&p1, 0, sizeof(p1)); + + switch (cmd) { + case SIOCGETTUNNEL: + if (dev == ip6n->fb_tnl_dev) { + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { + err = -EFAULT; + break; + } + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, 0); + if (IS_ERR(t)) + t = netdev_priv(dev); + } else { + memset(&p, 0, sizeof(p)); + } + ip6_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) { + err = -EFAULT; + } + break; + case SIOCADDTUNNEL: + case SIOCCHGTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + break; + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + break; + err = -EINVAL; + if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && + p.proto != 0) + break; + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, cmd == SIOCADDTUNNEL); + if (cmd == SIOCCHGTUNNEL) { + if (!IS_ERR(t)) { + if (t->dev != dev) { + err = -EEXIST; + break; + } + } else + t = netdev_priv(dev); + if (dev == ip6n->fb_tnl_dev) + err = ip6_tnl0_update(t, &p1); + else + err = ip6_tnl_update(t, &p1); + } + if (!IS_ERR(t)) { + err = 0; + ip6_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + + } else { + err = PTR_ERR(t); + } + break; + case SIOCDELTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + break; + + if (dev == ip6n->fb_tnl_dev) { + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + break; + err = -ENOENT; + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, 0); + if (IS_ERR(t)) + break; + err = -EPERM; + if (t->dev == ip6n->fb_tnl_dev) + break; + dev = t->dev; + } + err = 0; + unregister_netdevice(dev); + break; + default: + err = -EINVAL; + } + return err; +} + +/** + * ip6_tnl_change_mtu - change mtu manually for tunnel device + * @dev: virtual device associated with tunnel + * @new_mtu: the new mtu + * + * Return: + * 0 on success, + * %-EINVAL if mtu too small + **/ + +int rpl_ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) +{ + struct ip6_tnl *tnl = netdev_priv(dev); + + if (tnl->parms.proto == IPPROTO_IPV6) { + if (new_mtu < IPV6_MIN_MTU) + return -EINVAL; + } else { + if (new_mtu < ETH_MIN_MTU) + return -EINVAL; + } + if (new_mtu > 0xFFF8 - dev->hard_header_len) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +#ifdef HAVE_NDO_GET_IFLINK +int rpl_ip6_tnl_get_iflink(const struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + return t->parms.link; +} + +#endif +const struct ip6_tnl_encap_ops __rcu * + rpl_ip6tun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly; + +int rpl_ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num) +{ + if (num >= MAX_IPTUN_ENCAP_OPS) + return -ERANGE; + + return !cmpxchg((const struct ip6_tnl_encap_ops **) + &rpl_ip6tun_encaps[num], + NULL, ops) ? 0 : -1; +} + +int rpl_ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num) +{ + int ret; + + if (num >= MAX_IPTUN_ENCAP_OPS) + return -ERANGE; + + ret = (cmpxchg((const struct ip6_tnl_encap_ops **) + &rpl_ip6tun_encaps[num], + ops, NULL) == ops) ? 0 : -1; + + synchronize_net(); + + return ret; +} + +int rpl_ip6_tnl_encap_setup(struct ip6_tnl *t, + struct ip_tunnel_encap *ipencap) +{ + int hlen; + + memset(&t->encap, 0, sizeof(t->encap)); + + hlen = ip6_encap_hlen(ipencap); + if (hlen < 0) + return hlen; + + t->encap.type = ipencap->type; + t->encap.sport = ipencap->sport; + t->encap.dport = ipencap->dport; + t->encap.flags = ipencap->flags; + + t->encap_hlen = hlen; + t->hlen = t->encap_hlen + t->tun_hlen; + + return 0; +} + +static const struct net_device_ops ip6_tnl_netdev_ops = { + .ndo_init = ip6_tnl_dev_init, + .ndo_uninit = ip6_tnl_dev_uninit, + .ndo_start_xmit = ip6_tnl_start_xmit, + .ndo_do_ioctl = ip6_tnl_ioctl, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats = ip6_get_stats, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +#define IPXIPX_FEATURES (NETIF_F_SG | \ + NETIF_F_FRAGLIST | \ + NETIF_F_HIGHDMA | \ + NETIF_F_GSO_SOFTWARE | \ + NETIF_F_HW_CSUM) + +/** + * ip6_tnl_dev_setup - setup virtual tunnel device + * @dev: virtual device associated with tunnel + * + * Description: + * Initialize function pointers and device parameters + **/ + +static void ip6_tnl_dev_setup(struct net_device *dev) +{ + dev->netdev_ops = &ip6_tnl_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6_dev_free; +#endif + + dev->type = ARPHRD_TUNNEL6; + dev->flags |= IFF_NOARP; + dev->addr_len = sizeof(struct in6_addr); + dev->features |= NETIF_F_LLTX; + netif_keep_dst(dev); + + dev->features |= IPXIPX_FEATURES; + dev->hw_features |= IPXIPX_FEATURES; + + /* This perm addr will be used as interface identifier by IPv6 */ + dev->addr_assign_type = NET_ADDR_RANDOM; + eth_random_addr(dev->perm_addr); +} + + +/** + * ip6_tnl_dev_init_gen - general initializer for all tunnel devices + * @dev: virtual device associated with tunnel + **/ + +static inline int +ip6_tnl_dev_init_gen(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int ret; + int t_hlen; + + t->dev = dev; + t->net = dev_net(dev); + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); + if (ret) + goto free_stats; + + ret = gro_cells_init(&t->gro_cells, dev); + if (ret) + goto destroy_dst; + + t->tun_hlen = 0; + t->hlen = t->encap_hlen + t->tun_hlen; + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + dev->type = ARPHRD_TUNNEL6; + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; +#ifdef HAVE_NET_DEVICE_MAX_MTU + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = 0xFFF8 - dev->hard_header_len; +#endif + + return 0; + +destroy_dst: + dst_cache_destroy(&t->dst_cache); +free_stats: + free_percpu(dev->tstats); + dev->tstats = NULL; + + return ret; +} + +/** + * ip6_tnl_dev_init - initializer for all non fallback tunnel devices + * @dev: virtual device associated with tunnel + **/ + +static int ip6_tnl_dev_init(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int err = ip6_tnl_dev_init_gen(dev); + + if (err) + return err; + ip6_tnl_link_config(t); + if (t->parms.collect_md) { + dev->features |= NETIF_F_NETNS_LOCAL; + netif_keep_dst(dev); + } + return 0; +} + +/** + * ip6_fb_tnl_dev_init - initializer for fallback tunnel device + * @dev: fallback device + * + * Return: 0 + **/ + +static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + u8 proto; + + if (!data || !data[IFLA_IPTUN_PROTO]) + return 0; + + proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); + if (proto != IPPROTO_IPV6 && + proto != IPPROTO_IPIP && + proto != 0) + return -EINVAL; + + return 0; +} +#define ip6_tnl_validate rpl_ip6_tnl_validate + +static void ip6_tnl_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) +{ + memset(parms, 0, sizeof(*parms)); + + if (!data) + return; + + if (data[IFLA_IPTUN_LINK]) + parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]); + + if (data[IFLA_IPTUN_LOCAL]) + parms->laddr = nla_get_in6_addr(data[IFLA_IPTUN_LOCAL]); + + if (data[IFLA_IPTUN_REMOTE]) + parms->raddr = nla_get_in6_addr(data[IFLA_IPTUN_REMOTE]); + + if (data[IFLA_IPTUN_TTL]) + parms->hop_limit = nla_get_u8(data[IFLA_IPTUN_TTL]); + + if (data[IFLA_IPTUN_ENCAP_LIMIT]) + parms->encap_limit = nla_get_u8(data[IFLA_IPTUN_ENCAP_LIMIT]); + + if (data[IFLA_IPTUN_FLOWINFO]) + parms->flowinfo = nla_get_be32(data[IFLA_IPTUN_FLOWINFO]); + + if (data[IFLA_IPTUN_FLAGS]) + parms->flags = nla_get_u32(data[IFLA_IPTUN_FLAGS]); + + if (data[IFLA_IPTUN_PROTO]) + parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); + + if (data[IFLA_IPTUN_COLLECT_METADATA]) + parms->collect_md = true; + + if (data[IFLA_IPTUN_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); +} + +static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], + struct ip_tunnel_encap *ipencap) +{ + bool ret = false; + + memset(ipencap, 0, sizeof(*ipencap)); + + if (!data) + return ret; + + if (data[IFLA_IPTUN_ENCAP_TYPE]) { + ret = true; + ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]); + } + + if (data[IFLA_IPTUN_ENCAP_FLAGS]) { + ret = true; + ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]); + } + + if (data[IFLA_IPTUN_ENCAP_SPORT]) { + ret = true; + ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]); + } + + if (data[IFLA_IPTUN_ENCAP_DPORT]) { + ret = true; + ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]); + } + + return ret; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip_tunnel_encap ipencap; + struct ip6_tnl *nt, *t; + int err; + + nt = netdev_priv(dev); + + if (ip6_tnl_netlink_encap_parms(data, &ipencap)) { + err = ip6_tnl_encap_setup(nt, &ipencap); + if (err < 0) + return err; + } + + ip6_tnl_netlink_parms(data, &nt->parms); + + if (nt->parms.collect_md) { + if (rtnl_dereference(ip6n->collect_md_tun)) + return -EEXIST; + } else { + t = ip6_tnl_locate(net, &nt->parms, 0); + if (!IS_ERR(t)) + return -EEXIST; + } + + err = ip6_tnl_create2(dev); + if (!err && tb[IFLA_MTU]) + ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU])); + + return err; +} +#define ip6_tnl_newlink rpl_ip6_tnl_newlink + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm p; + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip_tunnel_encap ipencap; + + if (dev == ip6n->fb_tnl_dev) + return -EINVAL; + + if (ip6_tnl_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(t, &ipencap); + + if (err < 0) + return err; + } + ip6_tnl_netlink_parms(data, &p); + if (p.collect_md) + return -EINVAL; + + t = ip6_tnl_locate(net, &p, 0); + if (!IS_ERR(t)) { + if (t->dev != dev) + return -EEXIST; + } else + t = netdev_priv(dev); + + return ip6_tnl_update(t, &p); +} +#define ip6_tnl_changelink rpl_ip6_tnl_changelink + +static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head) +{ + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + if (dev != ip6n->fb_tnl_dev) + unregister_netdevice_queue(dev, head); +} + +static size_t ip6_tnl_get_size(const struct net_device *dev) +{ + return + /* IFLA_IPTUN_LINK */ + nla_total_size(4) + + /* IFLA_IPTUN_LOCAL */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_IPTUN_REMOTE */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_IPTUN_TTL */ + nla_total_size(1) + + /* IFLA_IPTUN_ENCAP_LIMIT */ + nla_total_size(1) + + /* IFLA_IPTUN_FLOWINFO */ + nla_total_size(4) + + /* IFLA_IPTUN_FLAGS */ + nla_total_size(4) + + /* IFLA_IPTUN_PROTO */ + nla_total_size(1) + + /* IFLA_IPTUN_ENCAP_TYPE */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_FLAGS */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_SPORT */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_DPORT */ + nla_total_size(2) + + /* IFLA_IPTUN_COLLECT_METADATA */ + nla_total_size(0) + + /* IFLA_IPTUN_FWMARK */ + nla_total_size(4) + + 0; +} + +static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + struct __ip6_tnl_parm *parm = &tunnel->parms; + + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || + nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || + nla_put_in6_addr(skb, IFLA_IPTUN_REMOTE, &parm->raddr) || + nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) || + nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || + nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark)) + goto nla_put_failure; + + if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || + nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, tunnel->encap.flags)) + goto nla_put_failure; + + if (parm->collect_md) + if (nla_put_flag(skb, IFLA_IPTUN_COLLECT_METADATA)) + goto nla_put_failure; + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +#ifdef HAVE_GET_LINK_NET +struct net *rpl_ip6_tnl_get_link_net(const struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + + return tunnel->net; +} + +#endif +static const struct nla_policy ip6_tnl_policy[RPL_IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .len = sizeof(struct in6_addr) }, + [IFLA_IPTUN_REMOTE] = { .len = sizeof(struct in6_addr) }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +}; + +static struct rtnl_link_ops ip6_link_ops __read_mostly = { + .kind = "ip6tnl", + .maxtype = RPL_IFLA_IPTUN_MAX, + .policy = ip6_tnl_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6_tnl_dev_setup, + .validate = ip6_tnl_validate, + .newlink = ip6_tnl_newlink, + .changelink = ip6_tnl_changelink, + .dellink = ip6_tnl_dellink, + .get_size = ip6_tnl_get_size, + .fill_info = ip6_tnl_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct xfrm6_tunnel ip4ip6_handler __read_mostly = { + .handler = ip4ip6_rcv, + .err_handler = ip4ip6_err, + .priority = 1, +}; + +static struct xfrm6_tunnel ip6ip6_handler __read_mostly = { + .handler = ip6ip6_rcv, + .err_handler = ip6ip6_err, + .priority = 1, +}; + +static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head *list) +{ + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct net_device *dev, *aux; + int h; + struct ip6_tnl *t; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == &ip6_link_ops) + unregister_netdevice_queue(dev, list); + + for (h = 0; h < IP6_TUNNEL_HASH_SIZE; h++) { + t = rtnl_dereference(ip6n->tnls_r_l[h]); + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, list); + t = rtnl_dereference(t->next); + } + } +} + +static int __net_init ip6_tnl_init_net(struct net *net) +{ + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip6_tnl *t = NULL; + int err; + + ip6n->tnls[0] = ip6n->tnls_wc; + ip6n->tnls[1] = ip6n->tnls_r_l; + + err = -ENOMEM; + ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", + NET_NAME_UNKNOWN, ip6_tnl_dev_setup); + + if (!ip6n->fb_tnl_dev) + goto err_alloc_dev; + dev_net_set(ip6n->fb_tnl_dev, net); + ip6n->fb_tnl_dev->rtnl_link_ops = &ip6_link_ops; + /* FB netdevice is special: we have one, and only one per netns. + * Allowing to move it to another netns is clearly unsafe. + */ + ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL; + + err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; + + err = register_netdev(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; + + t = netdev_priv(ip6n->fb_tnl_dev); + + strcpy(t->parms.name, ip6n->fb_tnl_dev->name); + return 0; + +err_register: + free_netdev(ip6n->fb_tnl_dev); +err_alloc_dev: + return err; +} + +static void __net_exit ip6_tnl_exit_batch_net(struct list_head *net_list) +{ + struct net *net; + LIST_HEAD(list); + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) + ip6_tnl_destroy_tunnels(net, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); +} + +static struct pernet_operations ip6_tnl_net_ops = { + .init = ip6_tnl_init_net, + .exit_batch = ip6_tnl_exit_batch_net, + .id = &ip6_tnl_net_id, + .size = sizeof(struct ip6_tnl_net), +}; + +/** + * ip6_tunnel_init - register protocol and reserve needed resources + * + * Return: 0 on success + **/ + +int rpl_ip6_tunnel_init(void) +{ + int err; + +#if 0 + if (!ipv6_mod_enabled()) + return -EOPNOTSUPP; +#endif + err = register_pernet_device(&ip6_tnl_net_ops); + if (err < 0) + goto out_pernet; + + err = xfrm6_tunnel_register(&ip4ip6_handler, AF_INET); + if (err < 0) { + pr_err("%s: can't register ip4ip6\n", __func__); + goto out_ip4ip6; + } + + err = xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6); + if (err < 0) { + pr_err("%s: can't register ip6ip6\n", __func__); + goto out_ip6ip6; + } + err = rtnl_link_register(&ip6_link_ops); + if (err < 0) + goto rtnl_link_failed; + + return 0; + +rtnl_link_failed: + xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); +out_ip6ip6: + xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); +out_ip4ip6: + unregister_pernet_device(&ip6_tnl_net_ops); +out_pernet: + return err; +} + +/** + * ip6_tunnel_cleanup - free resources and unregister protocol + **/ + +void rpl_ip6_tunnel_cleanup(void) +{ + rtnl_link_unregister(&ip6_link_ops); + if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET)) + pr_info("%s: can't deregister ip4ip6\n", __func__); + + if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) + pr_info("%s: can't deregister ip6ip6\n", __func__); + + unregister_pernet_device(&ip6_tnl_net_ops); +} + +#endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 8060097..0b0a17f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -196,6 +196,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; const struct iphdr *iph; + struct erspan_md2 *md2; int ver; int len; diff --git a/datapath/vport.c b/datapath/vport.c index 711c29f..f4131be 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -67,6 +67,12 @@ int ovs_vport_init(void) err = ipgre_init(); if (err) goto err_gre; + err = ip6gre_init(); + if (err) + goto err_ip6gre; + err = ip6_tunnel_init(); + if (err) + goto err_ip6_tunnel; err = geneve_init_module(); if (err) goto err_geneve; @@ -84,6 +90,10 @@ err_stt: err_vxlan: geneve_cleanup_module(); err_geneve: + ip6_tunnel_cleanup(); +err_ip6_tunnel: + ip6gre_fini(); +err_ip6gre: ipgre_fini(); err_gre: lisp_cleanup_module(); @@ -102,6 +112,8 @@ void ovs_vport_exit(void) ovs_stt_cleanup_module(); vxlan_cleanup_module(); geneve_cleanup_module(); + ip6_tunnel_cleanup(); + ip6gre_fini(); ipgre_fini(); lisp_cleanup_module(); kfree(dev_table); diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 40c4569..63d3454 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -90,6 +90,9 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_VXLAN: return "vxlan"; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L3) { return "gre"; } else if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L2) { @@ -262,6 +265,9 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -316,6 +322,9 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, nl_msg_put_be16(&request, IFLA_VXLAN_PORT, tnl_cfg->dst_port); break; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: nl_msg_put_flag(&request, IFLA_GRE_COLLECT_METADATA); break; case OVS_VPORT_TYPE_GENEVE: @@ -438,6 +447,9 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index bb9e95d..e8ffd6f 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -787,6 +787,11 @@ get_vport_type(const struct dpif_netlink_vport *vport) case OVS_VPORT_TYPE_STT: return "stt"; + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: + return ""; + case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: break; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index f529e2c..ddb8349 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3377,6 +3377,9 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac, switch (tnl_type) { case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: nw_proto = IPPROTO_GRE; break; case OVS_VPORT_TYPE_VXLAN: From patchwork Sat May 19 00:49:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916700 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NCm5O1DT"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmr91tg2z9s4w for ; Sat, 19 May 2018 10:58:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 92064DD0; Sat, 19 May 2018 00:50:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id CFCC4CC1 for ; Sat, 19 May 2018 00:50:12 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9F9E06CE for ; Sat, 19 May 2018 00:50:12 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id w3-v6so3969949pgv.12 for ; Fri, 18 May 2018 17:50:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vF+h5j49m4OeaAysg9XaOt8MSByqeN2+208QyR24qw8=; b=NCm5O1DTTyqVKxr5Dakf+Qc/1rgW5AWzKMH21ZIIFbYEmaUeh+BKh4upGbeo2LQ2ML TWYNtEvMZ+QmhjjN6QjL5EHyzyGR04OQlNFGA+pHzyzv+HgDyl4iXVyWd77YIW6n1leY 1IutiDk+ap9QUCvskjuD8vgkafO6TnnGE8NeP/4m241vkKCtryh9hPe4hAYc93fgZlNe E5YcWwtUEzaEKZh9tBZBeBq/HOEoRioYDQTRiYq/tiDA5N0IZ5FoK54vOxNQ+fly0CA2 nCA+4TRm7XxTKFYzk9Ni71zKQzZBJk+8DwBebOYMb9bR2Cl2kMJh5QF0b8So5Wsbk9rv ycHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vF+h5j49m4OeaAysg9XaOt8MSByqeN2+208QyR24qw8=; b=HMhw6BNxF//uvmZWfH3Pi0/2k4ZUJvledZU4PHMTQRIfprOFq4jO+WPDAQ34pQ5ZCX ICh0gEYty/9kYkNt4cPQ/4q7ktPAgAYqIm7ywBR1JAF4KWLckLezb+Vy7oe1Zp5veSjC mFqIMO6A8H35fTjW0I/qF/SvavQydqR0hM7oF4YERzxTFOTXrQPeCd8p0jrZXYeNsUz2 +KvdNry9S/vrk5magFW8jP+4BT1A5PDq7XfVeQeBMqq08k4/NbS16uM8bv3DsIqKCyq1 Wvv+9V7hKaVCrwasX20fYg5V9eUAV1dJJR5AhoIDt6QIvabSjXGIEAyVJ1e3BmfgQJFT yv1w== X-Gm-Message-State: ALKqPwcfCPUpbOMcAvg6NYaUJS0wtYRF9/o5toVMhMEg8TlqieM3enzM ZZoRrS9xfAUfBPbWBlElUMjRoA== X-Google-Smtp-Source: AB8JxZpRXlagLBpIpKNAHi3YoIAJ8rBasZ6R4bmj5W96iK7HZ/+HUwEZwdxB/CV0tg9M80WCqmWnnw== X-Received: by 2002:a63:6742:: with SMTP id b63-v6mr9217355pgc.54.1526691011879; Fri, 18 May 2018 17:50:11 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:11 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:27 -0700 Message-Id: <1526690988-29912-20-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 19/40] datapath: Add dellink op to ip6gre and ip6erspan tap ops X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Fix an oversight in the ip6gre_tap_ops and ip6erspan_tap_ops in which the .dellink field was not initialized leading to bugs when trying to remove and re-add those type of ports. Signed-off-by: Greg Rose Tested-by: William Tu --- datapath/linux/compat/ip6_gre.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 23b1c83..1e2f46a 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -2324,6 +2324,7 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { .validate = ip6gre_tap_validate, .newlink = ip6gre_newlink, .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, #ifdef HAVE_GET_LINK_NET @@ -2340,6 +2341,7 @@ static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = { .validate = ip6erspan_tap_validate, .newlink = ip6gre_newlink, .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, #ifdef HAVE_GET_LINK_NET From patchwork Sat May 19 00:49:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916701 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="O2nvjMCt"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmrj25Ybz9s4w for ; Sat, 19 May 2018 10:59:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0606CDDC; Sat, 19 May 2018 00:50:33 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id AFC39C05 for ; Sat, 19 May 2018 00:50:13 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 6936A6CF for ; Sat, 19 May 2018 00:50:13 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id j20-v6so4489556pff.10 for ; Fri, 18 May 2018 17:50:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+K8Uz9GTAqOj4X8qwVF/G8F4McIsqoE82ebcV+AyN0E=; b=O2nvjMCtf/UpA6TC62WgnvRlhdcJ0ODLof9dFuDsMf4T902mudHBPdvFB/7VGbVw4x rLvCjQqu0QKOMnSZ8318w3wRCX4c7mV5ZeeRWn8/noEmkmEJA0+pbydRs0zX90exgNwY fUanscMALgWeA8esDz3kp4QrMsUC6wkYJMEu+6IapTR4DnDZrO475GZ1cn0uaM1iLMNW u7WX06XMx/xX4p1kc/mFCdOAqIfzEUK+wKxZYyrZPr2uFUf1F7AKvtuqqQEPlpE57qkm 2zS9zHQ27Qu96Cc9MpCkSf3MwtBQOjIuZR+HzYIae/0d8artBfVmfVbhD8jk9hQb1Dy0 uwaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+K8Uz9GTAqOj4X8qwVF/G8F4McIsqoE82ebcV+AyN0E=; b=ZgSDGZwVH6FzNIEFXa1zomFZk9fZ5osjK5cVhqDNlxXbicOYf3wcFoviJ1CSmIe3UY QE447TZ5c7D54nRDYWCFF5VHe7Ve+SS11yAbYWy3XvvbIi7ZmYFEgv1zFKEUxbLT46uj 9QXCGzji17hB3C2CDUoeQu6N0e5GYEobQUXvCFWYl++6/QMaVTcN3YPp/355Djy845SM IpROCxy128cK54FYLd1uiIrJA4ehZZaLY9qPpgBDu1PPqT1+P9Ir4RmmSlbbcyDlMDxD AZJsXZrh8UAQzLXBcrwBnNqROuU1GPzjZAJu4q9qNS9cPUtNmkzYqS5uWxaZiM3NmMkZ yWFg== X-Gm-Message-State: ALKqPwfkB19SbeANaZeyx1w2gY1eouxwRMp3WAr8wgXmz1WSLN4Q6zLT WOLKcU/p+dFEjIiZDpqDOizZGQ== X-Google-Smtp-Source: AB8JxZrGC1/E6Xdmo5peyTqNcMq++bA7QPUSE4sy9o5l5MOXPT5n4R5s7k2bZ8dNvLrixBjKEyb/AA== X-Received: by 2002:a62:e30f:: with SMTP id g15-v6mr11511679pfh.68.1526691012799; Fri, 18 May 2018 17:50:12 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:12 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:28 -0700 Message-Id: <1526690988-29912-21-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 20/40] datapath: Use correct tunnel receive for ip6gre X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org During backports of ip6 gre I used ovs_ip_tunnel_rcv() for the ip6gre_rcv() function but that is wrong because it processes ipv4 tunnels. Use the correct backported ip6 tunnel receive in ip6 tunnel.c ip6_tnl_rcv(). Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 1e2f46a..085d04f 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -603,8 +603,7 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) } - skb_reset_mac_header(skb); - ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, false); kfree(tun_dst); return PACKET_RCVD; } From patchwork Sat May 19 00:49:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916708 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="peVElDP2"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmxj3F8mz9s4w for ; Sat, 19 May 2018 11:03:21 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 26B06E83; Sat, 19 May 2018 00:50:51 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 43302CFF for ; Sat, 19 May 2018 00:50:15 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A9D4D6D2 for ; Sat, 19 May 2018 00:50:14 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id f189-v6so4500246pfa.7 for ; Fri, 18 May 2018 17:50:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QONi4bMB9a+QOmH5das6ahnsp7WJmQxwZ/R4O8w54oY=; b=peVElDP23Cx9OyXVBUniex6MZtwE8Zwf91I/9Dk/1cmGAk27QwEHi61L7hn/Egt+CC ZEa9ng5QsZctgiYJpeechQi4z+av35rCi7LbG+IJSmoQGkirusK/fMRkeJOMHK3LOq0L gJ/fQXn1TqRztv6fONnfGpPp7OkI3vBfZeZsgGBs6WWxHu92sTONTyc88LhVgY6pOCCh HM/gEDAMgFq/FRIU+vzNP8vTPcf0JuhqbKKP+V8Sq+P2Or4igE/Vftp2M1t7K6wjq1YM fB2OkADBCjcuvvMPaT1bNtwh5J1daZoUSKqcXxRYCpFempgy5r6DZ2E0DwAiBXrgVkbq W5sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QONi4bMB9a+QOmH5das6ahnsp7WJmQxwZ/R4O8w54oY=; b=mdaks9+2IT2tnaNzeCE+yHdJmSZjRcrTN3ZsgsHTSGmDijz2fOZ73ngCcMv8aCQpCW UjeovVkl8SwdYW39st6PKdYA8GN9SvO6DASJrn2odWXtwGEaT0zRlgn66mJEC2DTdaHL WzNyG/NO41It83LpBhLUlQCgqtFoqb0DCbhGpJwXuct0Nyt7qbGCyqcm7Zyb4g7acN/h 5WamtP4dS8sb5fKTvUzanOb+H+k4irxtaLqh7jrx5khVHUtRLK/vx7yJk5pFOk1MHoi6 fWE9/5ndsc8GEBMTtphy0W83uuKIP+FDj5mV9fzXlq5AYaOYn6PsPX78VNUttbUgukg4 yXug== X-Gm-Message-State: ALKqPweEdFC2YXp/+S6JcJqSZQ+KGnJHyu9IuwoUZyOkWt0UnBRGqu40 xXxI3wI9MOANDlUHqeMRybSPCQ== X-Google-Smtp-Source: AB8JxZqiN82JoFW4D4SreOqSg9Qy33sAZgt3ZkhhW0ylw2wb0xOX3FyApUU5VNtEZmNDrRdq0hEtKg== X-Received: by 2002:a63:69c3:: with SMTP id e186-v6mr9082072pgc.353.1526691014036; Fri, 18 May 2018 17:50:14 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:13 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:29 -0700 Message-Id: <1526690988-29912-22-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 21/40] datapath: erspan: introduce erspan v2 for ip_gre X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit f551c91de262ba36b20c3ac19538afb4f4507441 Author: William Tu Date: Wed Dec 13 16:38:56 2017 -0800 net: erspan: introduce erspan v2 for ip_gre The patch adds support for erspan version 2. Not all features are supported in this patch. The SGT (security group tag), GRA (timestamp granularity), FT (frame type) are set to fixed value. Only hardware ID and direction are configurable. Optional subheader is also not supported. Signed-off-by: William Tu Signed-off-by: David S. Miller Includes some compatability layer adjustments and portions of this commit were introduced earlier while pulling in ipv6 erspan. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/include/net/ip_tunnels.h | 10 +++--- datapath/linux/compat/ip_gre.c | 44 ++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index ea3fb8d..9b2621e 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -257,7 +257,7 @@ struct rpl_ip_tunnel_dst { }; #define ip_tunnel rpl_ip_tunnel -struct ip_tunnel { +struct rpl_ip_tunnel { struct ip_tunnel __rcu *next; struct hlist_node hash_node; struct net_device *dev; @@ -301,7 +301,7 @@ struct ip_tunnel { }; #define ip_tunnel_net rpl_ip_tunnel_net -struct ip_tunnel_net { +struct rpl_ip_tunnel_net { struct net_device *fb_tunnel_dev; struct hlist_head tunnels[IP_TNL_HASH_SIZE]; struct ip_tunnel __rcu *collect_md_tun; @@ -368,8 +368,8 @@ struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *tot); #define ip_tunnel_get_dsfield rpl_ip_tunnel_get_dsfield -static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, - const struct sk_buff *skb) +static inline u8 rpl_ip_tunnel_get_dsfield(const struct iphdr *iph, + const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) return iph->tos; @@ -380,7 +380,7 @@ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, } #define ip_tunnel_ecn_encap rpl_ip_tunnel_ecn_encap -static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, +static inline u8 rpl_ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, const struct sk_buff *skb) { u8 inner = ip_tunnel_get_dsfield(iph, skb); diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 0b0a17f..9bc3277 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -364,7 +364,8 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) if (hdr_len < 0) goto drop; - if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) return 0; goto drop; @@ -819,9 +820,14 @@ enum { #if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) + IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, +#endif }; -#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_INDEX + 1) +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) { @@ -966,8 +972,14 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, } /* Push ERSPAN header */ - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, - truncate, true); + if (tunnel->erspan_ver == 1) + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + truncate, true); + else + erspan_build_header_v2(skb, tunnel->parms.o_key, + tunnel->dir, tunnel->hwid, + truncate, true); + tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); return NETDEV_TX_OK; @@ -1011,7 +1023,7 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + - sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; + erspan_hdr_len(tunnel->erspan_ver); t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; @@ -1248,6 +1260,12 @@ static size_t ipgre_get_size(const struct net_device *dev) nla_total_size(0) + /* IFLA_GRE_ERSPAN_INDEX */ nla_total_size(4) + + /* IFLA_GRE_ERSPAN_VER */ + nla_total_size(1) + + /* IFLA_GRE_ERSPAN_DIR */ + nla_total_size(1) + + /* IFLA_GRE_ERSPAN_HWID */ + nla_total_size(2) + 0; } @@ -1269,9 +1287,18 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) !!(p->iph.frag_off & htons(IP_DF)))) goto nla_put_failure; - if (t->index) - if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver)) + goto nla_put_failure; + + if (t->erspan_ver == 1) { + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + goto nla_put_failure; + } else if (t->erspan_ver == 2) { + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir)) + goto nla_put_failure; + if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid)) goto nla_put_failure; + } return 0; @@ -1291,6 +1318,9 @@ static const struct nla_policy ipgre_policy[RPL_IFLA_GRE_MAX + 1] = { [IFLA_GRE_TOS] = { .type = NLA_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, }; static struct rtnl_link_ops ipgre_link_ops __read_mostly = { From patchwork Sat May 19 00:49:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916702 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="I4cpj9xv"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmsC5zlhz9s4w for ; Sat, 19 May 2018 10:59:27 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5C5F5E28; Sat, 19 May 2018 00:50:41 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 577A1D4A for ; Sat, 19 May 2018 00:50:16 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id D29E8473 for ; Sat, 19 May 2018 00:50:15 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id a14-v6so4502252pfi.1 for ; Fri, 18 May 2018 17:50:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Ql5zHckoutwzkwrh+yOq+iYve1l5vcpvoK6Htq7JVWA=; b=I4cpj9xvu/YDc9B3VnAYnYSJfucd9bUVEBZP41n1wnERqxJLaQ4VviIOu505nnh2+0 kuPj8J+1ngqXBTyJLtk3jpirqQvhs6HvzrApieLh/P1XoXPUjRJqbBdfIdCWGy+WQcrf cHN7/rvnG4o7MzUPxQasHjO02ph4XDAl/05MGRy2Q30HNWQeE7V4nlExLe92Gv5ZM8SH iJtF5GzgdtziB4U85sCa6YHUgeXVfCO+aXCD3QvjaM4WpRGNnKTqRAUD4+meh7Udr3OO qNfA4yr4baLCHNIGxZvw3EaRAOzXFnaDbahvj80O0bMlWgw85KwTuSZXm5/mf6vnD1+G nCYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Ql5zHckoutwzkwrh+yOq+iYve1l5vcpvoK6Htq7JVWA=; b=q3YW9x+0EfBtwn+GPwJckyPB87AiZvPs1jdahfT1vTYai3iDNCbgv0pfkV5xHd/m+r JbMSbaX0SmCJOxpwBYaZU/NyESdZZMtsWNjA39OX6OhbDQgZclzK62CNeBSP4rFtEa41 pT1If9O++F7sbTnSWM2+n2btRiN8yqcLE7TItwS7OQLfbi/9ac4PyraFKcBNE72nw+Pp Uc+5saaDNExjZGlOUQKyuxx53Ub+gIa74fXH1Z8oexUgltzBUexlHb/f8qzyMARIZnoJ tmNzTxJNt4xnANegIOaS24FMXFAkWxD0gLcJFecV6zvjdtOXuGP1mMiSH8fZ2gFr6Rs5 R0Mg== X-Gm-Message-State: ALKqPwfD7UrWaoxkSzdCdFSe7Z0Yep4qjH+Suqi8XRNIqOhPfr6vU/m2 FALC/Wz5fTure7AQ2XJclsn8lQ== X-Google-Smtp-Source: AB8JxZp9AzvG8YheQVeovHvGbzo193wy48cQnz/YrvP2sK9tx79m2XLx52kZyWm2FLnA4QLnDNAsOg== X-Received: by 2002:a62:dfcd:: with SMTP id d74-v6mr11497424pfl.114.1526691015018; Fri, 18 May 2018 17:50:15 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:14 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:30 -0700 Message-Id: <1526690988-29912-23-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 22/40] compat: erspan: use bitfield instead of mask and offset X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit c69de58ba84f480879de64571d9dae5102d10ed6 Author: William Tu Date: Thu Jan 25 13:20:09 2018 -0800 net: erspan: use bitfield instead of mask and offset Originally the erspan fields are defined as a group into a __be16 field, and use mask and offset to access each field. This is more costly due to calling ntohs/htons. The patch changes it to use bitfields. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Folds in the ip_gre portions of this commit. Other portions of this commit are included in a previous patch where it is called out. Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 9bc3277..958965f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -973,10 +973,11 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, /* Push ERSPAN header */ if (tunnel->erspan_ver == 1) - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + erspan_build_header(skb, ntohl(tunnel->parms.o_key), + tunnel->index, truncate, true); else - erspan_build_header_v2(skb, tunnel->parms.o_key, + erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), tunnel->dir, tunnel->hwid, truncate, true); From patchwork Sat May 19 00:49:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916703 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JvHieo+N"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmss5ZDtz9s4w for ; Sat, 19 May 2018 11:00:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 9EB05E3E; Sat, 19 May 2018 00:50:42 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 561EDD54 for ; Sat, 19 May 2018 00:50:17 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id D44B4473 for ; Sat, 19 May 2018 00:50:16 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id p12-v6so4481913pff.13 for ; Fri, 18 May 2018 17:50:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AN3kBEMJAPx+b3R3KzG8xQfJhvNeYLRnhie23KlFAbU=; b=JvHieo+NAknU1R60nYPeZqTTxttCesfsJuBHIjPVbhiq10f9wAGzzgJQQgovgfeV50 4G4wFCWDLQvg7rU7/ZtD23pW+BTrNH8fvzRxkd8FwoMdeMEJ0lR4Mx44syfmyUczhiKc +IsoZKMh83n1WaPieTLOaPaLPp21g9W3MgqQ4oN4oQ6Jn9mhn9WsQyCenfiNfbUVtL9I 7RylUav73hwOmYelMFF7RXODmleFE68d5saKtAlrUyg9rIOQGhC5wPCm2iOQRO7llZW0 kAQFWhcmf9L37MpxGjmZaJn3xfrHTwd7SLixGFM1PZXjLVt53PgK53LT5fwLIu2uKOdv y2IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AN3kBEMJAPx+b3R3KzG8xQfJhvNeYLRnhie23KlFAbU=; b=fQEaZ6l7aKc+cZkQnBHxvy3apKKhOAmLMjcTklWbuYNWys1UJYupY7c+gjXgz1nc/4 Xp2kMBX6Lx67mnVCPrpgNVi3ZvbwFkMJpnlZh97/SQNtacwMzrFe/iDmFsJuft0P6DL7 Dei3TU23Uz2J1su1zXHStpu290GeTU0I30ZvhrVer2rpg5aYb/U9Eiq/6gbECxalrm85 XUQcan8lYZjmig9ZngVZDeLxNEqAaC83cgeUUWU9NBqYKZTamNiPP3QBkn7wwOxCHuzT R1+YWiUxqF3QLuq08v6AjGHROkTzoQ/0inMkdRn2TweuXzh1bpn+G1nznAaJjLPC9EO5 Dhtw== X-Gm-Message-State: ALKqPwccLjny4YOXzv74/0Uo/ltpQre1jVlK7tPmz46c6nTh0QbvLQ4x k9HEXGzaB+hZ840nYZMb6vxY+Q== X-Google-Smtp-Source: AB8JxZp92NutECuBBjtORtX6urNgrhyKw1yHcfU+dT7z2m4SQlQFssPtRHjmgk5JRDGfJQYBm4nuAw== X-Received: by 2002:a63:735e:: with SMTP id d30-v6mr5635474pgn.24.1526691016184; Fri, 18 May 2018 17:50:16 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:15 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:31 -0700 Message-Id: <1526690988-29912-24-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 23/40] datapath: add erspan version I and II support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit fc1372f89ffe1f58b589643b75f679e452350703 Author: William Tu Date: Thu Jan 25 13:20:11 2018 -0800 openvswitch: add erspan version I and II support The patch adds support for openvswitch to configure erspan v1 and v2. The OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS attr is added to uapi as a binary blob to support all ERSPAN v1 and v2's fields. Note that Previous commit "openvswitch: Add erspan tunnel support." was reverted since it does not design properly. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/flow_netlink.c | 52 ++++++++++++++++++++++- datapath/linux/compat/include/linux/openvswitch.h | 1 + lib/odp-util.c | 2 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index e2ccf91..1b7bad8 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "datapath.h" #include "conntrack.h" @@ -330,7 +331,8 @@ size_t ovs_tun_key_attr_size(void) + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ + nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */ - /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS is mutually exclusive with + /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and + * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it. */ + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */ @@ -401,6 +403,7 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] .next = ovs_vxlan_ext_key_lens }, [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, + [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, }; static const struct ovs_len_tbl @@ -632,6 +635,33 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr, return 0; } +static int erspan_tun_opt_from_nlattr(const struct nlattr *a, + struct sw_flow_match *match, bool is_mask, + bool log) +{ + unsigned long opt_key_offset; + + BUILD_BUG_ON(sizeof(struct erspan_metadata) > + sizeof(match->key->tun_opts)); + + if (nla_len(a) > sizeof(match->key->tun_opts)) { + OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).", + nla_len(a), sizeof(match->key->tun_opts)); + return -EINVAL; + } + + if (!is_mask) + SW_FLOW_KEY_PUT(match, tun_opts_len, + sizeof(struct erspan_metadata), false); + else + SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true); + + opt_key_offset = TUN_METADATA_OFFSET(nla_len(a)); + SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a), + nla_len(a), is_mask); + return 0; +} + static int ip_tun_from_nlattr(const struct nlattr *attr, struct sw_flow_match *match, bool is_mask, bool log) @@ -739,6 +769,20 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, break; case OVS_TUNNEL_KEY_ATTR_PAD: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + if (opts_type) { + OVS_NLERR(log, "Multiple metadata blocks provided"); + return -EINVAL; + } + + err = erspan_tun_opt_from_nlattr(a, match, is_mask, + log); + if (err) + return err; + + tun_flags |= TUNNEL_ERSPAN_OPT; + opts_type = type; + break; default: OVS_NLERR(log, "Unknown IP tunnel attribute %d", type); @@ -863,6 +907,10 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, else if (output->tun_flags & TUNNEL_VXLAN_OPT && vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len)) return -EMSGSIZE; + else if (output->tun_flags & TUNNEL_ERSPAN_OPT && + nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, + swkey_tun_opts_len, tun_opts)) + return -EMSGSIZE; } return 0; @@ -2490,6 +2538,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, break; case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + break; } } diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 771220b..6f4fa01 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -398,6 +398,7 @@ enum ovs_tunnel_key_attr { OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ OVS_TUNNEL_KEY_ATTR_PAD, + OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */ __OVS_TUNNEL_KEY_ATTR_MAX }; diff --git a/lib/odp-util.c b/lib/odp-util.c index 70188b6..752836a 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -3489,6 +3489,8 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr, break; case OVS_TUNNEL_KEY_ATTR_PAD: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + break; case __OVS_TUNNEL_KEY_ATTR_MAX: default: format_unknown_key(ds, a, ma); From patchwork Sat May 19 00:49:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916704 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="X+PQYpzj"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmtW1CcBz9s4w for ; Sat, 19 May 2018 11:00:35 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id DFD1DE4A; Sat, 19 May 2018 00:50:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 039BCCBE for ; Sat, 19 May 2018 00:50:18 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id AE7E2473 for ; Sat, 19 May 2018 00:50:17 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id c10-v6so4484338pfi.12 for ; Fri, 18 May 2018 17:50:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=180UToHz+/5upm/xU7/kHY7oDrdiwqCL4sXyx3n4SVo=; b=X+PQYpzjJ3SOIB9wLfAP3Vadcq55nKnQbhC085ZkG9Zc9eNJjyJulo41AK9OFrb0uv U4sOZX+9lT/SqAlMHL95YA3C5LLk+8nuWQN62jjUG45sbQLtvmd3lJ427pZx0tXCRx/t DPqHSV0Mj5hFvI3pksO2bpENcSoHTB+zDRTNBQc1J5g6O6pRqthmYlC/7xV7m7memOh2 /3RTCmdhwvNTpm6GGgqM5S5gtrxZCpyIobJgZiv6RDa4g7Aew3in1U8QhYWtfxUcW2o6 nrm09SrNzNwkdWsu9RzJZVQ4jrI4oEpd0X/NQ5L/m1Fv/j+gQxNRPY5+mEhoyM+iI5Wg bxeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=180UToHz+/5upm/xU7/kHY7oDrdiwqCL4sXyx3n4SVo=; b=WsZVE3RV9vmNbijKfj94K/hkrkbRT1/V1AOkxVJ46Y71cY3QnkrifAxTwTiHrj8+aK LWqfBRqwmM5CDqJ2T2XtQgsSPf3lR4nLX95PVg8r3vb6Qg8BFnbqOr09u+fa7MYm/E/8 xIrG7uATrE3X7lYQ1wX5BYz+L+UFg4spBBcHfVlePqXR9TURLfkcSv3NP9lVjp+HS4ga XPC7Nf56wWAlAEIx+QotM85OP+DE85okIsDMEH/rGVJZfg733b/erdVZhGyWR7uo3UDw 2smjeObYHhp5zSMNPbxBJohhtz08lWXpwHjfh2Nfnx+CsHYtMDZRhcDoMppPXhY7YlU1 hvqQ== X-Gm-Message-State: ALKqPwf6NfjXXsvzXrIdO02S5DmzoGiOj/RQkRNyO+uoqH4EvK3EELhn Pasi2kiNwy+TLjDk5SPBTL1JPw== X-Google-Smtp-Source: AB8JxZq6p8dauC8v9IXpIhw5z0pj3OfowSXhDStvU8qO1u3QVCrT631ZLNfqbla0FDwCbgIGOgGIIA== X-Received: by 2002:a62:20c7:: with SMTP id m68-v6mr11281076pfj.110.1526691017068; Fri, 18 May 2018 17:50:17 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:16 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:32 -0700 Message-Id: <1526690988-29912-25-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 24/40] netdev-native-tnl: refactor the tunnel push header. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu The patch adds additional 'struct netdev *' to the native tunnel's push_header() interface. This is used for later GRE sequence number support. Signed-off-by: William Tu --- lib/netdev-native-tnl.c | 6 ++++-- lib/netdev-native-tnl.h | 6 ++++-- lib/netdev-provider.h | 3 ++- lib/netdev.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index c3e698d..5eb3d22 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -215,7 +215,8 @@ udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl, void -netdev_tnl_push_udp_header(struct dp_packet *packet, +netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED, + struct dp_packet *packet, const struct ovs_action_push_tnl *data) { struct udp_header *udp; @@ -435,7 +436,8 @@ err: } void -netdev_gre_push_header(struct dp_packet *packet, +netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, + struct dp_packet *packet, const struct ovs_action_push_tnl *data) { struct gre_base_hdr *greh; diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index a912ce9..5012b2d 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -34,13 +34,15 @@ netdev_gre_build_header(const struct netdev *netdev, const struct netdev_tnl_build_header_params *params); void -netdev_gre_push_header(struct dp_packet *packet, +netdev_gre_push_header(const struct netdev *netdev, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); struct dp_packet * netdev_gre_pop_header(struct dp_packet *packet); void -netdev_tnl_push_udp_header(struct dp_packet *packet, +netdev_tnl_push_udp_header(const struct netdev *netdev, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); int netdev_geneve_build_header(const struct netdev *netdev, diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 6e8ae4f..5503b79 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -314,7 +314,8 @@ struct netdev_class { * flow. Push header is called for packet to build header specific to * a packet on actual transmit. It uses partial header build by * build_header() which is passed as data. */ - void (*push_header)(struct dp_packet *packet, + void (*push_header)(const struct netdev *, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); /* Pop tunnel header from packet, build tunnel metadata and resize packet diff --git a/lib/netdev.c b/lib/netdev.c index a1ac1b5..dec35de 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -858,7 +858,7 @@ netdev_push_header(const struct netdev *netdev, { struct dp_packet *packet; DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - netdev->netdev_class->push_header(packet, data); + netdev->netdev_class->push_header(netdev, packet, data); pkt_metadata_init(&packet->md, data->out_port); } From patchwork Sat May 19 00:49:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916705 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Dv3h6CTc"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmvB74GDz9s4w for ; Sat, 19 May 2018 11:01:10 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 06FF9E56; Sat, 19 May 2018 00:50:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7FFAFD5E for ; Sat, 19 May 2018 00:50:19 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f48.google.com (mail-pg0-f48.google.com [74.125.83.48]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E52AF6A3 for ; Sat, 19 May 2018 00:50:18 +0000 (UTC) Received: by mail-pg0-f48.google.com with SMTP id a13-v6so3981880pgu.4 for ; Fri, 18 May 2018 17:50:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4GQY7z5NyC1wygOl0cT8Us2f2XQ6o5sdFTQJM17wRSU=; b=Dv3h6CTcEkBQsoPyo/vMXAUtVWWSj4eOD3LPYJHze6+GtxTH7mxatVXDR3pWfS/yA1 u33hdYlaOjC+QBHqg17jAPd4STz+Lx01Jr5buD3GMrvlFCd8Uf+FOjg/l/b4IW0l3Et+ t+LpPoImTqXlpjrWQ7NZOw6DS1QhdGjnjWFMz1gT7cRG+DDMtj0WGlfZiW+eCH67BSpJ 0CjoCLTwxbnBlFpASgXKUI6SfLk4L+0/rCPA8XM0tZNe+E6XzJf0hJhuCU6YY82/l80R KXZUtKzNEtuxY5n89noo1p/vad/pifxg1dKt6XDjQMzXXVyqgIxoVZwOQat2rNXUhvBg 6fDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4GQY7z5NyC1wygOl0cT8Us2f2XQ6o5sdFTQJM17wRSU=; b=I6oMWXvP6gx8HYSk3O8WRUM4JUcc4vWDPi/+1B8T2WJLQYStYyZ2uwZl/UU5yDhZL3 RMeePtnOgmnIBteusL17Wnyfl+pqDFdF3tQK/xaskJaGHB8Gvf+dWXUhvR6aagFIqNyY 5nU6NOGYNutXmV1a8ImimC1V5c63WF+869081RkZWuwMRsFO8MXx+XkV9mJIFu/14oHx TSKreu3Yrk9/KCpI5oy3NJ4AanjNtzwSg+HLffqUqdIDbCKawsGmr9ilFNaOu5sAAmOH YjTf8VteWgUthF2DuyaZPmgUhKI9o/e31scDwM2pp9Ct9+LwkOgoSKqmBicdy3bJGhtt w42g== X-Gm-Message-State: ALKqPwewSXTRRZGLzMjmOZp+P7JoAiOAbufsYF12brmGqCoX6xK0UdwE yPALhw64/CMFxKsdwX40gLifFA== X-Google-Smtp-Source: AB8JxZoHy1+hezQTl+0ZoqAlDDjuS6T4LPqxTj4iMYTcfWx70fskq8Bw4/xDWTN5t3kOMrJ3siBowA== X-Received: by 2002:a62:478d:: with SMTP id p13-v6mr11428818pfi.164.1526691018175; Fri, 18 May 2018 17:50:18 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:17 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:33 -0700 Message-Id: <1526690988-29912-26-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 25/40] userspace: add gre sequence number support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu The patch adds support for gre sequence number. Default is disable. When enable with 'options:seq=true', the outgoing gre packet will have its sequence number incremented by one. Signed-off-by: William Tu --- lib/netdev-native-tnl.c | 19 ++++++++++++++++++- lib/netdev-vport.c | 11 ++++++++++- lib/netdev.h | 3 +++ tests/tunnel-push-pop.at | 8 ++++---- vswitchd/vswitch.xml | 7 +++++++ 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 5eb3d22..876718a 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -436,10 +436,12 @@ err: } void -netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, +netdev_gre_push_header(const struct netdev *netdev, struct dp_packet *packet, const struct ovs_action_push_tnl *data) { + struct netdev_vport *dev = netdev_vport_cast(netdev); + struct netdev_tunnel_config *tnl_cfg; struct gre_base_hdr *greh; int ip_tot_size; @@ -449,6 +451,15 @@ netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1); *csum_opt = csum(greh, ip_tot_size); } + + if (greh->flags & htons(GRE_SEQ)) { + /* Last 4 byte is GRE seqno */ + int seq_ofs = gre_header_len(greh->flags) - 4; + ovs_16aligned_be32 *seq_opt = + ALIGNED_CAST(ovs_16aligned_be32 *, (char *)greh + seq_ofs); + tnl_cfg = &dev->tnl_cfg; + put_16aligned_be32(seq_opt, htonl(tnl_cfg->seqno++)); + } } int @@ -491,6 +502,12 @@ netdev_gre_build_header(const struct netdev *netdev, options++; } + if (tnl_cfg->set_seq) { + greh->flags |= htons(GRE_SEQ); + /* seqno is updated at push header */ + options++; + } + ovs_mutex_unlock(&dev->mutex); hlen = (uint8_t *) options - (uint8_t *) greh; diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 52aa12d..cc50aa5 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -428,7 +428,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) const char *name = netdev_get_name(dev_); const char *type = netdev_get_type(dev_); struct ds errors = DS_EMPTY_INITIALIZER; - bool needs_dst_port, has_csum; + bool needs_dst_port, has_csum, has_seq; uint16_t dst_proto = 0, src_proto = 0; struct netdev_tunnel_config tnl_cfg; struct smap_node *node; @@ -436,6 +436,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) has_csum = strstr(type, "gre") || strstr(type, "geneve") || strstr(type, "stt") || strstr(type, "vxlan"); + has_seq = strstr(type, "gre"); memset(&tnl_cfg, 0, sizeof tnl_cfg); /* Add a default destination port for tunnel ports if none specified. */ @@ -506,6 +507,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) if (!strcmp(node->value, "true")) { tnl_cfg.csum = true; } + } else if (!strcmp(node->key, "seq") && has_seq) { + if (!strcmp(node->value, "true")) { + tnl_cfg.set_seq = true; + } } else if (!strcmp(node->key, "df_default")) { if (!strcmp(node->value, "false")) { tnl_cfg.dont_fragment = false; @@ -709,6 +714,10 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) smap_add(args, "csum", "true"); } + if (tnl_cfg.set_seq) { + smap_add(args, "seq", "true"); + } + enum tunnel_layers layers = tunnel_supported_layers(type, &tnl_cfg); if (tnl_cfg.pt_mode != default_pt_mode(layers)) { smap_add(args, "packet_type", diff --git a/lib/netdev.h b/lib/netdev.h index bd6f45a..e331cac 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -127,6 +127,9 @@ struct netdev_tunnel_config { bool csum; bool dont_fragment; enum netdev_pt_mode pt_mode; + + bool set_seq; + uint32_t seqno; }; void netdev_run(void); diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 10f98c6..4bd412e 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -358,7 +358,7 @@ AT_SETUP([tunnel_push_pop - underlay bridge match]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=gre \ - options:remote_ip=1.1.2.92 options:key=456 ofport_request=3], [0]) + options:remote_ip=1.1.2.92 options:key=456 options:seq=true ofport_request=3], [0]) AT_CHECK([ovs-appctl dpif/show], [0], [dnl dummy@ovs-dummy: hit:0 missed:0 @@ -367,7 +367,7 @@ dummy@ovs-dummy: hit:0 missed:0 p0 1/1: (dummy) int-br: int-br 65534/2: (dummy-internal) - t1 3/3: (gre: key=456, remote_ip=1.1.2.92) + t1 3/3: (gre: key=456, remote_ip=1.1.2.92, seq=true) ]) AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK @@ -390,14 +390,14 @@ AT_CHECK([ovs-ofctl add-flow int-br action=3]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4789)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], - [Datapath actions: clone(tnl_push(tnl_port(3),header(size=42,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x2000,proto=0x6558),key=0x1c8)),out_port(100)),1) + [Datapath actions: tnl_push(tnl_port(3),header(size=46,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x3000,proto=0x6558),key=0x1c8,seq=0x0)),out_port(100)) ]) dnl Verify outer L2 and L3 header flow fields can be matched in the underlay bridge AT_CHECK([ovs-appctl netdev-dummy/receive int-br '50540000000a5054000000091234']) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl) n_packets=1, n_bytes=42, priority=1,arp actions=NORMAL - n_packets=1, n_bytes=56, priority=99,ip,dl_src=aa:55:aa:55:00:00,dl_dst=f8:bc:12:44:34:b6,nw_src=1.1.2.88,nw_dst=1.1.2.92,nw_proto=47,nw_tos=0 actions=NORMAL + n_packets=1, n_bytes=60, priority=99,ip,dl_src=aa:55:aa:55:00:00,dl_dst=f8:bc:12:44:34:b6,nw_src=1.1.2.88,nw_dst=1.1.2.92,nw_proto=47,nw_tos=0 actions=NORMAL NXST_FLOW reply: ]) diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 7ab90d5..acc1b03 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2596,6 +2596,13 @@ + +

+ Optional. A 4-byte sequence number field for GRE tunnel only. + Default is disabled, set to true to enable. + Sequence number is incremented by one on each outgoing packet. +

+
From patchwork Sat May 19 00:49:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916714 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TCHypJ0y"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn0m40pGz9s4w for ; Sat, 19 May 2018 11:06:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 886CAE5F; Sat, 19 May 2018 00:50:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id C8238D94 for ; Sat, 19 May 2018 00:50:25 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 93A436A3 for ; Sat, 19 May 2018 00:50:21 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id ay10-v6so5509694plb.1 for ; Fri, 18 May 2018 17:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vYyS4w3CFA33BXG+CcVl6UFHL2pOD1YQyhAPfOmmXCQ=; b=TCHypJ0yyXmjJTrN5ScQsZfH5wgiK88cy94UzcdPhI3MnXzsjXIyhCeoBo/jdiOFah r0kQYyVAlWaI6a1OoXXGMvPcOaY6pvorJ0PWAWZi77VShfDhUCzzOan+RrSCQSW3heFZ 6Djt+ZAXj7PTIqOplk/2r0+bg3J86m9AnEyko5uhTcWvyPscSQmtnI93WkyppdKmIWrJ 3h7kLvIl6ud5k/na95edOVTMt1rq3eZ7jVxZh/l55PEEX/zMHDtfd6NdVvoAGLDNx1dQ aCznZ8pM6RLuzbtXOv8U8U0FsIrYpbmoBRmsDmgKRqzUJNJvm6xlDsqnvIRS1m3oK4aw xOIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vYyS4w3CFA33BXG+CcVl6UFHL2pOD1YQyhAPfOmmXCQ=; b=P6LBxqECpIp5l1HFg5v+EEus7eB8PjpyvsoKdGhxS1SCX8h6E1kAKDmHHjqcfAAWYW ttcKxxYkNrEwy5zgs94J+YayMipGAUardvKze+iEApbLSDHlcYd22GeohTYjGXK04SBO 6SjJbPjMjaUHrmxTIaUkaT4HDwZrler56xx+BTnXiNhifivPB39Wah5eEy7BoK5/F22Y VzwQ+HLV+iZv7DFN/LmpDaZReGmuKa7wZTq1iqe4QKKt7SsnMtTHAYkrDRRStIeuVhP1 07UweE0xLFuJDY8MKTZyrZh8n9jxvOll9V1hXSEaRUGFRP63HpjKglruWSDCa+InY1Ex 6UKg== X-Gm-Message-State: ALKqPwfF4lpcs9Rdn7Z+iiQJRAk6yT3G15n41DV5xh/hOyQ2UfiJZ/PP d4pjS3hDdiwH6wbObRa+pDaIuQ== X-Google-Smtp-Source: AB8JxZq7ZwKOMJy/uGSGVUutuMaovpoDwtI26sy7ERpdRVBR+pShXoOAefauT1qkPKyfQ7I8NXKtaA== X-Received: by 2002:a17:902:24a5:: with SMTP id w34-v6mr11509593pla.52.1526691019652; Fri, 18 May 2018 17:50:19 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:19 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:34 -0700 Message-Id: <1526690988-29912-27-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 26/40] userspace: add erspan tunnel support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu ERSPAN is a tunneling protocol based on GRE tunnel. The patch add erspan tunnel support for ovs-vswitchd with userspace datapath. Configuring erspan tunnel is similar to gre tunnel, but with additional erspan's parameters. Matching a flow on erspan's metadata is also supported, see ovs-fields for more details. Cc: Ben Pfaff Signed-off-by: William Tu Signed-off-by: Greg Rose --- V2 - Additional changes from Ben Pfaff folded in as per his suggestion. V3 - Fix tunnel push/pop --- include/openvswitch/flow.h | 4 +- include/openvswitch/match.h | 12 +++ include/openvswitch/meta-flow.h | 56 ++++++++++++ include/openvswitch/packets.h | 6 +- lib/dpif-netlink.c | 4 + lib/flow.c | 32 +++++-- lib/flow.h | 2 +- lib/match.c | 69 ++++++++++++++- lib/meta-flow.c | 77 ++++++++++++++++ lib/meta-flow.xml | 89 +++++++++++++++++++ lib/netdev-native-tnl.c | 166 ++++++++++++++++++++++++++++++++++ lib/netdev-native-tnl.h | 12 +++ lib/netdev-vport.c | 54 +++++++++++ lib/netdev.h | 4 + lib/nx-match.c | 13 ++- lib/odp-util.c | 80 ++++++++++++++++- lib/odp-util.h | 2 +- lib/ofp-match.c | 2 +- lib/packets.h | 126 ++++++++++++++++++++++++++ lib/tnl-ports.c | 3 +- ofproto/ofproto-dpif-rid.h | 2 +- ofproto/ofproto-dpif-xlate.c | 2 +- ofproto/tunnel.c | 13 +++ tests/odp.at | 4 +- tests/ofproto.at | 6 +- tests/tunnel-push-pop-ipv6.at | 129 ++++++++++++++++++++++++++- tests/tunnel-push-pop.at | 192 +++++++++++++++++++++++++++++++++++++++- tests/tunnel.at | 12 +++ vswitchd/vswitch.xml | 34 +++++++ 29 files changed, 1181 insertions(+), 26 deletions(-) diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h index cd61fff..5d2cf09 100644 --- a/include/openvswitch/flow.h +++ b/include/openvswitch/flow.h @@ -27,7 +27,7 @@ extern "C" { /* This sequence number should be incremented whenever anything involving flows * or the wildcarding of flows changes. This will cause build assertion * failures in places which likely need to be updated. */ -#define FLOW_WC_SEQ 40 +#define FLOW_WC_SEQ 41 /* Number of Open vSwitch extension 32-bit registers. */ #define FLOW_N_REGS 16 @@ -166,7 +166,7 @@ BUILD_ASSERT_DECL(sizeof(struct ovs_key_nsh) % sizeof(uint64_t) == 0); /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t) == sizeof(struct flow_tnl) + sizeof(struct ovs_key_nsh) + 300 - && FLOW_WC_SEQ == 40); + && FLOW_WC_SEQ == 41); /* Incremental points at which flow classification may be performed in * segments. diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h index 49333ae..49e463a 100644 --- a/include/openvswitch/match.h +++ b/include/openvswitch/match.h @@ -109,6 +109,18 @@ void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id); void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask); void match_set_tun_gbp_flags(struct match *match, uint8_t flags); +void match_set_tun_erspan_ver(struct match *match, uint8_t ver); +void match_set_tun_erspan_ver_masked(struct match *match, uint8_t ver, + uint8_t mask); +void match_set_tun_erspan_idx(struct match *match, uint32_t idx); +void match_set_tun_erspan_idx_masked(struct match *match, uint32_t idx, + uint32_t mask); +void match_set_tun_erspan_dir(struct match *match, uint8_t dir); +void match_set_tun_erspan_dir_masked(struct match *match, uint8_t dir, + uint8_t mask); +void match_set_tun_erspan_hwid(struct match *match, uint8_t hwid); +void match_set_tun_erspan_hwid_masked(struct match *match, uint8_t hwid, + uint8_t mask); void match_set_in_port(struct match *, ofp_port_t ofp_port); void match_set_pkt_mark(struct match *, uint32_t pkt_mark); void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask); diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 98c9e1c..64470b5 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -450,6 +450,62 @@ enum OVS_PACKED_ENUM mf_field_id { */ MFF_TUN_GBP_FLAGS, + /* "tun_erspan_idx". + * + * ERSPAN index (direction/port number) + * + * Type: be32 (low 20 bits). + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_IDX(11) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_IDX, + + /* "tun_erspan_ver". + * + * ERSPAN version (v1 / v2) + * + * Type: u8 (low 4 bits). + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_VER(12) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_VER, + + /* "tun_erspan_dir". + * + * ERSPAN mirrored traffic's direction + * + * Type: u8 (low 1 bits). + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_DIR(13) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_DIR, + + /* "tun_erspan_hwid". + * + * ERSPAN Hardware ID + * + * Type: u8 (low 6 bits). + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_HWID(14) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_HWID, + #if TUN_METADATA_NUM_OPTS == 64 /* "tun_metadata". * diff --git a/include/openvswitch/packets.h b/include/openvswitch/packets.h index fef756b..925844e 100644 --- a/include/openvswitch/packets.h +++ b/include/openvswitch/packets.h @@ -39,7 +39,11 @@ struct flow_tnl { ovs_be16 tp_dst; ovs_be16 gbp_id; uint8_t gbp_flags; - uint8_t pad1[5]; /* Pad to 64 bits. */ + uint8_t erspan_ver; + uint32_t erspan_idx; + uint8_t erspan_dir; + uint8_t erspan_hwid; + uint8_t pad1[6]; /* Pad to 64 bits. */ struct tun_metadata metadata; }; diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index e8ffd6f..a8b3ec6 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -819,6 +819,10 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_VXLAN; } else if (!strcmp(type, "lisp")) { return OVS_VPORT_TYPE_LISP; + } else if (!strcmp(type, "erspan")) { + return OVS_VPORT_TYPE_ERSPAN; + } else if (!strcmp(type, "ip6erspan")) { + return OVS_VPORT_TYPE_IP6ERSPAN; } else { return OVS_VPORT_TYPE_UNSPEC; } diff --git a/lib/flow.c b/lib/flow.c index 09b66b8..136f060 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -126,7 +126,7 @@ struct mf_ctx { * away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are * defined as macros. */ -#if (FLOW_WC_SEQ != 40) +#if (FLOW_WC_SEQ != 41) #define MINIFLOW_ASSERT(X) ovs_assert(X) BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime " "assertions enabled. Consider updating FLOW_WC_SEQ after " @@ -1014,7 +1014,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) { int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); match_init_catchall(flow_metadata); if (flow->tunnel.tun_id != htonll(0)) { @@ -1042,6 +1042,18 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) if (flow->tunnel.gbp_flags) { match_set_tun_gbp_flags(flow_metadata, flow->tunnel.gbp_flags); } + if (flow->tunnel.erspan_ver) { + match_set_tun_erspan_ver(flow_metadata, flow->tunnel.erspan_ver); + } + if (flow->tunnel.erspan_idx) { + match_set_tun_erspan_idx(flow_metadata, flow->tunnel.erspan_idx); + } + if (flow->tunnel.erspan_dir) { + match_set_tun_erspan_dir(flow_metadata, flow->tunnel.erspan_dir); + } + if (flow->tunnel.erspan_hwid) { + match_set_tun_erspan_hwid(flow_metadata, flow->tunnel.erspan_hwid); + } tun_metadata_get_fmd(&flow->tunnel, flow_metadata); if (flow->metadata != htonll(0)) { match_set_metadata(flow_metadata, flow->metadata); @@ -1581,7 +1593,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc, memset(&wc->masks, 0x0, sizeof wc->masks); /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); if (flow_tnl_dst_is_set(&flow->tunnel)) { if (flow->tunnel.flags & FLOW_TNL_F_KEY) { @@ -1598,6 +1610,10 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc, WC_MASK_FIELD(wc, tunnel.tp_dst); WC_MASK_FIELD(wc, tunnel.gbp_id); WC_MASK_FIELD(wc, tunnel.gbp_flags); + WC_MASK_FIELD(wc, tunnel.erspan_ver); + WC_MASK_FIELD(wc, tunnel.erspan_idx); + WC_MASK_FIELD(wc, tunnel.erspan_dir); + WC_MASK_FIELD(wc, tunnel.erspan_hwid); if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) { if (flow->tunnel.metadata.present.map) { @@ -1728,7 +1744,7 @@ void flow_wc_map(const struct flow *flow, struct flowmap *map) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); flowmap_init(map); @@ -1829,7 +1845,7 @@ void flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata); memset(&wc->masks.regs, 0, sizeof wc->masks.regs); @@ -1973,7 +1989,7 @@ flow_wildcards_set_xxreg_mask(struct flow_wildcards *wc, int idx, uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); uint32_t hash = basis; if (flow) { @@ -2020,7 +2036,7 @@ ASSERT_SEQUENTIAL(ipv6_src, ipv6_dst); uint32_t flow_hash_5tuple(const struct flow *flow, uint32_t basis) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); uint32_t hash = basis; if (flow) { @@ -2609,7 +2625,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type, if (clear_flow_L3) { /* Clear all L3 and L4 fields and dp_hash. */ - BUILD_ASSERT(FLOW_WC_SEQ == 40); + BUILD_ASSERT(FLOW_WC_SEQ == 41); memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0, sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT); flow->dp_hash = 0; diff --git a/lib/flow.h b/lib/flow.h index af82931..7a9e7d0 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -959,7 +959,7 @@ static inline void pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); md->recirc_id = flow->recirc_id; md->dp_hash = flow->dp_hash; diff --git a/lib/match.c b/lib/match.c index 2e9a803..bf7e636 100644 --- a/lib/match.c +++ b/lib/match.c @@ -320,6 +320,61 @@ match_set_tun_gbp_flags(struct match *match, uint8_t flags) } void +match_set_tun_erspan_ver_masked(struct match *match, uint8_t ver, uint8_t mask) +{ + match->wc.masks.tunnel.erspan_ver = ver; + match->flow.tunnel.erspan_ver = ver & mask; +} + +void +match_set_tun_erspan_ver(struct match *match, uint8_t ver) +{ + match_set_tun_erspan_ver_masked(match, ver, UINT8_MAX); +} + +void +match_set_tun_erspan_idx_masked(struct match *match, uint32_t erspan_idx, + uint32_t mask) +{ + match->wc.masks.tunnel.erspan_idx = mask; + match->flow.tunnel.erspan_idx = erspan_idx & mask; +} + +void +match_set_tun_erspan_idx(struct match *match, uint32_t erspan_idx) +{ + match_set_tun_erspan_idx_masked(match, erspan_idx, UINT32_MAX); +} + +void +match_set_tun_erspan_dir_masked(struct match *match, uint8_t dir, + uint8_t mask) +{ + match->wc.masks.tunnel.erspan_dir = dir; + match->flow.tunnel.erspan_dir = dir & mask; +} + +void +match_set_tun_erspan_dir(struct match *match, uint8_t dir) +{ + match_set_tun_erspan_dir_masked(match, dir, UINT8_MAX); +} + +void +match_set_tun_erspan_hwid_masked(struct match *match, uint8_t hwid, + uint8_t mask) +{ + match->wc.masks.tunnel.erspan_hwid = hwid; + match->flow.tunnel.erspan_hwid = hwid & mask; +} + +void +match_set_tun_erspan_hwid(struct match *match, uint8_t hwid) +{ + match_set_tun_erspan_hwid_masked(match, hwid, UINT8_MAX); +} + +void match_set_in_port(struct match *match, ofp_port_t ofp_port) { match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX); @@ -1232,6 +1287,18 @@ format_flow_tunnel(struct ds *s, const struct match *match) if (wc->masks.tunnel.ip_ttl) { ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl); } + if (wc->masks.tunnel.erspan_ver) { + ds_put_format(s, "tun_erspan_ver=%"PRIu8",", tnl->erspan_ver); + } + if (wc->masks.tunnel.erspan_idx && tnl->erspan_ver == 1) { + ds_put_format(s, "tun_erspan_idx=%#"PRIx32",", tnl->erspan_idx); + } + if (wc->masks.tunnel.erspan_dir && tnl->erspan_ver == 2) { + ds_put_format(s, "tun_erspan_dir=%"PRIu8",", tnl->erspan_dir); + } + if (wc->masks.tunnel.erspan_hwid && tnl->erspan_ver == 2) { + ds_put_format(s, "tun_erspan_hwid=%#"PRIx8",", tnl->erspan_hwid); + } if (wc->masks.tunnel.flags & FLOW_TNL_F_MASK) { format_flags_masked(s, "tun_flags", flow_tun_flag_to_string, tnl->flags & FLOW_TNL_F_MASK, @@ -1303,7 +1370,7 @@ match_format(const struct match *match, bool is_megaflow = false; int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "%spriority=%s%d,", diff --git a/lib/meta-flow.c b/lib/meta-flow.c index aa2ec01..8b8d174 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -231,6 +231,14 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) return !wc->masks.tunnel.gbp_id; case MFF_TUN_GBP_FLAGS: return !wc->masks.tunnel.gbp_flags; + case MFF_TUN_ERSPAN_VER: + return !wc->masks.tunnel.erspan_ver; + case MFF_TUN_ERSPAN_IDX: + return !wc->masks.tunnel.erspan_idx; + case MFF_TUN_ERSPAN_DIR: + return !wc->masks.tunnel.erspan_dir; + case MFF_TUN_ERSPAN_HWID: + return !wc->masks.tunnel.erspan_hwid; CASE_MFF_TUN_METADATA: return !ULLONG_GET(wc->masks.tunnel.metadata.present.map, mf->id - MFF_TUN_METADATA0); @@ -513,6 +521,10 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_TUN_TTL: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_ERSPAN_IDX: + case MFF_TUN_ERSPAN_VER: + case MFF_TUN_ERSPAN_DIR: + case MFF_TUN_ERSPAN_HWID: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -680,6 +692,18 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, case MFF_TUN_TOS: value->u8 = flow->tunnel.ip_tos; break; + case MFF_TUN_ERSPAN_VER: + value->u8 = flow->tunnel.erspan_ver; + break; + case MFF_TUN_ERSPAN_IDX: + value->be32 = htonl(flow->tunnel.erspan_idx); + break; + case MFF_TUN_ERSPAN_DIR: + value->u8 = flow->tunnel.erspan_dir; + break; + case MFF_TUN_ERSPAN_HWID: + value->u8 = flow->tunnel.erspan_hwid; + break; CASE_MFF_TUN_METADATA: tun_metadata_read(&flow->tunnel, mf, value); break; @@ -994,6 +1018,18 @@ mf_set_value(const struct mf_field *mf, case MFF_TUN_TTL: match_set_tun_ttl(match, value->u8); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver(match, value->u8); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx(match, ntohl(value->be32)); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir(match, value->u8); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid(match, value->u8); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, value, NULL, match, err_str); break; @@ -1391,6 +1427,18 @@ mf_set_flow_value(const struct mf_field *mf, case MFF_TUN_TTL: flow->tunnel.ip_ttl = value->u8; break; + case MFF_TUN_ERSPAN_VER: + flow->tunnel.erspan_ver = value->u8; + break; + case MFF_TUN_ERSPAN_IDX: + flow->tunnel.erspan_idx = ntohl(value->be32); + break; + case MFF_TUN_ERSPAN_DIR: + flow->tunnel.erspan_dir = value->u8; + break; + case MFF_TUN_ERSPAN_HWID: + flow->tunnel.erspan_hwid = value->u8; + break; CASE_MFF_TUN_METADATA: tun_metadata_write(&flow->tunnel, mf, value); break; @@ -1700,6 +1748,10 @@ mf_is_pipeline_field(const struct mf_field *mf) case MFF_TUN_FLAGS: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_ERSPAN_VER: + case MFF_TUN_ERSPAN_IDX: + case MFF_TUN_ERSPAN_DIR: + case MFF_TUN_ERSPAN_HWID: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -1876,6 +1928,18 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) case MFF_TUN_TTL: match_set_tun_ttl_masked(match, 0, 0); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid_masked(match, 0, 0); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, NULL, NULL, match, err_str); break; @@ -2256,6 +2320,19 @@ mf_set(const struct mf_field *mf, case MFF_TUN_TOS: match_set_tun_tos_masked(match, value->u8, mask->u8); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver_masked(match, value->u8, mask->u8); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx_masked(match, ntohl(value->be32), + ntohl(mask->be32)); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir_masked(match, value->u8, mask->u8); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid_masked(match, value->u8, mask->u8); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, value, mask, match, err_str); break; diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml index 933d4b8..144657c 100644 --- a/lib/meta-flow.xml +++ b/lib/meta-flow.xml @@ -1456,6 +1456,7 @@ ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
  • LISP has a 24-bit instance ID.
  • GRE has an optional 32-bit key.
  • STT has a 64-bit key.
  • +
  • ERSPAN has a 10-bit key (Session ID).
  • @@ -1715,6 +1716,87 @@ ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1' +

    ERSPAN Metadata Fields

    +

    + These fields provide access to features in the ERSPAN tunneling protocol + [ERSPAN], which has two major versions: version 1 (aka type II) and + version 2 (aka type III). +

    + +

    + Regardless of version, ERSPAN is encapsulated within a fixed 8-byte GRE + header that consists of a 4-byte GRE base header and a 4-byte sequence + number. The ERSPAN version 1 header format is: +

    + + +
    + + + +
    +
    + + + + + +
    +
    + + + +
    + +
    + +

    + The ERSPAN version 2 header format is: +

    + + +
    + + + +
    +
    + + + + + + + + +
    +
    + + + +
    + +
    + + + ERSPAN version number: 1 for version 1, or 2 for version 2. + + + + This field is a 20-bit index/port number associated with the ERSPAN + traffic's source port and direction (ingress/egress). This field is + platform dependent. + + + + For ERSPAN v2, the mirrored traffic's direction: 0 for ingress traffic, 1 + for egress traffic. + + + + A 6-bit unique identifier of an ERSPAN v2 engine within a system. + +

    Geneve Fields

    @@ -4520,6 +4602,13 @@ r r c c c. Computer Communications Review, October 2007. +

    ERSPAN
    +
    + M. Foschiano, K. Ghosh, M. Mehta, ``Cisco Systems' Encapsulated Remote + Switch Port Analyzer (ERSPAN),'' . +
    +
    EXT-56
    J. Tonsing, ``Permit one of a set of prerequisites to apply, e.g. don't diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 876718a..66eb18e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -518,6 +518,172 @@ netdev_gre_build_header(const struct netdev *netdev, } struct dp_packet * +netdev_erspan_pop_header(struct dp_packet *packet) +{ + const struct gre_base_hdr *greh; + const struct erspan_base_hdr *ersh; + struct pkt_metadata *md = &packet->md; + struct flow_tnl *tnl = &md->tunnel; + int hlen = sizeof(struct eth_header); + unsigned int ulen; + uint16_t greh_protocol; + + hlen += netdev_tnl_is_header_ipv6(dp_packet_data(packet)) ? + IPV6_HEADER_LEN : IP_HEADER_LEN; + + pkt_metadata_init_tnl(md); + if (hlen > dp_packet_size(packet)) { + goto err; + } + + greh = netdev_tnl_ip_extract_tnl_md(packet, tnl, &ulen); + if (!greh) { + goto err; + } + + greh_protocol = ntohs(greh->protocol); + if (greh_protocol != ETH_TYPE_ERSPAN1 && + greh_protocol != ETH_TYPE_ERSPAN2) { + goto err; + } + + if (greh->flags & ~htons(GRE_SEQ)) { + goto err; + } + + ersh = ERSPAN_HDR(greh); + tnl->tun_id = be32_to_be64(be16_to_be32(htons(get_sid(ersh)))); + tnl->erspan_ver = ersh->ver; + + if (ersh->ver == 1) { + ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *, + ersh + 1); + tnl->erspan_idx = ntohl(get_16aligned_be32(index)); + tnl->flags |= FLOW_TNL_F_KEY; + hlen = ulen + ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE; + } else if (ersh->ver == 2) { + struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + tnl->erspan_dir = md2->dir; + tnl->erspan_hwid = get_hwid(md2); + tnl->flags |= FLOW_TNL_F_KEY; + hlen = ulen + ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE; + } else { + VLOG_WARN_RL(&err_rl, "ERSPAN version error %d", ersh->ver); + goto err; + } + + if (hlen > dp_packet_size(packet)) { + goto err; + } + + dp_packet_reset_packet(packet, hlen); + + return packet; +err: + dp_packet_delete(packet); + return NULL; +} + +void +netdev_erspan_push_header(const struct netdev *netdev, + struct dp_packet *packet, + const struct ovs_action_push_tnl *data) +{ + struct netdev_vport *dev = netdev_vport_cast(netdev); + struct netdev_tunnel_config *tnl_cfg; + struct erspan_base_hdr *ersh; + struct gre_base_hdr *greh; + struct erspan_md2 *md2; + int ip_tot_size; + + greh = netdev_tnl_push_ip_header(packet, data->header, + data->header_len, &ip_tot_size); + + /* update GRE seqno */ + tnl_cfg = &dev->tnl_cfg; + ovs_16aligned_be32 *seqno = (ovs_16aligned_be32 *) (greh + 1); + put_16aligned_be32(seqno, htonl(tnl_cfg->seqno++)); + + /* update v2 timestamp */ + if (greh->protocol == htons(ETH_TYPE_ERSPAN2)) { + ersh = ERSPAN_HDR(greh); + md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + put_16aligned_be32(&md2->timestamp, get_erspan_ts(ERSPAN_100US)); + } + return; +} + +int +netdev_erspan_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params) +{ + struct netdev_vport *dev = netdev_vport_cast(netdev); + struct netdev_tunnel_config *tnl_cfg; + struct gre_base_hdr *greh; + struct erspan_base_hdr *ersh; + unsigned int hlen; + uint32_t tun_id; + uint16_t sid; + + /* XXX: RCUfy tnl_cfg. */ + ovs_mutex_lock(&dev->mutex); + tnl_cfg = &dev->tnl_cfg; + greh = netdev_tnl_ip_build_header(data, params, IPPROTO_GRE); + ersh = ERSPAN_HDR(greh); + + tun_id = ntohl(be64_to_be32(params->flow->tunnel.tun_id)); + /* ERSPAN only has 10-bit session ID */ + if (tun_id & ~ERSPAN_SID_MASK) { + ovs_mutex_unlock(&dev->mutex); + return 1; + } else { + sid = (uint16_t) tun_id; + } + + if (tnl_cfg->erspan_ver == 1) { + greh->protocol = htons(ETH_TYPE_ERSPAN1); + greh->flags = htons(GRE_SEQ); + ersh->ver = 1; + set_sid(ersh, sid); + + put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1), + htonl(tnl_cfg->erspan_idx)); + + hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE; + } else if (tnl_cfg->erspan_ver == 2) { + greh->protocol = htons(ETH_TYPE_ERSPAN2); + greh->flags = htons(GRE_SEQ); + ersh->ver = 2; + set_sid(ersh, sid); + + struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + md2->sgt = 0; /* security group tag */ + md2->gra = 0; + put_16aligned_be32(&md2->timestamp, 0); + set_hwid(md2, tnl_cfg->erspan_hwid); + md2->dir = tnl_cfg->erspan_dir; + + hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE; + } else { + VLOG_WARN_RL(&err_rl, "ERSPAN version error %d", tnl_cfg->erspan_ver); + ovs_mutex_unlock(&dev->mutex); + return 1; + } + + ovs_mutex_unlock(&dev->mutex); + + data->header_len += hlen; + + if (params->is_ipv6) { + data->tnl_type = OVS_VPORT_TYPE_IP6ERSPAN; + } else { + data->tnl_type = OVS_VPORT_TYPE_ERSPAN; + } + return 0; +} + +struct dp_packet * netdev_vxlan_pop_header(struct dp_packet *packet) { struct pkt_metadata *md = &packet->md; diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index 5012b2d..5dc0012 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -40,6 +40,18 @@ netdev_gre_push_header(const struct netdev *netdev, struct dp_packet * netdev_gre_pop_header(struct dp_packet *packet); +int +netdev_erspan_build_header(const struct netdev *netdev, + struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *p); + +void +netdev_erspan_push_header(const struct netdev *netdev, + struct dp_packet *packet, + const struct ovs_action_push_tnl *data); +struct dp_packet * +netdev_erspan_pop_header(struct dp_packet *packet); + void netdev_tnl_push_udp_header(const struct netdev *netdev, struct dp_packet *packet, diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index cc50aa5..4311d2b 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -544,6 +544,38 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) } else if (!strcmp(node->key, "egress_pkt_mark")) { tnl_cfg.egress_pkt_mark = strtoul(node->value, NULL, 10); tnl_cfg.set_egress_pkt_mark = true; + } else if (!strcmp(node->key, "erspan_idx")) { + tnl_cfg.erspan_idx = strtol(node->value, NULL, 16); + if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) { + ds_put_format(&errors, "%s: invalid erspan index: %s\n", + name, node->value); + err = EINVAL; + goto out; + } + } else if (!strcmp(node->key, "erspan_ver")) { + tnl_cfg.erspan_ver = atoi(node->value); + if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) { + ds_put_format(&errors, "%s: invalid erspan version: %s\n", + name, node->value); + err = EINVAL; + goto out; + } + } else if (!strcmp(node->key, "erspan_dir")) { + tnl_cfg.erspan_dir = atoi(node->value); + if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) { + ds_put_format(&errors, "%s: invalid erspan direction: %s\n", + name, node->value); + err = EINVAL; + goto out; + } + } else if (!strcmp(node->key, "erspan_hwid")) { + tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16); + if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) { + ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } else { ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name, type, node->key); @@ -734,6 +766,20 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) smap_add_format(args, "egress_pkt_mark", "%"PRIu32, tnl_cfg.egress_pkt_mark); } + + if (tnl_cfg.erspan_idx) { + smap_add_format(args, "erspan_idx", "0x%x", tnl_cfg.erspan_idx); + } + if (tnl_cfg.erspan_ver) { + smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver); + } + if (tnl_cfg.erspan_dir) { + smap_add_format(args, "erspan_dir", "%d", tnl_cfg.erspan_dir); + } + if (tnl_cfg.erspan_hwid) { + smap_add_format(args, "erspan_hwid", "0x%x", tnl_cfg.erspan_hwid); + } + return 0; } @@ -988,6 +1034,14 @@ netdev_vport_tunnel_register(void) NETDEV_VPORT_GET_IFINDEX), TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL, NULL), TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL, NULL), + TUNNEL_CLASS("erspan", "erspan_sys", netdev_erspan_build_header, + netdev_erspan_push_header, + netdev_erspan_pop_header, + NULL), + TUNNEL_CLASS("ip6erspan", "ip6erspan_sys", netdev_erspan_build_header, + netdev_erspan_push_header, + netdev_erspan_pop_header, + NULL), }; static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; diff --git a/lib/netdev.h b/lib/netdev.h index e331cac..0c74dfe 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -130,6 +130,10 @@ struct netdev_tunnel_config { bool set_seq; uint32_t seqno; + uint32_t erspan_idx; + uint8_t erspan_ver; + uint8_t erspan_dir; + uint8_t erspan_hwid; }; void netdev_run(void); diff --git a/lib/nx-match.c b/lib/nx-match.c index a3c22ee..6b1b563 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1026,7 +1026,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, ovs_be32 spi_mask; int match_len; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); struct nxm_put_ctx ctx = { .output = b, .implied_ethernet = false }; @@ -1155,6 +1155,17 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags); tun_metadata_to_nx_match(b, oxm, match); + /* ERSPAN */ + nxm_put_32m(&ctx, MFF_TUN_ERSPAN_IDX, oxm, + htonl(flow->tunnel.erspan_idx), + htonl(match->wc.masks.tunnel.erspan_idx)); + nxm_put_8m(&ctx, MFF_TUN_ERSPAN_VER, oxm, + flow->tunnel.erspan_ver, match->wc.masks.tunnel.erspan_ver); + nxm_put_8m(&ctx, MFF_TUN_ERSPAN_DIR, oxm, + flow->tunnel.erspan_dir, match->wc.masks.tunnel.erspan_dir); + nxm_put_8m(&ctx, MFF_TUN_ERSPAN_HWID, oxm, + flow->tunnel.erspan_hwid, match->wc.masks.tunnel.erspan_hwid); + /* Network Service Header */ nxm_put_8m(&ctx, MFF_NSH_FLAGS, oxm, flow->nsh.flags, match->wc.masks.nsh.flags); diff --git a/lib/odp-util.c b/lib/odp-util.c index 752836a..fc842ee 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -712,6 +712,28 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) options++; } ds_put_format(ds, ")"); + } else if (data->tnl_type == OVS_VPORT_TYPE_ERSPAN || + data->tnl_type == OVS_VPORT_TYPE_IP6ERSPAN) { + const struct gre_base_hdr *greh; + const struct erspan_base_hdr *ersh; + + greh = (const struct gre_base_hdr *) l4; + ersh = ERSPAN_HDR(greh); + + if (ersh->ver == 1) { + ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *, + ersh + 1); + ds_put_format(ds, "erspan(ver=1,sid=0x%"PRIx16",idx=0x%"PRIx32")", + get_sid(ersh), ntohl(get_16aligned_be32(index))); + } else if (ersh->ver == 2) { + struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, + ersh + 1); + ds_put_format(ds, "erspan(ver=2,sid=0x%"PRIx16 + ",dir=%"PRIu8",hwid=0x%"PRIx8")", + get_sid(ersh), md2->dir, get_hwid(md2)); + } else { + VLOG_WARN("%s Invalid ERSPAN version %d\n", __func__, ersh->ver); + } } ds_put_format(ds, ")"); } @@ -1399,11 +1421,14 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) struct ovs_16aligned_ip6_hdr *ip6; struct udp_header *udp; struct gre_base_hdr *greh; - uint16_t gre_proto, gre_flags, dl_type, udp_src, udp_dst, csum; + struct erspan_base_hdr *ersh; + struct erspan_md2 *md2; + uint16_t gre_proto, gre_flags, dl_type, udp_src, udp_dst, csum, sid; ovs_be32 sip, dip; - uint32_t tnl_type = 0, header_len = 0, ip_len = 0; + uint32_t tnl_type = 0, header_len = 0, ip_len = 0, erspan_idx = 0; void *l3, *l4; int n = 0; + uint8_t hwid, dir; if (!ovs_scan_len(s, &n, "tnl_push(tnl_port(%"SCNi32"),", &data->tnl_port)) { return -EINVAL; @@ -1574,6 +1599,57 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) header_len = sizeof *eth + ip_len + ((uint8_t *) options - (uint8_t *) greh); + } else if (ovs_scan_len(s, &n, "erspan(ver=1,sid="SCNx16",idx=0x"SCNx32")", + &sid, &erspan_idx)) { + ersh = ERSPAN_HDR(greh); + ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *, + ersh + 1); + + if (eth->eth_type == htons(ETH_TYPE_IP)) { + tnl_type = OVS_VPORT_TYPE_ERSPAN; + } else { + tnl_type = OVS_VPORT_TYPE_IP6ERSPAN; + } + + greh->flags = htons(GRE_SEQ); + greh->protocol = htons(ETH_TYPE_ERSPAN1); + + ersh->ver = 1; + set_sid(ersh, sid); + put_16aligned_be32(index, htonl(erspan_idx)); + + if (!ovs_scan_len(s, &n, ")")) { + return -EINVAL; + } + header_len = sizeof *eth + ip_len + ERSPAN_GREHDR_LEN + + sizeof *ersh + ERSPAN_V1_MDSIZE; + + } else if (ovs_scan_len(s, &n, "erspan(ver=2,sid="SCNx16"dir="SCNu8 + ",hwid=0x"SCNx8")", &sid, &dir, &hwid)) { + + ersh = ERSPAN_HDR(greh); + md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + + if (eth->eth_type == htons(ETH_TYPE_IP)) { + tnl_type = OVS_VPORT_TYPE_ERSPAN; + } else { + tnl_type = OVS_VPORT_TYPE_IP6ERSPAN; + } + + greh->flags = htons(GRE_SEQ); + greh->protocol = htons(ETH_TYPE_ERSPAN2); + + ersh->ver = 2; + set_sid(ersh, sid); + set_hwid(md2, hwid); + md2->dir = dir; + + if (!ovs_scan_len(s, &n, ")")) { + return -EINVAL; + } + + header_len = sizeof *eth + ip_len + ERSPAN_GREHDR_LEN + + sizeof *ersh + ERSPAN_V2_MDSIZE; } else { return -EINVAL; } diff --git a/lib/odp-util.h b/lib/odp-util.h index 49467c9..6e684f8 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -147,7 +147,7 @@ void odp_portno_name_format(const struct hmap *portno_names, * add another field and forget to adjust this value. */ #define ODPUTIL_FLOW_KEY_BYTES 640 -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); /* A buffer with sufficient size and alignment to hold an nlattr-formatted flow * key. An array of "struct nlattr" might not, in theory, be sufficiently diff --git a/lib/ofp-match.c b/lib/ofp-match.c index acdf0b7..3a46b39 100644 --- a/lib/ofp-match.c +++ b/lib/ofp-match.c @@ -65,7 +65,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask) void ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); /* Initialize most of wc. */ flow_wildcards_init_catchall(wc); diff --git a/lib/packets.h b/lib/packets.h index b2bf706..7645a9d 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -32,6 +32,7 @@ #include "tun-metadata.h" #include "unaligned.h" #include "util.h" +#include "timeval.h" struct dp_packet; struct ds; @@ -404,6 +405,8 @@ ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, #define ETH_TYPE_MPLS 0x8847 #define ETH_TYPE_MPLS_MCAST 0x8848 #define ETH_TYPE_NSH 0x894f +#define ETH_TYPE_ERSPAN1 0x88be /* version 1 type II */ +#define ETH_TYPE_ERSPAN2 0x22eb /* version 2 type III */ static inline bool eth_type_mpls(ovs_be16 eth_type) { @@ -1246,6 +1249,129 @@ struct gre_base_hdr { #define GRE_FLAGS 0x00F8 #define GRE_VERSION 0x0007 +/* + * ERSPAN protocol header and metadata + * + * Version 1 (Type II) header (8 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS | En|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + * ERSPAN Version 2 (Type III) header (12 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS |BSO|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Timestamp | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SGT |P| FT | Hw ID |D|Gra|O| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + +/* ERSPAN has fixed 8-byte GRE header */ +#define ERSPAN_GREHDR_LEN 8 +#define ERSPAN_HDR(gre_base_hdr) \ + ((struct erspan_base_hdr *)((char *)gre_base_hdr + ERSPAN_GREHDR_LEN)) + +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 + +#define ERSPAN_SID_MASK 0x03ff /* 10-bit Session ID. */ +#define ERSPAN_IDX_MASK 0xfffff /* v1 Index */ +#define ERSPAN_HWID_MASK 0x03f0 +#define ERSPAN_DIR_MASK 0x0008 + +struct erspan_base_hdr { + uint8_t vlan_upper:4, + ver:4; + uint8_t vlan:8; + uint8_t session_id_upper:2, + t:1, + en:2, + cos:3; + uint8_t session_id:8; +}; + +struct erspan_md2 { + ovs_16aligned_be32 timestamp; + ovs_be16 sgt; + uint8_t hwid_upper:2, + ft:5, + p:1; + uint8_t o:1, + gra:2, + dir:1, + hwid:4; +}; + +struct erspan_metadata { + int version; + union { + ovs_be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ + } u; +}; + +static inline uint16_t get_sid(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->session_id_upper << 8) + ershdr->session_id; +} + +static inline void set_sid(struct erspan_base_hdr *ershdr, uint16_t id) +{ + ershdr->session_id = id & 0xff; + ershdr->session_id_upper = (id >> 8) &0x3; +} + +static inline uint8_t get_hwid(const struct erspan_md2 *md2) +{ + return (md2->hwid_upper << 4) + md2->hwid; +} + +static inline void set_hwid(struct erspan_md2 *md2, uint8_t hwid) +{ + md2->hwid = hwid & 0xf; + md2->hwid_upper = (hwid >> 4) & 0x3; +} + +/* ERSPAN timestamp granularity + * 00b --> granularity = 100 microseconds + * 01b --> granularity = 100 nanoseconds + * 10b --> granularity = IEEE 1588 + * Here we only support 100 microseconds. + */ +enum erspan_ts_gra { + ERSPAN_100US, + ERSPAN_100NS, + ERSPAN_IEEE1588, +}; + +static inline ovs_be32 get_erspan_ts(enum erspan_ts_gra gra) +{ + ovs_be32 ts = 0; + + switch (gra) { + case ERSPAN_100US: + ts = htonl((uint32_t)(time_wall_usec() / 100)); + break; + case ERSPAN_100NS: + /* fall back */ + case ERSPAN_IEEE1588: + /* fall back */ + default: + OVS_NOT_REACHED(); + break; + } + return ts; +} + /* VXLAN protocol header */ struct vxlanhdr { union { diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index b814f7a..5753179 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -171,7 +171,8 @@ tnl_type_to_nw_proto(const char type[]) if (!strcmp(type, "stt")) { return IPPROTO_TCP; } - if (!strcmp(type, "gre")) { + if (!strcmp(type, "gre") || !strcmp(type, "erspan") || + !strcmp(type, "ip6erspan")) { return IPPROTO_GRE; } if (!strcmp(type, "vxlan")) { diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h index 441584a..ab5b87a 100644 --- a/ofproto/ofproto-dpif-rid.h +++ b/ofproto/ofproto-dpif-rid.h @@ -99,7 +99,7 @@ struct rule; /* Metadata for restoring pipeline context after recirculation. Helpers * are inlined below to keep them together with the definition for easier * updates. */ -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); struct frozen_metadata { /* Metadata in struct flow. */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index ddb8349..c7c9df5 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3917,7 +3917,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, /* If 'struct flow' gets additional metadata, we'll need to zero it out * before traversing a patch port. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); memset(&flow_tnl, 0, sizeof flow_tnl); if (!check_output_prerequisites(ctx, xport, flow, check_stp)) { diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index a040b54..2fd6ffb 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -474,6 +474,19 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow, wc->masks.pkt_mark = UINT32_MAX; } + if (cfg->erspan_ver) { + flow->tunnel.erspan_ver = cfg->erspan_ver; + } + if (cfg->erspan_idx) { + flow->tunnel.erspan_idx = cfg->erspan_idx; + } + if (cfg->erspan_dir) { + flow->tunnel.erspan_dir = cfg->erspan_dir; + } + if (cfg->erspan_hwid) { + flow->tunnel.erspan_hwid = cfg->erspan_hwid; + } + if (pre_flow_str) { char *post_flow_str = flow_to_string(flow, NULL); char *tnl_str = tnl_port_to_string(tnl_port); diff --git a/tests/odp.at b/tests/odp.at index cdf3d66..64012c8 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -314,8 +314,8 @@ tnl_push(tnl_port(6),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:1 tnl_push(tnl_port(6),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(oam,vni=0x1c7)),out_port(1)) tnl_push(tnl_port(6),header(size=58,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(crit,vni=0x1c7,options({class=0xffff,type=0x80,len=4,0xa}))),out_port(1)) tnl_push(tnl_port(6),header(size=50,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0xffff),geneve(vni=0x1c7)),out_port(1)) -tnl_push(tnl_port(4),header(size=62,type=3,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x2000,proto=0x6558),key=0x1e241)),out_port(1)) -tnl_push(tnl_port(4),header(size=66,type=3,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0xa000,proto=0x6558),csum=0x0,key=0x1e241)),out_port(1)) +tnl_push(tnl_port(4),header(size=62,type=109,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x2000,proto=0x6558),key=0x1e241)),out_port(1)) +tnl_push(tnl_port(4),header(size=66,type=109,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0xa000,proto=0x6558),csum=0x0,key=0x1e241)),out_port(1)) tnl_push(tnl_port(6),header(size=70,type=4,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x1c7)),out_port(1)) tnl_push(tnl_port(6),header(size=70,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=6081,csum=0x0),geneve(oam,vni=0x1c7)),out_port(1)) tnl_push(tnl_port(6),header(size=78,type=5,eth(dst=f8:bc:12:44:34:b6,src=f8:bc:12:46:58:e0,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=6081,csum=0x0),geneve(crit,vni=0x1c7,options({class=0xffff,type=0x80,len=4,0xa}))),out_port(1)) diff --git a/tests/ofproto.at b/tests/ofproto.at index fff06eb..26a6ff6 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -2454,7 +2454,7 @@ head_table () { instructions: meter,apply_actions,clear_actions,write_actions,write_metadata,goto_table Write-Actions and Apply-Actions features: actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue - supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 dnl + supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_erspan_idx tun_erspan_ver tun_erspan_dir tun_erspan_hwid tun_metadata0 dnl tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl matching: @@ -2470,6 +2470,10 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 tun_flags: arbitrary mask tun_gbp_id: arbitrary mask tun_gbp_flags: arbitrary mask + tun_erspan_idx: arbitrary mask + tun_erspan_ver: arbitrary mask + tun_erspan_dir: arbitrary mask + tun_erspan_hwid: arbitrary mask tun_metadata0: arbitrary mask tun_metadata1: arbitrary mask tun_metadata2: arbitrary mask diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at index 772f62c..aff5fa7 100644 --- a/tests/tunnel-push-pop-ipv6.at +++ b/tests/tunnel-push-pop-ipv6.at @@ -1,5 +1,124 @@ AT_BANNER([tunnel_push_pop_ipv6]) +AT_SETUP([tunnel_push_pop_ipv6 - ip6erspan]) + +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) +AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=ip6erspan \ + options:remote_ip=2001:cafe::92 options:key=123 \ + options:erspan_ver=1 options:erspan_idx=3 ofport_request=2\ + -- add-port int-br t3 -- set Interface t3 type=ip6erspan \ + options:remote_ip=2001:cafe::93 options:key=567 \ + options:erspan_ver=2 options:erspan_dir=1 options:erspan_hwid=0x7 \ + ofport_request=3\ + ], [0]) + +AT_CHECK([ovs-appctl dpif/show], [0], [dnl +dummy@ovs-dummy: hit:0 missed:0 + br0: + br0 65534/100: (dummy-internal) + p0 1/1: (dummy) + int-br: + int-br 65534/2: (dummy-internal) + t2 2/6: (ip6erspan: erspan_idx=0x3, erspan_ver=1, key=123, remote_ip=2001:cafe::92) + t3 3/6: (ip6erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=2001:cafe::93) +]) + +dnl First setup dummy interface IP address, then add the route +dnl so that tnl-port table can get valid IP address for the device. +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK +]) +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK +]) + +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) + +dnl Check Neighbour discovery. +AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap]) + +AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)']) +AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1]) + +AT_CHECK([cat p0.pcap.txt | grep 92aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl +3333ff000092aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009287004d48000000002001cafe0000000000000000000000920101aa55aa550000 +]) +AT_CHECK([cat p0.pcap.txt | grep 93aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl +3333ff000093aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009387004d46000000002001cafe0000000000000000000000930101aa55aa550000 +]) + + +dnl +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)']) +dnl +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b7,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::93,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::93,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b7)']) + +dnl Check ARP Snoop +dnl AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::94,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)']) + +dnl AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b7,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::93,dst=2001:cafe::94,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::93,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b7)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:b6 br0 +2001:cafe::93 f8:bc:12:44:34:b7 br0 +]) + +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl +Listening ports: +ip6erspan_sys (6) ref_cnt=2 +]) + +dnl Check ERSPAN tunnel pop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=47,tclass=0x0,hlimit=64)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_pop(6) +]) + +dnl Check ERSPAN v1 tunnel push +AT_CHECK([ovs-ofctl add-flow int-br action=2]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(6),header(size=70,type=108,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),erspan(ver=1,sid=0x7b,idx=0x3)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 tunnel push +AT_CHECK([ovs-ofctl mod-flows int-br action=3]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(6),header(size=74,type=108,eth(dst=f8:bc:12:44:34:b7,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::93,label=0,proto=47,tclass=0x0,hlimit=64),erspan(ver=2,sid=0x237,dir=1,hwid=0x7)),out_port(100)),1) +]) + +ovs-appctl vlog/set dbg +dnl Check decapsulation of ERSPAN v1 +dnl Hex dump: GRE:(100088be) +dnl ERSPAN: v1, session id = 0x7b (1000007b), index=3 (00000003) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6486dd60000000006a2f402001cafe0000000000000000000000922001cafe000000000000000000000088100088be000000011000007b00000003fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6486dd60000000006a2f402001cafe0000000000000000000000922001cafe000000000000000000000088100088be000000011000007b00000003fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) + +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 2'], [0], [dnl + port 2: rx pkts=2, bytes=196, drop=?, errs=?, frame=?, over=?, crc=? +]) + +dnl Check decapsulation ERSPAN v2 +dnl Hex dump: GRE:(100022eb) +dnl ERSPAN: v2, session id = 0x237 (20000237), hwid = 8,dir = 1 (00000078) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6486dd60000000006a2f402001cafe0000000000000000000000932001cafe000000000000000000000088100022eb000000012000023710abcd0100000078fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) + +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl + port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=? +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel_push_pop_ipv6 - action]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) @@ -30,6 +149,14 @@ dummy@ovs-dummy: hit:0 missed:0 t5 6/3: (gre: key=455, packet_type=legacy_l3, remote_ip=2001:cafe::92) ]) +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl +Listening ports: +genev_sys_6081 (6081) ref_cnt=1 +gre_sys (3) ref_cnt=2 +vxlan_sys_4789 (4789) ref_cnt=2 +]) + + dnl First setup dummy interface IP address, then add the route dnl so that tnl-port table can get valid IP address for the device. AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK @@ -176,7 +303,7 @@ dnl Check GRE tunnel push AT_CHECK([ovs-ofctl add-flow int-br action=3]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], - [Datapath actions: clone(tnl_push(tnl_port(3),header(size=62,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x2000,proto=0x6558),key=0x1c8)),out_port(100)),1) + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=62,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x2000,proto=0x6558),key=0x1c8)),out_port(100)),1) ]) dnl Check Geneve tunnel push diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 4bd412e..a3b284a 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -1,5 +1,195 @@ AT_BANNER([tunnel_push_pop]) +AT_SETUP([tunnel_push_pop - erspan]) +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=erspan \ + options:remote_ip=1.1.2.92 options:key=123 options:erspan_ver=1 \ + options:erspan_idx=3 ofport_request=2 \ + -- add-port int-br t2 -- set Interface t2 type=erspan \ + options:remote_ip=1.1.2.92 options:key=567 options:erspan_ver=2 \ + options:erspan_dir=1 options:erspan_hwid=0x7 ofport_request=3\ + ], [0]) + +AT_CHECK([ovs-appctl dpif/show], [0], [dnl +dummy@ovs-dummy: hit:0 missed:0 + br0: + br0 65534/100: (dummy-internal) + p0 1/1: (dummy) + int-br: + int-br 65534/2: (dummy-internal) + t1 2/3: (erspan: erspan_idx=0x3, erspan_ver=1, key=123, remote_ip=1.1.2.92) + t2 3/3: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=1.1.2.92) +]) + +dnl First setup dummy interface IP address, then add the route +dnl so that tnl-port table can get valid IP address for the device. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK +]) +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK +]) + +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK +]) + +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0 pkt_mark=1234], [0], [OK +]) + +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) + +dnl Check ARP request +AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap]) + +AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)']) + +dnl Wait for the two ARP requests to be sent. Sometimes the system +dnl can be slow (e.g. under valgrind) +OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | sort | uniq | wc -l` -ge 1]) + +AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1]) + +AT_CHECK([cat p0.pcap.txt | grep 101025 | uniq], [0], [dnl +ffffffffffffaa55aa55000008060001080006040001aa55aa550000010102580000000000000101025c +]) + + +dnl Check ARP Snoop +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b7,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.93,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b7,tha=00:00:00:00:00:00)']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.94,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b8,tha=00:00:00:00:00:00)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:b6 br0 +1.1.2.93 f8:bc:12:44:34:b7 br0 +1.1.2.94 f8:bc:12:44:34:b8 br0 +]) + +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl +Listening ports: +erspan_sys (3) ref_cnt=2 +]) + +dnl Check ERSPAN v1 tunnel push +AT_CHECK([ovs-vsctl -- set Interface br0 options:pcap=br0.pcap]) +AT_CHECK([ovs-ofctl add-flow int-br action=2]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=50,type=107,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=1,sid=0x7b,idx=0x3)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 tunnel push +AT_CHECK([ovs-ofctl mod-flows int-br action=3]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x237,dir=1,hwid=0x7)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 flow-based tunnel push +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,4"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x1c8,dir=1,hwid=0x1)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 flow-based tunnel push, erspan_ver=flow +dnl Dynamically set erspan v2 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x38,dir=1,hwid=0x1)),out_port(100)),1) +]) + +dnl Dynamically set erspan v1 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_ver,set_field:1->tun_erspan_idx,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=50,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=1,sid=0x38,idx=0x1)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 flow-based tunnel push +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,4"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x1c8,dir=1,hwid=0x1)),out_port(100)),1) +]) + +dnl Check ERSPAN v2 flow-based tunnel push, erspan_ver=flow +dnl Dynamically set erspan v2 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x38,dir=1,hwid=0x1)),out_port(100)),1) +]) + +dnl Dynamically set erspan v1 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_ver,set_field:1->tun_erspan_idx,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=50,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=1,sid=0x38,idx=0x1)),out_port(100)),1) +]) + +dnl Check ERSPAN tunnel pop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.11.93,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_pop(3) +]) + +AT_CHECK([ovs-ofctl del-flows int-br]) + +dnl Check decapsulation of ERSPAN v1 +dnl Hex dump: GRE:(100088be) +dnl ERSPAN: v1, session id = 0x7b (1000007b), index=3 (00000003) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c01010258100088be000000011000007b00000003fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) + +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 2'], [0], [dnl + port 2: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=? +]) + +dnl Check decapsulation ERSPAN v2 +dnl Hex dump: GRE:(100022eb) +dnl ERSPAN: v2, session id = 0x237 (20000237), hwid =7, dir = 1 (00000078) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c01010258100022eb000000012000023710abcd0100000078fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) + +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl + port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=? +]) + +dnl Check ERSPAN encap in pcap file +dnl This ARP reply from p0 has two effects: +dnl 1. The ARP cache will learn that 1.1.2.92 is at f8:bc:12:44:34:b6. +dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0. +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(2),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) + +AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap]) + +dnl Output to tunnel from a int-br internal port +AT_CHECK([ovs-ofctl add-flow int-br "in_port=LOCAL,actions=output:2"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl netdev-dummy/receive int-br '50540000000a5054000000091234']) +dnl 100088be: GRE with ERSPANv1, 00000001: Seqno, 1000007b: v1 with 0x7b session ID (key) +OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100088be000000011000007b | wc -l` -ge 1]) + +AT_CHECK([ovs-ofctl mod-flows int-br "in_port=LOCAL,actions=output:3"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl netdev-dummy/receive int-br '50540000000a5054000000091235']) +dnl 100022eb: GRE with ERSPANv2, 00000001: Seqno, 20000237: v2 with 0x237 session ID (key) +OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100022eb0000000120000237 | wc -l` -ge 1]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel_push_pop - action]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) @@ -390,7 +580,7 @@ AT_CHECK([ovs-ofctl add-flow int-br action=3]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4789)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], - [Datapath actions: tnl_push(tnl_port(3),header(size=46,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x3000,proto=0x6558),key=0x1c8,seq=0x0)),out_port(100)) + [Datapath actions: clone(tnl_push(tnl_port(3),header(size=46,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x3000,proto=0x6558),key=0x1c8,seq=0x0)),out_port(100)),1) ]) dnl Verify outer L2 and L3 header flow fields can be matched in the underlay bridge diff --git a/tests/tunnel.at b/tests/tunnel.at index eeadb2f..620f4c8 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -406,6 +406,18 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([tunnel - ERSPAN]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=1]) + +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl + br0 65534/100: (dummy-internal) + p1 1/1: (erspan: remote_ip=1.1.1.1) +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel - different VXLAN UDP port]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \ options:remote_ip=1.1.1.1 ofport_request=1 options:dst_port=4341]) diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index acc1b03..3940b8d 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2633,6 +2633,40 @@ + +

    + Only erspan interfaces support these options. +

    + +

    + 20 bit index/port number associated with the ERSPAN traffic's + source port and direction (ingress/egress). This field is + platform dependent. +

    +
    + + +

    + ERSPAN version: 1 for version 1 (type II) + or 2 for version 2 (type III). +

    +
    + + +

    + Specifies the ERSPAN v2 mirrored traffic's direction. + 1 for egress traffic, and 0 for ingress traffic. +

    +
    + + +

    + ERSPAN hardware ID is a 6-bit unique identifier of an + ERSPAN v2 engine within a system. +

    +
    +
    +

    These options apply only to patch ports, that is, interfaces From patchwork Sat May 19 00:49:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916710 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="l2b7RVj5"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmyL5MVnz9s4w for ; Sat, 19 May 2018 11:03:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id AB8E2E64; Sat, 19 May 2018 00:50:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 77946C64 for ; Sat, 19 May 2018 00:50:23 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f67.google.com (mail-pg0-f67.google.com [74.125.83.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E14496D2 for ; Sat, 19 May 2018 00:50:21 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id u8-v6so3976543pgp.13 for ; Fri, 18 May 2018 17:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LxuEYziw4sRPr85yXE7A7if2HweMmiTeQX/EZdSMUOg=; b=l2b7RVj5AyoCEih7xt+slh5oJfvoFAVmNg/5bmYnkyXgnVfHC/NZBHAlGSKTpSBjVD A9M2W6GY7005fQA+I0LOA2gCWjXMtdCsjI+V8i/GdvZ3rvKL5C8xviEDK9JiAu5GhPyk jbaxA3tgB/nijLSotc6pFL1QFb/pzwFSllUQ/i3gZ1Vm3jDax5moH88B/7k4QXgxho+r I+I0YVsbjH6RWWchRWxoat5wXQ+TAUzmaugwaoF8fPTlNcGWID6DrAveJmIDvp25FKx0 J8bwWQH/1Xd9q4sq2AxUcmI8Mlnjc6cTagHL7RvV3+MnAgAC+lPBBfO+Sp7TRDkVrCbm 1AbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LxuEYziw4sRPr85yXE7A7if2HweMmiTeQX/EZdSMUOg=; b=d9QG7iYH7BHJMzF50NfrBAKLo3ZReAzT6qAThGPyECyCZVj/npJNjasJduRDpRF7bu xkdlMSiPjMgYLuF92eMXcz3rJ8dz5ORR+z2RTLfkD8kvwNemI/nraU4ttsVL3CrnJ1aB Ef6yajFpfeVmYwXAMaqZUY2+eGOEE21f11WpE92uxS564QGOodAHpaso3sk3Tbh2n5Hl mI0/C9a6BM9T8BlSCzOvD8fujv8BNLMl/1mZ4CsCWW3eyPsBI1YevCbuEGbxHICUqaGC Rv8mMgsG+dFZYx9NuvP/mCvKjJcPwjQlEzQLk9HUHVf+Z59RI15ajb4UDT4FpzAslNfp qP+A== X-Gm-Message-State: ALKqPwdUY2Od7PdB2wHCwLuXcAFnEtOUw/8MBPX/ZULskKNaAUQH4/8i lkvZEj7jJZZGX+A0ApjX3qEIpg== X-Google-Smtp-Source: AB8JxZrLuTCsmZImCuVmimHnK5SOWhGkMCcI7/y+CqaRq2Wb+xPQdZgIrhZ+WMwKoDSBS7++27NiSg== X-Received: by 2002:a63:18c:: with SMTP id 134-v6mr9026592pgb.138.1526691020587; Fri, 18 May 2018 17:50:20 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:20 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:35 -0700 Message-Id: <1526690988-29912-28-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 27/40] erspan: add kernel datapath support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu pass check, check-kernel (4.16-rc4), check-system-userspace Signed-off-by: William Tu --- V3 - Tunnels fixup --- lib/dpif-netlink-rtnl.c | 20 +++--- lib/dpif-netlink.c | 3 + lib/odp-util.c | 152 ++++++++++++++++++++++++++++++++++++++++++ tests/odp.at | 25 ++++++- tests/system-common-macros.at | 5 ++ tests/system-traffic.at | 147 ++++++++++++++++++++++++++++++++++++++++ tests/tunnel.at | 93 ++++++++++++++++++++++++++ 7 files changed, 435 insertions(+), 10 deletions(-) diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 63d3454..817e544 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -90,9 +90,6 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_VXLAN: return "vxlan"; case OVS_VPORT_TYPE_GRE: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L3) { return "gre"; } else if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L2) { @@ -102,6 +99,11 @@ vport_type_to_kind(enum ovs_vport_type type, } case OVS_VPORT_TYPE_GENEVE: return "geneve"; + case OVS_VPORT_TYPE_ERSPAN: + return "erspan"; + case OVS_VPORT_TYPE_IP6ERSPAN: + return "ip6erspan"; + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -256,6 +258,9 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, err = dpif_netlink_rtnl_vxlan_verify(tnl_cfg, kind, reply); break; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: err = dpif_netlink_rtnl_gre_verify(tnl_cfg, kind, reply); break; case OVS_VPORT_TYPE_GENEVE: @@ -265,9 +270,6 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -442,14 +444,14 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_VXLAN: case OVS_VPORT_TYPE_GRE: case OVS_VPORT_TYPE_GENEVE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: return dpif_netlink_rtnl_destroy(name); case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index a8b3ec6..f5ae21e 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -788,7 +788,10 @@ get_vport_type(const struct dpif_netlink_vport *vport) return "stt"; case OVS_VPORT_TYPE_ERSPAN: + return "erspan"; + case OVS_VPORT_TYPE_IP6ERSPAN: + return "ip6erspan"; case OVS_VPORT_TYPE_IP6GRE: return ""; diff --git a/lib/odp-util.c b/lib/odp-util.c index fc842ee..9c2b2c1 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2451,6 +2451,7 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + .next_max = OVS_VXLAN_EXT_MAX}, [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = 16 }, [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = 16 }, + [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = ATTR_LEN_VARIABLE }, }; const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = { @@ -2774,6 +2775,23 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask, case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: tun_metadata_from_geneve_nlattr(a, is_mask, tun); break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: { + int attr_len = nl_attr_get_size(a); + struct erspan_metadata opts; + + memcpy(&opts, nl_attr_get(a), attr_len); + + tun->erspan_ver = opts.version; + if (tun->erspan_ver == 1) { + tun->erspan_idx = ntohl(opts.u.index); + } else if (tun->erspan_ver == 2) { + tun->erspan_dir = opts.u.md2.dir; + tun->erspan_hwid = get_hwid(&opts.u.md2); + } else { + VLOG_WARN("%s invalid erspan version\n", __func__); + } + break; + } default: /* Allow this to show up as unexpected, if there are unknown @@ -2863,6 +2881,22 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a); } + if ((!tnl_type || !strcmp(tnl_type, "erspan") || + !strcmp(tnl_type, "ip6erspan")) && + (tun_key->erspan_ver == 1 || tun_key->erspan_ver == 2)) { + struct erspan_metadata opts; + + opts.version = tun_key->erspan_ver; + if (opts.version == 1) { + opts.u.index = htonl(tun_key->erspan_idx); + } else { + opts.u.md2.dir = tun_key->erspan_dir; + set_hwid(&opts.u.md2, tun_key->erspan_hwid); + } + nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, + &opts, sizeof(opts)); + } + nl_msg_end_nested(a, tun_key_ofs); } @@ -3318,6 +3352,46 @@ format_odp_tun_vxlan_opt(const struct nlattr *attr, ofpbuf_uninit(&ofp); } +static void +format_odp_tun_erspan_opt(const struct nlattr *attr, + const struct nlattr *mask_attr, struct ds *ds, + bool verbose) +{ + const struct erspan_metadata *opts, *mask; + uint8_t ver, ver_ma, dir, dir_ma, hwid, hwid_ma; + + opts = nl_attr_get(attr); + mask = mask_attr ? nl_attr_get(mask_attr) : NULL; + + ver = (uint8_t)opts->version; + if (mask) { + ver_ma = (uint8_t)mask->version; + } + + format_u8u(ds, "ver", ver, mask ? &ver_ma : NULL, verbose); + + if (opts->version == 1) { + if (mask) { + ds_put_format(ds, "idx=%#"PRIx32"/%#"PRIx32",", + ntohl(opts->u.index), + ntohl(mask->u.index)); + } else { + ds_put_format(ds, "idx=%#"PRIx32",", ntohl(opts->u.index)); + } + } else if (opts->version == 2) { + dir = opts->u.md2.dir; + hwid = opts->u.md2.hwid; + if (mask) { + dir_ma = mask->u.md2.dir; + hwid_ma = mask->u.md2.hwid; + } + + format_u8u(ds, "dir", dir, mask ? &dir_ma : NULL, verbose); + format_u8x(ds, "hwid", hwid, mask ? &hwid_ma : NULL, verbose); + } + ds_chomp(ds, ','); +} + #define MASK(PTR, FIELD) PTR ? &PTR->FIELD : NULL static void @@ -3566,6 +3640,9 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr, case OVS_TUNNEL_KEY_ATTR_PAD: break; case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + ds_put_cstr(ds, "erspan("); + format_odp_tun_erspan_opt(a, ma, ds, verbose); + ds_put_cstr(ds, "),"); break; case __OVS_TUNNEL_KEY_ATTR_MAX: default: @@ -4751,6 +4828,70 @@ scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask) } static int +scan_erspan_metadata(const char *s, + struct erspan_metadata *key, + struct erspan_metadata *mask) +{ + const char *s_base = s; + uint32_t idx = 0, idx_mask = 0; + uint8_t ver = 0, dir = 0, hwid = 0; + uint8_t ver_mask = 0, dir_mask = 0, hwid_mask = 0; + + if (!strncmp(s, "ver=", 4)) { + s += 4; + s += scan_u8(s, &ver, mask ? &ver_mask : NULL); + } + + if (s[0] == ',') { + s++; + } + + if (ver == 1) { + if (!strncmp(s, "idx=", 4)) { + s += 4; + s += scan_u32(s, &idx, mask ? &idx_mask : NULL); + } + + if (!strncmp(s, ")", 1)) { + s += 1; + key->version = ver; + key->u.index = htonl(idx); + if (mask) { + mask->u.index = htonl(idx_mask); + } + } + return s - s_base; + + } else if (ver == 2) { + if (!strncmp(s, "dir=", 4)) { + s += 4; + s += scan_u8(s, &dir, mask ? &dir_mask : NULL); + } + if (s[0] == ',') { + s++; + } + if (!strncmp(s, "hwid=", 5)) { + s += 5; + s += scan_u8(s, &hwid, mask ? &hwid_mask : NULL); + } + + if (!strncmp(s, ")", 1)) { + s += 1; + key->version = ver; + key->u.md2.hwid = hwid; + key->u.md2.dir = dir; + if (mask) { + mask->u.md2.hwid = hwid_mask; + mask->u.md2.dir = dir_mask; + } + } + return s - s_base; + } + + return 0; +} + +static int scan_geneve(const char *s, struct geneve_scan *key, struct geneve_scan *mask) { const char *s_base = s; @@ -4885,6 +5026,15 @@ geneve_to_attr(struct ofpbuf *a, const void *data_) geneve->len); } +static void +erspan_to_attr(struct ofpbuf *a, const void *data_) +{ + const struct erspan_metadata *md = data_; + + nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, md, + sizeof *md); +} + #define SCAN_PUT_ATTR(BUF, ATTR, DATA, FUNC) \ { \ unsigned long call_fn = (unsigned long)FUNC; \ @@ -5253,6 +5403,8 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, SCAN_FIELD_NESTED("ttl=", uint8_t, u8, OVS_TUNNEL_KEY_ATTR_TTL); SCAN_FIELD_NESTED("tp_src=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_SRC); SCAN_FIELD_NESTED("tp_dst=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_DST); + SCAN_FIELD_NESTED_FUNC("erspan(", struct erspan_metadata, erspan_metadata, + erspan_to_attr); SCAN_FIELD_NESTED_FUNC("vxlan(gbp(", uint32_t, vxlan_gbp, vxlan_gbp_to_attr); SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve, geneve_to_attr); diff --git a/tests/odp.at b/tests/odp.at index 64012c8..aad89e8 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -80,6 +80,16 @@ sed 's/^/skb_priority(0),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt | s echo echo '# Valid forms with IP later fragment.' sed 's/^/skb_priority(0),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt | sed -n 's/,frag=no),.*/,frag=later)/p' + + echo + echo '# Valid forms with tunnel and ERSPAN v1 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=1,idx=0x7),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v2 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=2,dir=0x1,hwid=0x7),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt ) > odp-in.txt AT_CAPTURE_FILE([odp-in.txt]) @@ -172,7 +182,18 @@ sed -n 's/,frag=no),/,frag=first),/p' odp-base.txt echo echo '# Valid forms with IP later fragment.' -sed -n 's/,frag=no),.*/,frag=later)/p' odp-base.txt) > odp.txt +sed -n 's/,frag=no),.*/,frag=later)/p' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v1 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=1/0,idx=0x7/0xf),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v2 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=2,dir=0x1,hwid=0x7/0xf),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt +) > odp.txt AT_CAPTURE_FILE([odp.txt]) AT_CHECK_UNQUOTED([ovstest test-odp parse-wc-keys < odp.txt], [0], [`cat odp.txt` ]) @@ -358,6 +379,8 @@ ct_clear trunc(100) clone(1) clone(clone(push_vlan(vid=12,pcp=0),2),1) +set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))) +set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=2,dir=1,hwid=0x1),flags(df|key))) ]) AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [`cat actions.txt` diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at index d2a9b59..64bf5ec 100644 --- a/tests/system-common-macros.at +++ b/tests/system-common-macros.at @@ -297,6 +297,11 @@ m4_define([OVS_CHECK_GRE], [AT_SKIP_IF([! ip link add foo type gretap help 2>&1 | grep gretap >/dev/null]) OVS_CHECK_FIREWALL()]) +# OVS_CHECK_ERSPAN() +m4_define([OVS_CHECK_ERSPAN], + [AT_SKIP_IF([! ip link add foo type erspan help 2>&1 | grep erspan >/dev/null]) + OVS_CHECK_FIREWALL()]) + # OVS_CHECK_GRE_L3() m4_define([OVS_CHECK_GRE_L3], [AT_SKIP_IF([! ip link add foo type gre help 2>&1 | grep "gre " >/dev/null]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 58db095..2c74161 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -339,6 +339,153 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([datapath - ping over erspan v1 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24") +AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL([erspan], [br0], [at_erspan0], [172.31.1.1], [10.1.1.100/24], [options:key=1 options:erspan_ver=1 options:erspan_idx=7]) +ADD_NATIVE_TUNNEL([erspan], [ns_erspan0], [at_ns0], [172.31.1.100], [10.1.1.1/24], [seq key 1 erspan_ver 1 erspan 7]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +dnl NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +NS_CHECK_EXEC([at_ns0], [ping -s 1200 -i 0.3 -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over erspan v2 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24") +AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL([erspan], [br0], [at_erspan0], [172.31.1.1], [10.1.1.100/24], [options:key=1 options:erspan_ver=2 options:erspan_dir=1 options:erspan_hwid=0x7]) +ADD_NATIVE_TUNNEL([erspan], [ns_erspan0], [at_ns0], [172.31.1.100], [10.1.1.1/24], [seq key 1 erspan_ver 2 erspan_dir egress erspan_hwid 7]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +dnl NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +NS_CHECK_EXEC([at_ns0], [ping -s 1200 -i 0.3 -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over ip6erspan v1 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad) +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL6([ip6erspan], [br0], [at_erspan0], [fc00:100::1], [10.1.1.100/24], + [options:key=123 options:erspan_ver=1 options:erspan_idx=0x7]) +ADD_NATIVE_TUNNEL6([ip6erspan], [ns_erspan0], [at_ns0], [fc00:100::100], + [10.1.1.1/24], [local fc00:100::1 seq key 123 erspan_ver 1 erspan 7]) + +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over ip6erspan v2 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad) +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL6([ip6erspan], [br0], [at_erspan0], [fc00:100::1], [10.1.1.100/24], + [options:key=121 options:erspan_ver=2 options:erspan_dir=0 options:erspan_hwid=0x7]) +ADD_NATIVE_TUNNEL6([ip6erspan], [ns_erspan0], [at_ns0], [fc00:100::100], + [10.1.1.1/24], + [local fc00:100::1 seq key 121 erspan_ver 2 erspan_dir ingress erspan_hwid 0x7]) + +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([datapath - ping over geneve tunnel]) OVS_CHECK_GENEVE() diff --git a/tests/tunnel.at b/tests/tunnel.at index 620f4c8..315453d 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -478,6 +478,99 @@ AT_CHECK([tail -1 stdout], [0], OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([tunnel - ERSPAN v1/v2 metadata]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy \ + ofport_request=1 \ + -- add-port br0 p2 -- set Interface p2 type=dummy \ + ofport_request=2 \ + -- add-port br0 p3 -- set Interface p3 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=3 \ + options:key=1 options:erspan_ver=1 options:erspan_idx=7 \ + -- add-port br0 p4 -- set Interface p4 type=erspan \ + options:remote_ip=1.1.1.2 ofport_request=4 \ + options:key=2 options:erspan_ver=2 options:erspan_dir=1 options:erspan_hwid=7 \ + ]) +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP + +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl + br0 65534/100: (dummy-internal) + p1 1/3: (dummy) + p2 2/2: (dummy) + p3 3/1: (erspan: erspan_idx=0x7, erspan_ver=1, key=1, remote_ip=1.1.1.1) + p4 4/1: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=2, remote_ip=1.1.1.2) +]) + +AT_DATA([flows.txt], [dnl +in_port=1,actions=3 +in_port=2,actions=4 +in_port=3,tun_erspan_ver=1,tun_erspan_idx=0x7,actions=1 +in_port=4,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0xf/0x1,actions=2 +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +dnl test encap: in_port=1,actions=3 (erspan v1 port) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))),1 +]) + +dnl test encap: in_port=2,actions=4 (erspan v2 port) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0x2,dst=1.1.1.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key))),1 +]) + +dnl receive packet from ERSPAN port with v1 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no +Datapath actions: 3 +]) + +dnl receive packet from ERSPAN port with wrong v1 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0xabcd),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no +Datapath actions: drop +]) + +dnl receive packet from ERSPAN port with v2 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=1,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: 2 +]) + +dnl receive packet from ERSPAN port with wrong v2 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=0,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: drop +]) + +dnl test wildcard mask: recevie all v2 regardless of its metadata +AT_CHECK([ovs-ofctl del-flows br0 in_port=4,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0xf/0x1]) +AT_CHECK([ovs-ofctl add-flow br0 in_port=4,tun_erspan_ver=2,tun_erspan_dir=0/0,tun_erspan_hwid=0x0/0x0,actions=2]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=output:3 + in_port=2 actions=output:4 + erspan_ver=1,erspan_idx=0x7,in_port=3 actions=output:1 + erspan_ver=2,in_port=4 actions=output:2 +]) + +dnl this time it won't drop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: 2 +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel - Geneve metadata]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \ options:remote_ip=1.1.1.1 ofport_request=1 \ From patchwork Sat May 19 00:49:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916707 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tGxrU8Or"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmwW0tg5z9s4w for ; Sat, 19 May 2018 11:02:19 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B6BF4E6A; Sat, 19 May 2018 00:50:47 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7540AC9F for ; Sat, 19 May 2018 00:50:22 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 202F76CF for ; Sat, 19 May 2018 00:50:22 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id bi12-v6so5481226plb.12 for ; Fri, 18 May 2018 17:50:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6gPwmbsxlJ++SQ1QOTKcmra14PfdL0ZHlWMKQ4vPL58=; b=tGxrU8OrsJIkMp84z2F4uvHwXGh0lW4x+j0JFg9BiZmL+EziSMbNJqQpb8E+NkCTxh utxD4Okn5mAvqEMtEKgF61UzBWImQEaqJ3mUMe2SrWmtFoLPVPSfmmZfoEhy3FwvRBY2 hxp1PCz7fthUaMMwww51s+m55Nx8/JWR1y2KhTonyHBx5xpYdmv4DoGj2J4ofhspPGzl UWWrft5drNbEqE54kZPe1kpgCGDPYxh9OeK5Xe/JmPremmlzkyWuoOQMYn1rpR5Ow7ZK WwSwPIUWg4a9FNX4iTz+N6rJhWAZ3POTPVkzCSK8s55Caktdrv9SNyI7IltIIMi8n50o JMQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6gPwmbsxlJ++SQ1QOTKcmra14PfdL0ZHlWMKQ4vPL58=; b=YB6+fwCveBZNf8sLx68rN8CGKB/tz2jNYXYFcjkFpudC0rj3Rp1gInL75os6ptciLJ 1V0EYgk5/mnssqL4AND3J94RxlDeg6eY409jpdIDNReD6m0x8SzZjKqLJ34dnrsoV9f8 IXDqIvRdLKbbLk9ekdqItkSCme20KVZH/lc/VmQYjCmMiGYOajP24MVNchnZ3xoYdiMI cG085w5BfwF1+LIiZDboJHS0SyF58iHU1+P7mMAJGmoZd9xm6oLOHwZE1w7AaaQtyvvw x3I+PFllF18pPDj7iGDIhubCCc9UoKg3qgQKM7ggQEo/d0lYXbUQBf1Ey0SesDqanvCq ZMZg== X-Gm-Message-State: ALKqPwez6hOB90a7cJOhCVFEdha4bGso9xcYFJQf6tovJ/pJNGYcf/fx Cw0vF/3U6+OrNPzVXNDyvtbU5g== X-Google-Smtp-Source: AB8JxZpaqrRh5MaHeg/Rh3v1soZ6It/9tphIGqfaU3QSp+3V+GMBfIPEqTB9jRicX50HWoiFqQp/2Q== X-Received: by 2002:a17:902:622:: with SMTP id 31-v6mr3745732plg.135.1526691021465; Fri, 18 May 2018 17:50:21 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:21 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:36 -0700 Message-Id: <1526690988-29912-29-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 28/40] openvswitch: fix vport packet length check. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 46e371f0e78a82186a83cbcb4f4b8850417c7dd5 Author: William Tu Date: Wed Mar 7 15:38:48 2018 -0800 openvswitch: fix vport packet length check. When sending a packet to a tunnel device, the dev's hard_header_len could be larger than the skb->len in function packet_length(). In the case of ip6gretap/erspan, hard_header_len = LL_MAX_HEADER + t_hlen, which is around 180, and an ARP packet sent to this tunnel has skb->len = 42. This causes the 'unsign int length' to become super large because it is negative value, causing the later ovs_vport_send to drop it due to over-mtu size. The patch fixes it by setting it to 0. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/vport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/datapath/vport.c b/datapath/vport.c index f4131be..184c859 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -520,10 +520,10 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, return 0; } -static unsigned int packet_length(const struct sk_buff *skb, - struct net_device *dev) +static int packet_length(const struct sk_buff *skb, + struct net_device *dev) { - unsigned int length = skb->len - dev->hard_header_len; + int length = skb->len - dev->hard_header_len; if (!skb_vlan_tag_present(skb) && eth_type_vlan(skb->protocol)) @@ -534,7 +534,7 @@ static unsigned int packet_length(const struct sk_buff *skb, * account for 802.1ad. e.g. is_skb_forwardable(). */ - return length; + return length > 0 ? length: 0; } void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto) From patchwork Sat May 19 00:49:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916711 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="aUzUDKXg"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmyy2hQPz9s4w for ; Sat, 19 May 2018 11:04:26 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 15662E9B; Sat, 19 May 2018 00:50:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8AA72C9F for ; Sat, 19 May 2018 00:50:23 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f68.google.com (mail-pg0-f68.google.com [74.125.83.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 137DC473 for ; Sat, 19 May 2018 00:50:23 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id 11-v6so2348967pge.2 for ; Fri, 18 May 2018 17:50:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EJrXAlS7rn25ITrnXEOaZl5ND1LXojmiV0efrc4UHrE=; b=aUzUDKXgmSI8criVDrMke1q6rypxDUugRVlTEn735lHwMNhV74XOYx4fKvmokds43k D08bWpSym/vhsaz8hYEqr5FLW5OFDVmv59Lh2B3ZG+Yap57qfX8VI2jtaUfuAy1NjqMU 6OtfYHVlOpD8asUwZiz1GSk2rnfVUsQx0xkvLEMDHTzMJW3GGac7jZJZl9CbbqRj2jZF uhPipeylXJSQsqUJJGs6lUss/6/lx3RilGpse0yjSFFe8Z3EawUkKE3CcGrFKklNd0nb fO0CRqWVYlCXWGjpTbZ0X0gcIrSOrB56Dhq0fHGkB37Hgj/TLsMBB+cuMYlOiOBhW+iD oSVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EJrXAlS7rn25ITrnXEOaZl5ND1LXojmiV0efrc4UHrE=; b=n17xHlxbesjvosM0LYe4QXC6FY7oaWJM1P8O3UKCahpvRN2IF6boESDZw0es2bLzw2 3Yl0cpKgaTjHsM8M6S/QW87jKgLSwT02kIKgZ62NFkJh6aJYGqipWztZr5iNWn044iph pNASZ4Hexe2fqRVh2RzmdCktOfVoGOex9kuwFaHgCLfjUrmdzkqsw8tQXPLTskeXD4nm jkq91cyQJo/+VWGvV3+GnAGap8bdSxcuwpxvmzTjUvlerIYxzj/J5pqBm7y+EbPOhOjn jIWR0VMIWig3OkpRDaYf0yDdCsPOHAHuqyB0OwscBpaW+PQ2MEg6jWmg5JifsNFJdrfN j0Lw== X-Gm-Message-State: ALKqPwdlnqqPQ529kAEworLnce6saPOSsw5qBxXYSByIfRmTgctE9bIA T6cyk2EjSeTO7bPJVOm54wywrg== X-Google-Smtp-Source: AB8JxZpXhX4dV0muzITygOnSPYArEpEhG76oR9UEiHB51nrnwRvsm8tRDwHidLRVubPH87CRPBxfSA== X-Received: by 2002:a65:5883:: with SMTP id d3-v6mr9154478pgu.131.1526691022346; Fri, 18 May 2018 17:50:22 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:21 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:37 -0700 Message-Id: <1526690988-29912-30-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 29/40] erspan: auto detect truncated packets. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 1baf5ebf8954d9bff8fa4e7dd6c416a0cebdb9e2 Author: William Tu Date: Fri Apr 27 14:16:32 2018 -0700 erspan: auto detect truncated packets. Currently the truncated bit is set only when the mirrored packet is larger than mtu. For certain cases, the packet might already been truncated before sending to the erspan tunnel. In this case, the patch detect whether the IP header's total length is larger than the actual skb->len. If true, this indicated that the mirrored packet is truncated and set the erspan truncate bit. I tested the patch using bpf_skb_change_tail helper function to shrink the packet size and send to erspan tunnel. Reported-by: Xiaoyan Jin Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 6 ++++++ datapath/linux/compat/ip_gre.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 085d04f..e0246d1 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1069,6 +1069,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, int err = -EINVAL; __be32 tun_id; __u32 mtu; + int nhoff; /* OVS doesn't support native mode ip6 tunnel traffic so @@ -1087,6 +1088,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, truncate = true; } + nhoff = skb_network_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IP) && + (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) + truncate = true; + t->parms.o_flags &= ~TUNNEL_KEY; IPCB(skb)->flags = 0; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 958965f..6b40013 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -631,6 +631,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, int tunnel_hlen; int version; __be16 df; + int nhoff; tun_info = skb_tunnel_info(skb); if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || @@ -658,6 +659,11 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, truncate = true; } + nhoff = skb_network_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IP) && + (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) + truncate = true; + if (version == 1) { erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), ntohl(md->u.index), truncate, true); From patchwork Sat May 19 00:49:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916712 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FGiWBAqi"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nmzX0vn4z9s4w for ; Sat, 19 May 2018 11:04:56 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0DA98E9C; Sat, 19 May 2018 00:50:56 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DC085D20 for ; Sat, 19 May 2018 00:50:24 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f44.google.com (mail-pl0-f44.google.com [209.85.160.44]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id EC4DC6D2 for ; Sat, 19 May 2018 00:50:23 +0000 (UTC) Received: by mail-pl0-f44.google.com with SMTP id i5-v6so5503397plt.2 for ; Fri, 18 May 2018 17:50:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=K/9Qe2zgTrlKp+CLvXRcq1ZzLDe9uo5frgiMz8NFqs4=; b=FGiWBAqiVYYZ44qHDR8h+G/KOCD71Dh4Nntv4ktG9o02ev6I51yHgeqv3UIz25447g xLCRFZECGffzTKgdvmNYWKnwOW6Y/x8sC+chioS8FSBtWLjV9QNtoonDbU9sWMaXMe3+ gZaOnabtioSbPOPZY1anlWRFLMgQpofKbu7jUfpYSVVU7HgEU+eOU3a0RHRvTMSyOVok MJhDyQaxtfYxDA6U24DiimsG+Y2x6saiCMehQskiER+3E+MpteZu6uGf7tgt1NgtvIwA eNO5Q8qqbq0uTrJu3tLXuN7RlibvSdsbgFVZpxo9vTUhytoPD1HnqCr7vZoASyeKKG6l E3/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=K/9Qe2zgTrlKp+CLvXRcq1ZzLDe9uo5frgiMz8NFqs4=; b=q/O6A7+EROgwHR0Q6XGXlthQiTEzf8MZj9DMG+ZNd7r7Co8npYqynrDHWDEzFSkpdT OAUfSabbURWNGmyrbWf9TW7v6LBTN98/C+FlfKpa4e9hWkhuP+L0QrdlUP+BXSUx6pVL zmexxsuchtkOialj/jqMnBjZCemlPWGyrexemHi/rxmivJ3QGiAKX5arHuV/a880rt9j TaKSiuG2zghznC/7yH44KTNhEpkLwhMCOnOi/5VKgunRN1nrZDDdI3bi/2PHcApHBScJ +4Y/AgIiIiIO1MT0zTSY/YjqwENhyzwhsCx+3NlJxsST4bPkkVZz9A+tS0Z+QJHO6I6j 9sjw== X-Gm-Message-State: ALKqPwc1Lyt4NRcMJJ5kyP8zCqHVWEGs/YdpSTh5XiOZi+N0M01myt2T jMQKMlr9DZPZnvSaVHVdv8zLBQ== X-Google-Smtp-Source: AB8JxZqJfj1fuAU84+kR7KFVqiukuzj1+FjmPma3/TCHTA+vi8GDU4GkVDwTEXPiLLw+VAm7jUOn2g== X-Received: by 2002:a17:902:e85:: with SMTP id 5-v6mr11687890plx.318.1526691023295; Fri, 18 May 2018 17:50:23 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:22 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:38 -0700 Message-Id: <1526690988-29912-31-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 30/40] ip6gre: Add ip6gre vport type X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Add handlers for OVS_VPORT_TYPE_IP6GRE Cc: Ben Pfaff Signed-off-by: Greg Rose Acked-by: William Tu --- V2 - Folded in additional change from Ben Pfaff as per his suggestion. --- lib/dpif-netlink-rtnl.c | 4 +++- lib/dpif-netlink.c | 7 +++++-- lib/netdev-native-tnl.c | 8 ++++++-- lib/netdev-vport.c | 4 ++++ lib/odp-util.c | 9 +++++++-- lib/tnl-ports.c | 2 +- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 817e544..bec3fce 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -104,6 +104,7 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_IP6ERSPAN: return "ip6erspan"; case OVS_VPORT_TYPE_IP6GRE: + return "ip6gre"; case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -349,7 +350,8 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, nl_msg_end_nested(&request, linkinfo_off); err = nl_transact(NETLINK_ROUTE, &request, NULL); - if (!err && type == OVS_VPORT_TYPE_GRE) { + if (!err && (type == OVS_VPORT_TYPE_GRE || + type == OVS_VPORT_TYPE_IP6GRE)) { /* Work around a bug in kernel GRE driver, which ignores IFLA_MTU in * RTM_NEWLINK, by setting the MTU again. See * https://bugzilla.redhat.com/show_bug.cgi?id=1488484. */ diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index f5ae21e..607b497 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -791,9 +791,10 @@ get_vport_type(const struct dpif_netlink_vport *vport) return "erspan"; case OVS_VPORT_TYPE_IP6ERSPAN: - return "ip6erspan"; + return "ip6erspan"; + case OVS_VPORT_TYPE_IP6GRE: - return ""; + return "ip6gre"; case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: @@ -826,6 +827,8 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_ERSPAN; } else if (!strcmp(type, "ip6erspan")) { return OVS_VPORT_TYPE_IP6ERSPAN; + } else if (!strcmp(type, "ip6gre")) { + return OVS_VPORT_TYPE_IP6GRE; } else { return OVS_VPORT_TYPE_UNSPEC; } diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 66eb18e..c70811e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -513,7 +513,11 @@ netdev_gre_build_header(const struct netdev *netdev, hlen = (uint8_t *) options - (uint8_t *) greh; data->header_len += hlen; - data->tnl_type = OVS_VPORT_TYPE_GRE; + if (!params->is_ipv6) { + data->tnl_type = OVS_VPORT_TYPE_GRE; + } else { + data->tnl_type = OVS_VPORT_TYPE_IP6GRE; + } return 0; } @@ -552,7 +556,7 @@ netdev_erspan_pop_header(struct dp_packet *packet) } ersh = ERSPAN_HDR(greh); - tnl->tun_id = be32_to_be64(be16_to_be32(htons(get_sid(ersh)))); + tnl->tun_id = be16_to_be64(htons(get_sid(ersh))); tnl->erspan_ver = ersh->ver; if (ersh->ver == 1) { diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 4311d2b..805f130 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -1042,6 +1042,10 @@ netdev_vport_tunnel_register(void) netdev_erspan_push_header, netdev_erspan_pop_header, NULL), + TUNNEL_CLASS("ip6gre", "ip6gre_sys", netdev_gre_build_header, + netdev_gre_push_header, + netdev_gre_pop_header, + NULL), }; static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; diff --git a/lib/odp-util.c b/lib/odp-util.c index 9c2b2c1..105ac80 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -690,7 +690,8 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) } ds_put_char(ds, ')'); - } else if (data->tnl_type == OVS_VPORT_TYPE_GRE) { + } else if (data->tnl_type == OVS_VPORT_TYPE_GRE || + data->tnl_type == OVS_VPORT_TYPE_IP6GRE) { const struct gre_base_hdr *greh; ovs_16aligned_be32 *options; @@ -1559,7 +1560,11 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) } else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")", &gre_flags, &gre_proto)){ - tnl_type = OVS_VPORT_TYPE_GRE; + if (eth->eth_type == htons(ETH_TYPE_IP)) { + tnl_type = OVS_VPORT_TYPE_GRE; + } else { + tnl_type = OVS_VPORT_TYPE_IP6GRE; + } greh->flags = htons(gre_flags); greh->protocol = htons(gre_proto); ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1); diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index 5753179..1735304 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -172,7 +172,7 @@ tnl_type_to_nw_proto(const char type[]) return IPPROTO_TCP; } if (!strcmp(type, "gre") || !strcmp(type, "erspan") || - !strcmp(type, "ip6erspan")) { + !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) { return IPPROTO_GRE; } if (!strcmp(type, "vxlan")) { From patchwork Sat May 19 00:49:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916713 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ZI/gQAG1"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn0634Nyz9s4w for ; Sat, 19 May 2018 11:05:26 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3D7F2E33; Sat, 19 May 2018 00:50:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 0CA6DCE4 for ; Sat, 19 May 2018 00:50:25 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f54.google.com (mail-pl0-f54.google.com [209.85.160.54]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id C77B76CE for ; Sat, 19 May 2018 00:50:24 +0000 (UTC) Received: by mail-pl0-f54.google.com with SMTP id c19-v6so5498349pls.6 for ; Fri, 18 May 2018 17:50:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gvO1Ufb5yFJUI7PYlTLQJ9zxolaDu+bZzqmXrwvm1XQ=; b=ZI/gQAG1FDmVTJjjDOH+gGSN0Oo9BlR7PtYVNdRm7FOdmI0SHYgxXLj2GKNLZ1GeQ5 Cbi7GGjpi5LcisHAgR+GaAi4OhdkOErW/y2/nWM3pv6zTButE7TupoHbuY8ZrKgxVhoB 2U1L1dJvsxGsq1L8zEYLHgaYN819DUrApAk4uwQ2Kjul12em1ZFcjBDj+O8MSti2//xc RBXKsHyDxMiAqjmGKWiqLN6UJWXXhMztPhRDbJPkqHM3K9b2N6WWGZLSZE1xSK8rNPKj bJ4N4xJdMbvbCPj64+JTi1RHPYdD35i7E6GBnd+8T1kxQY+KbFmzmwajz7tHaBtv01yJ QyZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gvO1Ufb5yFJUI7PYlTLQJ9zxolaDu+bZzqmXrwvm1XQ=; b=ltKwJinv7JtfXS0oMMwDicY3wSxNt8UNZFoYc9MglmX8Tm/U7Urejjxl54KrHMt20C KvMLDFHFt1q06Zn3QXnxs9kYACHbCxUdbT8C4YptZFmHq5mCpcmWk1yT1uIU1yoCQcTX 2bdfjoVSpYdA2Whq7Dda2QC6aEKp6N8ZDIcLaUbkNyEk44TEtUo+iFheUBUyjhzByA28 YUaoNR+kIfUyHHfx58RjqLtdEQMnebk3q/4Y+evrNU4Zbq00iFLlkoT/1UvCilQ0pYfG oz1C3f/0aiaPDa5AXxlNNmhHbALYJknPwCMt+zAgfVTGy/qph9QBbSnzIqSzBYxrFmEe 2qhg== X-Gm-Message-State: ALKqPwdBRVcG9hZySyX58E/mJA+8D9qdHu1h5XUcn8IcznuwsMe5EXKf ng1OOihrounSgWfNABn0bQLI0w== X-Google-Smtp-Source: AB8JxZoOHBcqiklujyd0QLbfVeJ/emLhcyCop0BUwivRqU6r+eFCLORqo+2Z2Ny27/wUHF0897/Tkw== X-Received: by 2002:a17:902:4483:: with SMTP id l3-v6mr11742049pld.282.1526691024183; Fri, 18 May 2018 17:50:24 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:23 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:39 -0700 Message-Id: <1526690988-29912-32-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 31/40] lib/dpif-netlink: Fix miscompare of gre ports X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org In netdev_to_ovs_vport_type() it checks for netdev types matching "gre" with a strstr(). This makes it match ip6gre as well and return OVS_VPORT_TYPE_GRE, which is clearly wrong. Move the usage of strstr() *after* all the exact matches with strcmp() to avoid the problem permanently because when I added the ip6gre type I ran into a very difficult to detect bug. Cc: Ben Pfaff Signed-off-by: Greg Rose Acked-by: William Tu --- V2 - Removed strstr for gre completely as per Ben's feedback. V3 - Fix mucked up V2 where strcmp was used instead of !strcmp --- lib/dpif-netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 607b497..41f42dc 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -817,8 +817,6 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_STT; } else if (!strcmp(type, "geneve")) { return OVS_VPORT_TYPE_GENEVE; - } else if (strstr(type, "gre")) { - return OVS_VPORT_TYPE_GRE; } else if (!strcmp(type, "vxlan")) { return OVS_VPORT_TYPE_VXLAN; } else if (!strcmp(type, "lisp")) { @@ -829,6 +827,8 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_IP6ERSPAN; } else if (!strcmp(type, "ip6gre")) { return OVS_VPORT_TYPE_IP6GRE; + } else if (!strcmp(type, "gre")) { + return OVS_VPORT_TYPE_GRE; } else { return OVS_VPORT_TYPE_UNSPEC; } From patchwork Sat May 19 00:49:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916715 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="i1WYJvUe"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn1T5kztz9s4w for ; Sat, 19 May 2018 11:06:37 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D5C69EA8; Sat, 19 May 2018 00:50:59 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 35FDFD84 for ; Sat, 19 May 2018 00:50:27 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f48.google.com (mail-pl0-f48.google.com [209.85.160.48]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 1C012674 for ; Sat, 19 May 2018 00:50:25 +0000 (UTC) Received: by mail-pl0-f48.google.com with SMTP id t12-v6so5491980plo.7 for ; Fri, 18 May 2018 17:50:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QWa2PAJpuhBHEFJjD6380dISR5EOV4zfUiXlVzSUpzw=; b=i1WYJvUex0t1XizxlUegsEW7SDfzlOEcVu9c9rQndoCLdhCoho09JARXTYswNE2/YQ Wh2/CMQkINBB2IDL/oNdcDvPM66bKvnrZsm7u0K2sn4OTVz0i+a0/P9dN9jt/Ku9Y9cn g2c/Zr/MZUtKRLC/UKUMC18Hwk12PKIGSLHntoMipvoWt5ny61OSEM41C93A5aiZDsaK 9jLonmdgq3eYkmykgW/w391i2WC3OANEMTQD0HYuhmuYHmNDzv27Lt9IqSumVrytu8kb u/D3PtDHHRfpSF0L1ZyHrQzXI42D2gjX+o/dCAS4MevWwHEMqiDmdstCllgkJSb2+cNQ cmvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QWa2PAJpuhBHEFJjD6380dISR5EOV4zfUiXlVzSUpzw=; b=ZnUTEuaY1TZOUfENUHxRHFZXdnusm7CDlRb/LOvuMJogDDmx3KreI03CToAsN9Ccs8 hqN6NjK9MJbqD2iZVFI+MbYT6ZpKt2KKUD7/sHIisoxB5VilJTcox8uEC59qBeT1fy3y 8CXlvPCulVtfdxabaUXV5QeGr4YGaCP160kpt7g8aS+qIewbUxclrwI1pIviZLXz8Get ajFXZZrWQp/XXGE+BMkKLO4bW0CL9pvs7h7ZV4Z1FTQjlsCZovZu9ZKMBl6nJCK5QVEd 2aKkJg2p6Hx5ocel7sMwVaejpGtEVlRioKuJl0t3Z0xUDT/CDgYu4bgfwVQ3NcZne6Kb oP6w== X-Gm-Message-State: ALKqPwc+5MHEDiGainDCTf2a9iDk1zwRib2y/2B7NIjI1HPK3vOW9boh 0+dU/zkv8So3PJMgUWnxZav6iQ== X-Google-Smtp-Source: AB8JxZpKfhqIgbP6HmBI3sumgJGGCm6i6NOX2YZ368aqUCKTnSFI61I6at0AndcXNToRGHQT7FD5pw== X-Received: by 2002:a17:902:5a46:: with SMTP id f6-v6mr11557038plm.85.1526691025228; Fri, 18 May 2018 17:50:25 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:24 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:40 -0700 Message-Id: <1526690988-29912-33-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 32/40] erspan: Add flow-based erspan options X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The patch add supports for flow-based erspan options. The erspan_ver, erspan_idx, erspan_dir, and erspan_hwid can be set as "flow" so that its value is set by the openflow rule, instead of statically configured at port creation time. Signed-off-by: William Tu --- V2 - A portion of this patch from lib/match.c was folded in a prior commit "userspace: add erspan tunnel support" as per Ben's review comments. --- lib/netdev-native-tnl.c | 38 +++++++++++++-- lib/netdev-vport.c | 120 +++++++++++++++++++++++++++++++++-------------- lib/netdev.h | 5 ++ ofproto/tunnel.c | 11 +++-- tests/tunnel-push-pop.at | 10 +++- tests/tunnel.at | 68 +++++++++++++++++++++++---- 6 files changed, 198 insertions(+), 54 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index c70811e..c97491e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -628,6 +628,7 @@ netdev_erspan_build_header(const struct netdev *netdev, struct erspan_base_hdr *ersh; unsigned int hlen; uint32_t tun_id; + int erspan_ver; uint16_t sid; /* XXX: RCUfy tnl_cfg. */ @@ -645,7 +646,15 @@ netdev_erspan_build_header(const struct netdev *netdev, sid = (uint16_t) tun_id; } - if (tnl_cfg->erspan_ver == 1) { + if (tnl_cfg->erspan_ver_flow) { + erspan_ver = params->flow->tunnel.erspan_ver; + } else { + erspan_ver = tnl_cfg->erspan_ver; + } + + if (erspan_ver == 1) { + ovs_be32 *index; + greh->protocol = htons(ETH_TYPE_ERSPAN1); greh->flags = htons(GRE_SEQ); ersh->ver = 1; @@ -654,19 +663,38 @@ netdev_erspan_build_header(const struct netdev *netdev, put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1), htonl(tnl_cfg->erspan_idx)); + index = (ovs_be32 *)(ersh + 1); + + if (tnl_cfg->erspan_idx_flow) { + *index = htonl(params->flow->tunnel.erspan_idx); + } else { + *index = htonl(tnl_cfg->erspan_idx); + } + hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE; - } else if (tnl_cfg->erspan_ver == 2) { + } else if (erspan_ver == 2) { + struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + greh->protocol = htons(ETH_TYPE_ERSPAN2); greh->flags = htons(GRE_SEQ); ersh->ver = 2; set_sid(ersh, sid); - struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); md2->sgt = 0; /* security group tag */ md2->gra = 0; put_16aligned_be32(&md2->timestamp, 0); - set_hwid(md2, tnl_cfg->erspan_hwid); - md2->dir = tnl_cfg->erspan_dir; + + if (tnl_cfg->erspan_hwid_flow) { + set_hwid(md2, params->flow->tunnel.erspan_hwid); + } else { + set_hwid(md2, tnl_cfg->erspan_hwid); + } + + if (tnl_cfg->erspan_dir_flow) { + md2->dir = params->flow->tunnel.erspan_dir; + } else { + md2->dir = tnl_cfg->erspan_dir; + } hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE; } else { diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 805f130..1dae7e0 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -545,36 +545,63 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) tnl_cfg.egress_pkt_mark = strtoul(node->value, NULL, 10); tnl_cfg.set_egress_pkt_mark = true; } else if (!strcmp(node->key, "erspan_idx")) { - tnl_cfg.erspan_idx = strtol(node->value, NULL, 16); - if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) { - ds_put_format(&errors, "%s: invalid erspan index: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_idx_flow = true; + } else { + tnl_cfg.erspan_idx_flow = false; + tnl_cfg.erspan_idx = strtol(node->value, NULL, 16); + + if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) { + ds_put_format(&errors, "%s: invalid erspan index: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_ver")) { - tnl_cfg.erspan_ver = atoi(node->value); - if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) { - ds_put_format(&errors, "%s: invalid erspan version: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_ver_flow = true; + tnl_cfg.erspan_idx_flow = true; + tnl_cfg.erspan_dir_flow = true; + tnl_cfg.erspan_hwid_flow = true; + } else { + tnl_cfg.erspan_ver_flow = false; + tnl_cfg.erspan_ver = atoi(node->value); + + if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) { + ds_put_format(&errors, "%s: invalid erspan version: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_dir")) { - tnl_cfg.erspan_dir = atoi(node->value); - if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) { - ds_put_format(&errors, "%s: invalid erspan direction: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_dir_flow = true; + } else { + tnl_cfg.erspan_dir_flow = false; + tnl_cfg.erspan_dir = atoi(node->value); + + if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) { + ds_put_format(&errors, "%s: invalid erspan direction: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_hwid")) { - tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16); - if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) { - ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_hwid_flow = true; + } else { + tnl_cfg.erspan_hwid_flow = false; + tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16); + + if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) { + ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else { ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name, @@ -767,17 +794,40 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) "%"PRIu32, tnl_cfg.egress_pkt_mark); } - if (tnl_cfg.erspan_idx) { - smap_add_format(args, "erspan_idx", "0x%x", tnl_cfg.erspan_idx); - } - if (tnl_cfg.erspan_ver) { - smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver); - } - if (tnl_cfg.erspan_dir) { - smap_add_format(args, "erspan_dir", "%d", tnl_cfg.erspan_dir); - } - if (tnl_cfg.erspan_hwid) { - smap_add_format(args, "erspan_hwid", "0x%x", tnl_cfg.erspan_hwid); + if (!strcmp("erspan", type) || !strcmp("ip6erspan", type)) { + if (tnl_cfg.erspan_ver_flow) { + /* since version number is not determined, + * assume print all other as flow + */ + smap_add(args, "erspan_ver", "flow"); + smap_add(args, "erspan_idx", "flow"); + smap_add(args, "erspan_dir", "flow"); + smap_add(args, "erspan_hwid", "flow"); + } else { + smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver); + + if (tnl_cfg.erspan_ver == 1) { + if (tnl_cfg.erspan_idx_flow) { + smap_add(args, "erspan_idx", "flow"); + } else { + smap_add_format(args, "erspan_idx", "0x%x", + tnl_cfg.erspan_idx); + } + } else if (tnl_cfg.erspan_ver == 2) { + if (tnl_cfg.erspan_dir_flow) { + smap_add(args, "erspan_dir", "flow"); + } else { + smap_add_format(args, "erspan_dir", "%d", + tnl_cfg.erspan_dir); + } + if (tnl_cfg.erspan_hwid_flow) { + smap_add(args, "erspan_hwid", "flow"); + } else { + smap_add_format(args, "erspan_hwid", "0x%x", + tnl_cfg.erspan_hwid); + } + } + } } return 0; diff --git a/lib/netdev.h b/lib/netdev.h index 0c74dfe..71ffdab 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -134,6 +134,11 @@ struct netdev_tunnel_config { uint8_t erspan_ver; uint8_t erspan_dir; uint8_t erspan_hwid; + + bool erspan_ver_flow; + bool erspan_idx_flow; + bool erspan_dir_flow; + bool erspan_hwid_flow; }; void netdev_run(void); diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 2fd6ffb..03f0ab7 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -474,16 +474,19 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow, wc->masks.pkt_mark = UINT32_MAX; } - if (cfg->erspan_ver) { + if (!cfg->erspan_ver_flow) { flow->tunnel.erspan_ver = cfg->erspan_ver; } - if (cfg->erspan_idx) { + + if (!cfg->erspan_idx_flow) { flow->tunnel.erspan_idx = cfg->erspan_idx; } - if (cfg->erspan_dir) { + + if (!cfg->erspan_dir_flow) { flow->tunnel.erspan_dir = cfg->erspan_dir; } - if (cfg->erspan_hwid) { + + if (!cfg->erspan_hwid_flow) { flow->tunnel.erspan_hwid = cfg->erspan_hwid; } diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index a3b284a..b2269df 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -9,6 +9,12 @@ AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=erspan \ -- add-port int-br t2 -- set Interface t2 type=erspan \ options:remote_ip=1.1.2.92 options:key=567 options:erspan_ver=2 \ options:erspan_dir=1 options:erspan_hwid=0x7 ofport_request=3\ + -- add-port int-br t3 -- set Interface t3 type=erspan \ + options:remote_ip=flow options:erspan_ver=2 options:key=456 \ + options:erspan_hwid=flow options:erspan_dir=flow ofport_request=4\ + -- add-port int-br t4 -- set Interface t4 type=erspan \ + options:remote_ip=flow options:erspan_ver=2 options:key=56 \ + options:erspan_ver=flow ofport_request=5\ ], [0]) AT_CHECK([ovs-appctl dpif/show], [0], [dnl @@ -20,6 +26,8 @@ dummy@ovs-dummy: hit:0 missed:0 int-br 65534/2: (dummy-internal) t1 2/3: (erspan: erspan_idx=0x3, erspan_ver=1, key=123, remote_ip=1.1.2.92) t2 3/3: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=1.1.2.92) + t3 4/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=456, remote_ip=flow) + t4 5/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=56, remote_ip=flow) ]) dnl First setup dummy interface IP address, then add the route @@ -69,7 +77,7 @@ AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl Listening ports: -erspan_sys (3) ref_cnt=2 +erspan_sys (3) ref_cnt=4 ]) dnl Check ERSPAN v1 tunnel push diff --git a/tests/tunnel.at b/tests/tunnel.at index 315453d..2bc004c 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -408,11 +408,42 @@ AT_CLEANUP AT_SETUP([tunnel - ERSPAN]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=erspan \ - options:remote_ip=1.1.1.1 ofport_request=1]) + options:remote_ip=1.1.1.1 options:key=1 options:erspan_ver=1 \ + options:erspan_idx=0x0 ofport_request=1 \ + -- add-port br0 p2 -- set Interface p2 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=2 \ + options:key=flow options:erspan_ver=1 options:erspan_idx=flow \ + -- add-port br0 p3 -- set Interface p3 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=3 \ + options:key=10 options:erspan_ver=2 options:erspan_dir=flow \ + options:erspan_hwid=flow \ + -- add-port br0 p4 -- set Interface p4 type=erspan \ + options:remote_ip=1.2.3.4 ofport_request=4 \ + options:key=flow options:erspan_ver=flow\ + ]) AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl br0 65534/100: (dummy-internal) - p1 1/1: (erspan: remote_ip=1.1.1.1) + p1 1/1: (erspan: erspan_idx=0x0, erspan_ver=1, key=1, remote_ip=1.1.1.1) + p2 2/1: (erspan: erspan_idx=flow, erspan_ver=1, key=flow, remote_ip=1.1.1.1) + p3 3/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=10, remote_ip=1.1.1.1) + p4 4/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=flow, remote_ip=1.2.3.4) +]) + +dnl Check ERSPAN v1 flow-based tunnel push +AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x1->tun_erspan_idx,2"]) + +dnl Check ERSPAN v2 flow-based tunnel push +AT_CHECK([ovs-ofctl add-flow br0 "in_port=2, actions=set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,3"]) + +AT_CHECK([ovs-ofctl add-flow br0 "in_port=3, actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,4"]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=set_tunnel:0xb,set_field:0x1->tun_erspan_idx,output:2 + in_port=2 actions=set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:3 + in_port=3 actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:4 ]) OVS_VSWITCHD_STOP @@ -523,28 +554,28 @@ AT_CHECK([tail -1 stdout], [0], dnl receive packet from ERSPAN port with v1 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no Datapath actions: 3 ]) dnl receive packet from ERSPAN port with wrong v1 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0xabcd),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no Datapath actions: drop ]) dnl receive packet from ERSPAN port with v2 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=1,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: 2 ]) dnl receive packet from ERSPAN port with wrong v2 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=0,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=0,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: drop ]) @@ -557,17 +588,36 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], NXST_FLOW reply: in_port=1 actions=output:3 in_port=2 actions=output:4 - erspan_ver=1,erspan_idx=0x7,in_port=3 actions=output:1 - erspan_ver=2,in_port=4 actions=output:2 + tun_erspan_ver=1,tun_erspan_idx=0x7,in_port=3 actions=output:1 + tun_erspan_ver=2,in_port=4 actions=output:2 ]) dnl this time it won't drop AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: 2 ]) +dnl flow-based erspan_idx options +AT_CHECK([ovs-vsctl add-port br0 p5 -- set Interface p5 type=erspan \ + options:remote_ip=1.1.1.2 ofport_request=5 \ + options:key=flow options:erspan_ver=1 options:erspan_idx=flow]) + +AT_CHECK([ovs-ofctl del-flows br0]) +AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x7->tun_erspan_idx,5"]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=set_tunnel:0xb,set_field:0x7->tun_erspan_idx,output:5 +]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0xb,dst=1.1.1.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))),1 +]) + OVS_VSWITCHD_STOP AT_CLEANUP From patchwork Sat May 19 00:49:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916716 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tsc2ELEn"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn2G1nZ5z9s52 for ; Sat, 19 May 2018 11:07:18 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E72EAEB1; Sat, 19 May 2018 00:51:00 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8613CDA1 for ; Sat, 19 May 2018 00:50:27 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 029036CE for ; Sat, 19 May 2018 00:50:26 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id n10-v6so5508007plp.0 for ; Fri, 18 May 2018 17:50:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UU1RXYZ2uh97/O9sN4ItEWlkcFT7J3HGaVr9SSa3hu4=; b=tsc2ELEnGS8f3K/JVu2jTpFBYqxsWReCZ3U6IJGE7ZCuiJaMKp4fzWB6qITiPJrHzv liVZYhnbY7+JICIlWbuu6isOU2lFA/UdutkPBLfTsPYNMX+Zml8kDr9+cPlsuYF2FXGj eQT4GhZBmC09TLaqvTULyK1WnsosLdLPdpETbwdl2pvnaGhwiV5ceh49ZHj3OJ1ENgfQ oR9wR40kGaETCxCmXMx0ckvF9ZRHoK+rDhF4T2hsgFLeXJg/F5ksVa5Bo4czQvoZYcbS 2lPnFhxj8DbNChAVMbErGlbzXODRYLlMXpSkI4pl8OpGU1oun45InCzFMsoepT7Zvadj jTIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UU1RXYZ2uh97/O9sN4ItEWlkcFT7J3HGaVr9SSa3hu4=; b=RIjQ7M+/9IsG0nZnLj03PvY4/FBTIgDl5bBKBnwPDsMXv/BVbjVbLrLHcFpOKdcJjE t1Wcf9NEFWGgM05juDzFYDCmUlmnrrZFRU0MX0sjBOfwaMXhTS+2oj6bQrJvw/5v8mdB cp5QJVi4dbyPAYqPcpLzI+Cl/JphaGevWmGDPRcNfqw4d4vEeuHKR7YMJ6ym1pkvV1Pu xwXDZBEr7og3UsK7AxhtV53t7T3mmaJ92D6PBpnArpJvZEEUnYdwtRPwpuCNg5K4277G apeA6+bjx86eLR/bXxXq+YglIhTovgdvY86I/b8YHp8xhQh/Lje5532dhlIvepzpk+fW gd/Q== X-Gm-Message-State: ALKqPwfVFDkSuzTHqu+JmmUGR7DC7DRsRp1UCs5G9kZidw5cROifAl4g Onxz4tO24kFgxNLUkg01PLFbxg== X-Google-Smtp-Source: AB8JxZrZLCrOYWym5GjTbr5lyKzLlJ4ZUl1s4Q3IDFPYIln6ib2NqX5drQSvt1uGFC8LmlbRdcd6kw== X-Received: by 2002:a17:902:41:: with SMTP id 59-v6mr11682621pla.345.1526691026380; Fri, 18 May 2018 17:50:26 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:25 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:41 -0700 Message-Id: <1526690988-29912-34-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 33/40] ip6gre: add erspan v2 to tunnel lookup X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 3b04caab81649a9e8d5375b919b6653d791951df Author: William Tu Date: Fri Mar 9 07:34:40 2018 -0800 ip6gre: add erspan v2 to tunnel lookup The patch adds the erspan v2 proto in ip6gre_tunnel_lookup so the erspan v2 tunnel can be found correctly. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index e0246d1..2f5fe49 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -138,7 +138,8 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, struct ip6_tnl *t, *cand = NULL; struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); int dev_type = (gre_proto == htons(ETH_P_TEB) || - gre_proto == htons(ETH_P_ERSPAN)) ? + gre_proto == htons(ETH_P_ERSPAN) || + gre_proto == htons(ETH_P_ERSPAN2)) ? ARPHRD_ETHER : ARPHRD_IP6GRE; int score, cand_score = 4; From patchwork Sat May 19 00:49:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916718 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Q0Ffk49O"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn2s35b8z9s55 for ; Sat, 19 May 2018 11:07:49 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E6FCCEB6; Sat, 19 May 2018 00:51:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 20D95DA1 for ; Sat, 19 May 2018 00:50:28 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id DA030674 for ; Sat, 19 May 2018 00:50:27 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id w19-v6so5498127plq.4 for ; Fri, 18 May 2018 17:50:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jKxD2n13S0k6MDXeNhgxpzMg3sDHDB0c/qSf7yEzrM4=; b=Q0Ffk49ONDf5/XZeX5b0pOHoRp3rYozbLmxF0dxVRUn/njjF3nyDdT/dC25Yh/rSE3 SFPS/EGotk6KfzbLU+inezuJv8nyhSJMINRAypPo5xrp8T5fBzPeNOHB4B0tiZj3rSeq 14wimBB6IWK+/E+JN2dvYJ013cF1Yrlno3d5NchxB4PG2xzlozqi8EnBUNQt4/AHtKDp dkdi0zEQQYW9gCSBFB5Ny2Hc+JqN3Y6MgV666wJlVXG24fnyg1si17qJL7G4iOpVFRLw Ewla+gk61e/k4l4iLdtOZe877Qn5RZxy9lcSh0xo2Ex2Bg3RG+RTccKmy2M2owNc0Gbr MkjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jKxD2n13S0k6MDXeNhgxpzMg3sDHDB0c/qSf7yEzrM4=; b=nBgN94ryBfYaXtqbCAgZm6EZvfzLg3i9EpImnIygag1my4KzLroltxPjk1HESoqowu vJjw30oUNWA5k8/adaiP+VcFeUCDjtMIIImiPOXKxf19UkBerg4R8ARWcs3wiFVu8O2O UoefpbVTyVItsX2POLJkEAaVAnHrsGLN55T/dfcPU4p+teSEfrDatGTnBidKhDYJf+sw RJUM05t8cLEf20RbOMVUKoO44od7S9cXeg8GTR1db1SkA7601wg1fgTZOTrp1X0Q+KVu kKYq1wSGrcggQe36KGjY02+utb4Elmzsw0PjrHDQ+zozXiiL8Eo4CXdTYvA9Cd5tT2KL ysow== X-Gm-Message-State: ALKqPwe9J2yuTtqJ5q4E0q6015hCfSvJBZDNJXkCP82uxHCWHNcdI26M K8YkSCc3Vtwg6/iDBGFhPqW/eg== X-Google-Smtp-Source: AB8JxZpCbnrjtA58O549QdlwO5Nrm7z9vOoQS5TnswnW/2iILHg8monWSDuyMSqqLDZWJG6Nu24n1g== X-Received: by 2002:a17:902:145:: with SMTP id 63-v6mr11677863plb.332.1526691027333; Fri, 18 May 2018 17:50:27 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:26 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:42 -0700 Message-Id: <1526690988-29912-35-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 34/40] ip6erspan: improve error handling for erspan version number. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d6aa71197ffcb68850bfebfc3fc160abe41df53b Author: William Tu Date: Fri Mar 9 07:34:41 2018 -0800 ip6erspan: improve error handling for erspan version number. When users fill in incorrect erspan version number through the struct erspan_metadata uapi, current code skips pushing the erspan header but continue pushing the gre header, which is incorrect. The patch fixes it by returning error. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 2f5fe49..25f24e3 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1136,6 +1136,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, truncate, false); tpi.hdr_len = ERSPAN_V2_MDSIZE; tpi.proto = htons(ETH_P_ERSPAN2); + } else { + goto tx_err; } tpi.flags = TUNNEL_SEQ; From patchwork Sat May 19 00:49:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916719 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="qZhNN5Dq"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn3N5m50z9s4w for ; Sat, 19 May 2018 11:08:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B0C1DEB8; Sat, 19 May 2018 00:51:03 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 19071DB3 for ; Sat, 19 May 2018 00:50:29 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id D1478674 for ; Sat, 19 May 2018 00:50:28 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id e6-v6so5487801plt.11 for ; Fri, 18 May 2018 17:50:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WfNAhJrgzuxp4IvFbYsjO81ly1shL5BQOn0687pWFS8=; b=qZhNN5DqGta9CsSjTCbpNJtaL2JdpyEE3ReQAc9asV1DI+SodZ7x7RFITu2mezNRi0 Dz+ZRtF+R3bmHjv8WK7BU2GL5JWpJUTISoK2keHHLEybGNAk1AO843dn3tJu1BUobXJr 9f272MMm8RcII1TKAJdEERTQ8CB1lOoBGVPlarj7phgxndzguG6gsfO+YHkpUDtvgWE+ uMGzVExBJOKS4ibWCq2zplG2w8RYlh7BWyG4J2QLYTO/Zw03Vh/YoZm2a4AxxBRt7pEE EScsn1FwiOTYfLyy4lKtEyh/E7WISBH1cqNRMKrlvEiODEj3LYgjRlQF+3xHmTZKK79r /fbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WfNAhJrgzuxp4IvFbYsjO81ly1shL5BQOn0687pWFS8=; b=bD4oiAg7q1CrL/8mXvc49JnQNbVONOyO2XP/jAvkoE4bMlCBIL5eke1PER7P/AD4WN Es6/b+bs1cR1He2qyTju6SK/DsXSGFnauhRbnlZwf+XlHr+RceiQxzL89umzSLw80GpY QV74WUDihpM8/j2djjYsuZ/i+czlO2ZQ4tsG7EKGBqakmVqIIyknyzTj230VDItciUe+ MrVKMEli0OIkYE+4HfnNdJbMu/AwAcoseN9DhG5yua60lLiBtSn0z5+5iuFAk4/7CiOw 8zbpqS7CZQQ1YfaYHFvRstN8o7Nbbb4GarngNzaCewi97aaEMLc/D+TggqSSV5m1GQi/ tXSQ== X-Gm-Message-State: ALKqPweb9uJ4QpxbCnEcX3P4Igy3v38Ez1kL8ZvR22dbbC1uqCCgvDPD 6LMmxnHb7Y1wBdqFBUH/t8Gf3Q== X-Google-Smtp-Source: AB8JxZonT3wILtqd5OGflqHMkIJoVwv9LigrJpfJlkMtPy5zaqTr5vHCntLs/CtZHHNzUVshkD3Jmg== X-Received: by 2002:a17:902:7443:: with SMTP id e3-v6mr11519808plt.169.1526691028190; Fri, 18 May 2018 17:50:28 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:27 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:43 -0700 Message-Id: <1526690988-29912-36-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 35/40] ip6erspan: make sure enough headroom at xmit. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit e41c7c68ea771683cae5a7f81c268f38d7912ecb Author: William Tu Date: Fri Mar 9 07:34:42 2018 -0800 ip6erspan: make sure enough headroom at xmit. The patch adds skb_cow_header() to ensure enough headroom at ip6erspan_tunnel_xmit before pushing the erspan header to the skb. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 25f24e3..c9bd80d 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1094,6 +1094,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + if (skb_cow_head(skb, dev->needed_headroom)) + goto tx_err; + t->parms.o_flags &= ~TUNNEL_KEY; IPCB(skb)->flags = 0; From patchwork Sat May 19 00:49:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916720 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YtC7jzfH"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn3x5gGqz9s4w for ; Sat, 19 May 2018 11:08:45 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 2BD05E31; Sat, 19 May 2018 00:51:05 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E7498DBB for ; Sat, 19 May 2018 00:50:29 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 974AB674 for ; Sat, 19 May 2018 00:50:29 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id q22-v6so4489472pff.11 for ; Fri, 18 May 2018 17:50:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4Jw8prR/6YlZpqCSVnDahtCXtFXLy8O9zvllDmNkO7c=; b=YtC7jzfHh3JBBN57Vgn2mGPrKbNqHCZfw3fPL7e0oRXo4vmdOmq6wDESaMBOagDjF7 J4+Mq/Ys2tqQneDp/0MzW18DGcs3q0iIQ7vbOO/V5E6jz6Gw3eNBSFv7iyfOj9sHcHjQ PUXEPU3mUq+vGBUIpRVdo93kiTUvhG0WYkTqEa/hJ/GKFk7gHgnVm1YobaKvjIUS25La PG7KHe6x3wo3W28XgGHviVuHluVn9Gd0+Pq8J+BaUWgojN7v6M4gRaj8xYdtog5llTGd 4H/0haylnuPx/QhN5J86FdimCXn2Ycyv8ZYyunsHRE55dkNAYzici5yvNuVx1/6T7Zd1 /RAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4Jw8prR/6YlZpqCSVnDahtCXtFXLy8O9zvllDmNkO7c=; b=aCO5ETCI6VSGqXSYLy8zkiOUasiFQWz5KWGzkgnUsI7pjRQBZYQHp5uVilLlXtZcIS CocVLKa9QCrvzQd/mJ2Ru4amYhg13qrLlOLP58ypxVFhk9ojbGuhxTdEbiFDsmlYYZtJ coERoSz7e3C6VQVJocg+zVXPVAcuYpF93yC1zwg26DNhmWx0Q18H7iUUeRXOhXU0OWiQ y4QVBjN3jzBCRID6TqtXchBZzGrXLyAJfpMcd+gfkjjGdZUefP9S1FvqKW4TOQ9j0ClS nA+oWFkOflRgb+J3V+YF+g8tBw3MOlBdKLRq0LLBFc784q6Fxx3/kKDIXHAjDTizoOez 8GBg== X-Gm-Message-State: ALKqPwcd9odZF7kb4YuGqJjV5B2ByDB7eEN9C1vPVuEjE1KXtEmQnE8Y +pc+g/GSBo25MXHEZJarDQb2Fw== X-Google-Smtp-Source: AB8JxZq9AI8o8wi4KQM/azJ04h7tLbWwTstSj41kE/VDPb6UFKbCxRCi7IdSYMLpvfKzxu3tej2Skw== X-Received: by 2002:a62:f24a:: with SMTP id y10-v6mr11474551pfl.75.1526691028999; Fri, 18 May 2018 17:50:28 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:28 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:44 -0700 Message-Id: <1526690988-29912-37-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 36/40] erspan: auto detect truncated ipv6 packets. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d5db21a3e6977dcb42cee3d16cd69901fa66510a Author: William Tu Date: Fri May 11 05:49:47 2018 -0700 erspan: auto detect truncated ipv6 packets. Currently the truncated bit is set only when 1) the mirrored packet is larger than mtu and 2) the ipv4 packet tot_len is larger than the actual skb->len. This patch adds another case for detecting whether ipv6 packet is truncated or not, by checking the ipv6 header payload_len and the skb->len. Reported-by: Xiaoyan Jin Signed-off-by: William Tu Signed-off-by: David S. Miller Signed-off-by: William Tu Cc: Greg Rose Acked-by: William Tu --- datapath/linux/compat/ip6_gre.c | 6 ++++++ datapath/linux/compat/ip_gre.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index c9bd80d..59694dd 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1071,6 +1071,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, __be32 tun_id; __u32 mtu; int nhoff; + int thoff; /* OVS doesn't support native mode ip6 tunnel traffic so @@ -1094,6 +1095,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + thoff = skb_transport_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IPV6) && + (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) + truncate = true; + if (skb_cow_head(skb, dev->needed_headroom)) goto tx_err; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 6b40013..6001d69 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -632,6 +632,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, int version; __be16 df; int nhoff; + int thoff; tun_info = skb_tunnel_info(skb); if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || @@ -664,6 +665,11 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + thoff = skb_transport_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IPV6) && + (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) + truncate = true; + if (version == 1) { erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), ntohl(md->u.index), truncate, true); From patchwork Sat May 19 00:49:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916721 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RT65wqqS"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn4T2R87z9s4w for ; Sat, 19 May 2018 11:09:13 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D6896EC1; Sat, 19 May 2018 00:51:06 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B4986DC4 for ; Sat, 19 May 2018 00:50:30 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7204F674 for ; Sat, 19 May 2018 00:50:30 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id q22-v6so4489479pff.11 for ; Fri, 18 May 2018 17:50:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uo9suIz8j3U5mzDWGfjg7845xUPK37Kcwx6xBEG/u5Q=; b=RT65wqqSvZld+Tvg+Yw5s9kcn4i5o+7ZkewHhPBMXMIdQCDu6F6T+Qrin1aP93xC2K Ledb97U1Y5Ah/wEsPyYWelWldjiHbTJ5dY05GmwzaCd2RAiSHo7q67y6z69ToyADlOvN rZwVuv5Ahw/reL0X75FP1maDuFi8RzQ65ug3QSbgfEDKk7BbAEqW8FH6NmL4Qxg29RKH LRHiRV36d9YNbIyrQkRANO/vFEh7B1KXEaZHJGyUGcMavARLkqRgqhqCWrbSqcXsg9M0 YNwadhFm8aT5O5hs0JsQWaHs7C2vgTEGfuHG4RvPAbgYxpBqZzliUSj0RBmUvyZif99C B9Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uo9suIz8j3U5mzDWGfjg7845xUPK37Kcwx6xBEG/u5Q=; b=LrbStxZe9/VDIzXrdPjzzjq1QjRaj6TnT7XR4LmrmPVq201ZAd18UUxVSqR0YfNJWO GVWzBWakNFkh+3NsAUDMj8lAp7cm+Bwp/oS4SNc1eP9ZXZ9KOG97AaHX6WVZDkOeChEl o+kRENS9w7d87irufEFfwOcTw+i/oeWTFDi8/az/23oUEkOP7goGthBxNAv595Uv3xGu /UbUXQEQVIvZX8ZuJYQT3TDPewaG5w4dpRXPZjXZyE1ItZs0DEReM+5hySkcwyh3CkXg 5QbzvAgQ1YxtpHk7Zltw2zeriXjlMPya0Z1x3p0llwmCrRcY4VkamiyjqOINLa8UlBJe /94A== X-Gm-Message-State: ALKqPwcKo47VO+HR4n3PtGePjywJ1ArUkpIG3XGzg25dsEZpgtvlD8/T PBUXlgShMz6TkxwU6rcoXt5OqQ== X-Google-Smtp-Source: AB8JxZp6VX0LsfxrtP0MLR65JpK/Y6pHL6hBgztj0C5ZFyz+xq3TucQqNb6PQ7Wri9DUvWOQKyGQsQ== X-Received: by 2002:a62:c898:: with SMTP id i24-v6mr11530372pfk.35.1526691029826; Fri, 18 May 2018 17:50:29 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:29 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:45 -0700 Message-Id: <1526690988-29912-38-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 37/40] erspan: set bso when truncated bit is set. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Before the patch, the erspan BSO bit (Bad/Short/Oversized) is not handled. BSO has 4 possible values: 00 --> Good frame with no error, or unknown integrity 11 --> Payload is a Bad Frame with CRC or Alignment Error 01 --> Payload is a Short Frame 10 --> Payload is an Oversized Frame This patch set BSO to 01 when truncate is true. Signed-off-by: William Tu --- datapath/linux/compat/include/net/erspan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h index 813a9c5..8adc89f 100644 --- a/datapath/linux/compat/include/net/erspan.h +++ b/datapath/linux/compat/include/net/erspan.h @@ -268,7 +268,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, } *qp; u16 vlan_tci = 0; u8 gra = 0; /* 100 usec */ - u8 bso = 0; /* Bad/Short/Oversized */ + u8 bso = truncate; /* Bad/Short/Oversized */ u8 sgt = 0; u8 tos; From patchwork Sat May 19 00:49:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916722 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gXIaS1AW"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn522wmwz9s4w for ; Sat, 19 May 2018 11:09:42 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5525EE6E; Sat, 19 May 2018 00:51:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B633DDD1 for ; Sat, 19 May 2018 00:50:31 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 523186CE for ; Sat, 19 May 2018 00:50:31 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id j20-v6so4489767pff.10 for ; Fri, 18 May 2018 17:50:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=s4xT+Maj0ypq5XAqKLn9VglV89jRmLAcLKT4xq80cms=; b=gXIaS1AWDfBLVXw+pC9TlKqlTlsACStu10T220fOYkuXaw/cw0TFZTpjx5y5FvgQvi XxVR5y+55OGPLVsjU5Xkj/3GcuEsy4zZyK+o5sPPQHjWKJqIaMOF3s0h6Vw5dhfxyXXq +9zKZ8/Rct3w+fMyNDhqvrPwcDqXpdp2eq5uwg3Gywf4BpJEWjviznocAVO6pemqMK/E CTUkaV7O1yQzanQITgitJDRI+C53TkBACsqlBNPEB9lcCe38LQMeMKAG5yIGjt6W+P/v k0fcoIMH+5G4STjDVF2kKGQV9gslFj4xXtFvK2fSJWTIdpgs/OLX/PJ2yn6r0Hb7x7X1 wbAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=s4xT+Maj0ypq5XAqKLn9VglV89jRmLAcLKT4xq80cms=; b=KdJZVxlvhLJUzWXR1bUK4Sm+yV01shSQErq8OnnbUYtVXmGrAjuo7p4ZOA02g1otCG zfqCEXQeuaarkumAFKsy+SqHup+aqsMlpSlucO0Kr40D5FsMmwKu1mD9NEVwOl2JTxov Yw5df9KEwIZ5dK20TsDZI5yswX7iwLfMjjbwmhprwnWCyWUohC/6mJ+dE/WreEpkJCdF w3Jih5P2nx9yeCpJO2qApfEk7jEamxtGg2YZDTXQbZYECO1Tcb2m4U9GquaN9vRnYF2I gQkCqQ0wKelaACNI4YJVGu/vk8CgYI7g02ImuzZiU+Q3lZ3UrjJ/rXYNid/Tt0kF9D3h BcYg== X-Gm-Message-State: ALKqPwdQMjE75QTSrJLa+KmUxijcy/m9ymk5MiTaTB8FLIl0lVBvKLpo oII4kpGYcJyPy6cl1O0pgX3fOA== X-Google-Smtp-Source: AB8JxZr2Av7oXEwF5CcvxwVQPMPwHJiQLSGNkGj745r35YbPsNJ513IS6gIciodPgeiWHoxCy8j7iA== X-Received: by 2002:a65:4ac8:: with SMTP id c8-v6mr3993445pgu.246.1526691030703; Fri, 18 May 2018 17:50:30 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:30 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:46 -0700 Message-Id: <1526690988-29912-39-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,UPPERCASE_50_75 autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 38/40] rhel: Enable ERSPAN features for RHEL 7.x X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Enable ERSPAN on RHEL 7.x Signed-off-by: Greg Rose --- acinclude.m4 | 15 ++++++++++++++- datapath/linux/compat/ip6_gre.c | 13 ++++++------- datapath/linux/compat/ip_gre.c | 12 ++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 8962862..2351792 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -531,7 +531,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ [OVS_GREP_IFELSE([$KSRC/include/net/ip_tunnels.h], [iptunnel_pull_offloads], [OVS_GREP_IFELSE([$KSRC/include/net/dst_cache.h], [dst_cache], - [OVS_DEFINE([USE_UPSTREAM_TUNNEL])])])]) + [OVS_GREP_IFELSE([$KSRC/include/net/erspan.h], [erspan_md2], + [OVS_DEFINE([USE_UPSTREAM_TUNNEL])])])])]) OVS_GREP_IFELSE([$KSRC/include/net/dst_cache.h], [dst_cache], [OVS_DEFINE([USE_BUILTIN_DST_CACHE])]) @@ -866,6 +867,18 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c], [parse_gre_header], [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ENCAP_DPORT]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_COLLECT_METADATA]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_IGNORE_DF]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_FWMARK]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ERSPAN_INDEX]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ERSPAN_HWID]) if cmp -s datapath/linux/kcompat.h.new \ datapath/linux/kcompat.h >/dev/null 2>&1; then diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 59694dd..c48c389 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1693,30 +1693,29 @@ static void __net_exit ip6gre_exit_batch_net(struct list_head *net_list) } enum { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) +#ifndef HAVE_IFLA_GRE_ENCAP_DPORT IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, IFLA_GRE_ENCAP_FLAGS, IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_DPORT, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) +#ifndef HAVE_IFLA_GRE_COLLECT_METADATA IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +#ifndef HAVE_IFLA_GRE_IGNORE_DF IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) +#ifndef HAVE_IFLA_GRE_FWMARK IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_INDEX IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_HWID IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, IFLA_GRE_ERSPAN_DIR, IFLA_GRE_ERSPAN_HWID, #endif - }; #define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 6001d69..eecd41a 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -814,25 +814,25 @@ out: } enum { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) +#ifndef HAVE_IFLA_GRE_ENCAP_DPORT IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, IFLA_GRE_ENCAP_FLAGS, IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_DPORT, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) +#ifndef HAVE_IFLA_GRE_COLLECT_METADATA IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +#ifndef HAVE_IFLA_GRE_IGNORE_DF IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) +#ifndef HAVE_IFLA_GRE_FWMARK IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_INDEX IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_HWID IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, IFLA_GRE_ERSPAN_DIR, IFLA_GRE_ERSPAN_HWID, From patchwork Sat May 19 00:49:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916723 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JLcrFLo7"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn5Z3Qxjz9s4w for ; Sat, 19 May 2018 11:10:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A2932ED3; Sat, 19 May 2018 00:51:09 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E56DADD9 for ; Sat, 19 May 2018 00:50:32 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 4A3EB473 for ; Sat, 19 May 2018 00:50:32 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id f189-v6so4500456pfa.7 for ; Fri, 18 May 2018 17:50:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ialQS4bWXLbkKIzfK2jAH9gDaWxY8I6EZlbVhIAhz5E=; b=JLcrFLo737HahJUfzIgC3P51NB/7ZUuMkJnWCyhxe6il2kGDuM0bbM8ou4QT6do9Cq vHTB0eQViBL969SAcGgba1M8N/VkmyjrocJdMYBK/9ookfSvMAF1L876tNkhpNISj5gN GkC1CTMaX2z1JF9nbCKKOv+57Ga0ihYiQtSSt18INwi2v0uuFhANOLvhWTJJOglz0iSk ZOgh4HYdgW9rI6aFyzoTezO0CxFe6JFal7jWiALrAVz5SciM2OhwPwysQ7KSa6kw2VF9 ctuQBe84hc85jXfOo8+09hU7uay+k+HbzTOP+tvX2cqBbojQWx6Jc0y0PTy5HudwBJbd 7hog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ialQS4bWXLbkKIzfK2jAH9gDaWxY8I6EZlbVhIAhz5E=; b=DVcKgBBqzNRIbNq2CpyXm3yS7ZKgBqevPEehkNHu3LDMptVn4S5cFnYOdB8Iap0GH/ SB/y6HI9HN5JA6Y2XNxucUL7reEvdIy/tlA7bnNT954a0B+wNyw2Xo8WK9atQ3owQYID gA9/fdQ/gJXDBk6LAuyfngeTcdAXSXrsaVOXYQlAncUv/ZFbAMYLnpUyxWrqkKZ5twUB Z9o/FOOmTtEt673H2zgl+U2ORbPRgdIotg94em+Qqkj9NpAAcb7HBXpsbSeB0e6ALeF3 +3wqVrmgMv6H7HaPy9Lbj5v/txVcjYVNlq9VuG/Nvz9awV3p1mwWc1qIgILmISlalsJi ZLAQ== X-Gm-Message-State: ALKqPwfVWZs9rB5CytuFItDeF/Fu53UX2pA4v43nGLWQ6aeRvLQTs2db jMIY3tmdLLohnuvjrTUooL7szA== X-Google-Smtp-Source: AB8JxZpvozR+AcHaQMlHK0dxlr16z95byfIXQ0KIsneRITKBGnBm1WV0fD9bJ1rwMDvuHnilIOldGQ== X-Received: by 2002:a62:859a:: with SMTP id m26-v6mr11299307pfk.247.1526691031550; Fri, 18 May 2018 17:50:31 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:31 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:47 -0700 Message-Id: <1526690988-29912-40-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 39/40] gre: Resolve gre receive issues X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org On newer Linux kernels or on older kernels such as Red Hat that backport from newer upstream Linux kernel releases the built-in gre kernel module will interfere with OVS gre code in the receive path. Fix this up by placing the gre kernel code within the openvswitch driver so it will not have to depend on the built-in gre kernel module. Signed-off-by: Greg Rose --- datapath/linux/compat/gre.c | 113 +++++++++++++++++++++++++++++--- datapath/linux/compat/include/net/gre.h | 18 +++++ datapath/linux/compat/ip_gre.c | 38 +++++++++-- datapath/vport.c | 13 ++-- 4 files changed, 164 insertions(+), 18 deletions(-) diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index 7d16aee..b45f8b4 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -41,6 +41,104 @@ #ifndef USE_UPSTREAM_TUNNEL #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) +static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; + +int rpl_gre_add_protocol(const struct gre_protocol *proto, u8 version) +{ + if (version >= GREPROTO_MAX) + return -EINVAL; + + return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? + 0 : -EBUSY; +} +EXPORT_SYMBOL_GPL(rpl_gre_add_protocol); + +int rpl_gre_del_protocol(const struct gre_protocol *proto, u8 version) +{ + int ret; + + if (version >= GREPROTO_MAX) + return -EINVAL; + + ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? + 0 : -EBUSY; + + if (ret) + return ret; + + synchronize_rcu(); + return 0; +} +EXPORT_SYMBOL_GPL(rpl_gre_del_protocol); + +static int gre_rcv(struct sk_buff *skb) +{ + const struct gre_protocol *proto; + u8 ver; + int ret; + + if (!pskb_may_pull(skb, 12)) + goto drop; + + ver = skb->data[1]&0x7f; + if (ver >= GREPROTO_MAX) + goto drop; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (!proto || !proto->handler) + goto drop_unlock; + ret = proto->handler(skb); + rcu_read_unlock(); + return ret; + +drop_unlock: + rcu_read_unlock(); +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static void gre_err(struct sk_buff *skb, u32 info) +{ + const struct gre_protocol *proto; + const struct iphdr *iph = (const struct iphdr *)skb->data; + u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f; + + if (ver >= GREPROTO_MAX) + return; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (proto && proto->err_handler) + proto->err_handler(skb, info); + rcu_read_unlock(); +} + +static const struct net_protocol net_gre_protocol = { + .handler = gre_rcv, + .err_handler = gre_err, + .netns_ok = 1, +}; + +int rpl_gre_init(void) +{ + pr_info("GRE over IPv4 demultiplexor driver\n"); + + if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { + pr_err("can't add protocol\n"); + return -EAGAIN; + } + return 0; +} +EXPORT_SYMBOL_GPL(rpl_gre_init); + +void rpl_gre_exit(void) +{ + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); +} +EXPORT_SYMBOL_GPL(rpl_gre_exit); + #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen #define gre_calc_hlen rpl_ip_gre_calc_hlen static int rpl_ip_gre_calc_hlen(__be16 o_flags) @@ -142,25 +240,20 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, return iptunnel_pull_header(skb, hdr_len, tpi->proto, false); } -#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ - static struct gre_cisco_protocol __rcu *gre_cisco_proto; static int gre_cisco_rcv(struct sk_buff *skb) { - struct tnl_ptk_info tpi; struct gre_cisco_protocol *proto; + struct tnl_ptk_info tpi; + bool csum_err = false; rcu_read_lock(); proto = rcu_dereference(gre_cisco_proto); if (!proto) goto drop; -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER - { - bool csum_err = false; - if (parse_gre_header(skb, &tpi, &csum_err) < 0) + + if (parse_gre_header(skb, &tpi, &csum_err) < 0) goto drop; - } -#endif proto->handler(skb, &tpi); rcu_read_unlock(); return 0; @@ -194,7 +287,6 @@ EXPORT_SYMBOL_GPL(rpl_gre_cisco_register); int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto) { int ret; - ret = (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, proto, NULL) == proto) ? 0 : -EINVAL; @@ -207,6 +299,7 @@ int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto) } EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister); +#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ #endif /* !HAVE_GRE_CISCO_REGISTER */ #endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 11a95a5..141ed2d 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -32,6 +32,15 @@ static inline void rpl_ip6_tunnel_cleanup(void) { } +static inline int rpl_gre_init(void) +{ + return 0; +} + +static inline void rpl_gre_exit(void) +{ +} + #define gre_fb_xmit dev_queue_xmit #ifdef CONFIG_INET @@ -153,6 +162,8 @@ int rpl_ip6gre_init(void); void rpl_ip6gre_fini(void); int rpl_ip6_tunnel_init(void); void rpl_ip6_tunnel_cleanup(void); +int rpl_gre_init(void); +void rpl_gre_exit(void); #define gretap_fb_dev_create rpl_gretap_fb_dev_create struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, @@ -164,6 +175,11 @@ int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, #define gre_fb_xmit rpl_gre_fb_xmit netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); + +#define gre_add_protocol rpl_gre_add_protocol +int rpl_gre_add_protocol(const struct gre_protocol *proto, u8 version); +#define gre_del_protocol rpl_gre_del_protocol +int rpl_gre_del_protocol(const struct gre_protocol *proto, u8 version); #endif /* USE_UPSTREAM_TUNNEL */ #define ipgre_init rpl_ipgre_init @@ -172,6 +188,8 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define ip6gre_fini rpl_ip6gre_fini #define ip6_tunnel_init rpl_ip6_tunnel_init #define ip6_tunnel_cleanup rpl_ip6_tunnel_cleanup +#define gre_init rpl_gre_init +#define gre_exit rpl_gre_exit #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index eecd41a..9240ab2 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -96,13 +96,14 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) { return PACKET_REJECT; } - +#endif static struct dst_ops md_dst_ops = { .family = AF_UNSPEC, }; @@ -746,11 +747,28 @@ static void __gre_tunnel_init(struct net_device *dev) } } -static struct gre_cisco_protocol ipgre_protocol = { +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER +static struct gre_cisco_protocol ipgre_cisco_protocol = { .handler = gre_rcv, .err_handler = gre_err, .priority = 1, }; +#endif + +static int __gre_rcv(struct sk_buff *skb) +{ + return gre_rcv(skb, NULL); +} + +void __gre_err(struct sk_buff *skb, u32 info) +{ + pr_warn("%s: GRE receive error\n", __func__); +} + +static const struct gre_protocol ipgre_protocol = { + .handler = __gre_rcv, + .err_handler = __gre_err, +}; static int __net_init ipgre_init_net(struct net *net) { @@ -1631,11 +1649,19 @@ int rpl_ipgre_init(void) if (err < 0) goto pnet_ipgre_failed; - err = gre_cisco_register(&ipgre_protocol); +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + err = gre_cisco_register(&ipgre_cisco_protocol); if (err < 0) { pr_info("%s: can't add protocol\n", __func__); goto add_proto_failed; } +#else + err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); + if (err < 0) { + pr_info("%s: can't add protocol\n", __func__); + goto add_proto_failed; + } +#endif pr_info("GRE over IPv4 tunneling driver\n"); @@ -1658,7 +1684,11 @@ void rpl_ipgre_fini(void) { ovs_vport_ops_unregister(&ovs_erspan_vport_ops); ovs_vport_ops_unregister(&ovs_ipgre_vport_ops); - gre_cisco_unregister(&ipgre_protocol); +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + gre_cisco_unregister(&ipgre_cisco_protocol); +#else + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); +#endif unregister_pernet_device(&ipgre_net_ops); unregister_pernet_device(&erspan_net_ops); unregister_pernet_device(&ipgre_tap_net_ops); diff --git a/datapath/vport.c b/datapath/vport.c index 184c859..73dd778 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -66,7 +66,7 @@ int ovs_vport_init(void) goto err_lisp; err = ipgre_init(); if (err) - goto err_gre; + goto err_ipgre; err = ip6gre_init(); if (err) goto err_ip6gre; @@ -76,15 +76,19 @@ int ovs_vport_init(void) err = geneve_init_module(); if (err) goto err_geneve; - err = vxlan_init_module(); if (err) goto err_vxlan; err = ovs_stt_init_module(); if (err) goto err_stt; - return 0; + err = gre_init(); + if (err) + goto err_gre; + return 0; +err_gre: + ovs_stt_cleanup_module(); err_stt: vxlan_cleanup_module(); err_vxlan: @@ -95,7 +99,7 @@ err_ip6_tunnel: ip6gre_fini(); err_ip6gre: ipgre_fini(); -err_gre: +err_ipgre: lisp_cleanup_module(); err_lisp: kfree(dev_table); @@ -109,6 +113,7 @@ err_lisp: */ void ovs_vport_exit(void) { + gre_exit(); ovs_stt_cleanup_module(); vxlan_cleanup_module(); geneve_cleanup_module(); From patchwork Sat May 19 00:49:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 916724 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mJv6LnHN"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nn654CFsz9s4w for ; Sat, 19 May 2018 11:10:37 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C942AEDC; Sat, 19 May 2018 00:51:10 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 512C3DD5 for ; Sat, 19 May 2018 00:50:33 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 0C117473 for ; Sat, 19 May 2018 00:50:33 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id f189-v6so4500462pfa.7 for ; Fri, 18 May 2018 17:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+7npVpruVivgEdzdzlmzo2EG9C5oiUgfnBhOyaLQpTc=; b=mJv6LnHNpUgoBuVMWeV0iI6DY0DCufY0IjSb+tCzlmXEplmmS0u51vGI8/AGJfCccB XaFHDUHfrXNUe65Y37jKZBSCjt0rd+8JsqLxF/spCpQ83F9yHr4bP8rzy7QGz7VDkW8J cuGSdvOhNgykCoXzvhkGbtALN8l2mk20e0jU3ezDSn0MG7GbpA6ilOpX5DQO8Lez/KhU k/4e1/AUjoBl9RpFdEdJryGXWtqDYxbXZNSBGXfOmK6FGk8IeZmEVIx4mYX1/Cw8rB4Z 1OlPu64wFOmrW7bRg+VZYkhm8HyCvWO3InH74L7t5VCmL8Gw+nRk98NSED85GTxegD+v uR1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+7npVpruVivgEdzdzlmzo2EG9C5oiUgfnBhOyaLQpTc=; b=R2WlyXZpQ7LFzV3hiKrHQocCsh832Xi2nUFr1VE9Q7FYwRb4SHb76AnIwhPVnDzyCN KfWD3O6ShqhWONDIM3E9j9x+TArjmkJ/WLXfXQ7mi5PfZ3vNz5P5fSK8gWvcRfuiqViu tJQJyuuzmJ4vZjKZh6nTrYh7dEymdTnHeR+Y7PU6/Aj0KoM4B2JdQynKoQ+oFolJcch5 oNrVhDjX5I/SUc7s3SEwkaqjMoHTr4pubB2Q2LWjGGB0vZeNVWMu26kwmInNdWTmaaXt 9KAJfcGwjUiVKxe+UAtDUnqb/Q/aF9eKdSyTYR0n+6BCGW2Cy5BO2Ju9DrWuWgu4zQ9c mERQ== X-Gm-Message-State: ALKqPwf1qj6FeSBJT9tnbHVOZMWqbWwgW9hYo1+8R9+LS0PM1L8fbre/ lmKNLGV6Z2mTLp+QSoeO85Z/+A== X-Google-Smtp-Source: AB8JxZrbMcTuyusQl6ucnowzp3QaRvWjQ0IswYujoXZqpzimADF8toy/oB7EptWos9pISSuB8G/QHQ== X-Received: by 2002:a62:6756:: with SMTP id b83-v6mr11494355pfc.76.1526691032465; Fri, 18 May 2018 17:50:32 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id 131-v6sm13536685pfa.128.2018.05.18.17.50.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 17:50:31 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Fri, 18 May 2018 17:49:48 -0700 Message-Id: <1526690988-29912-41-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> References: <1526690988-29912-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V3 40/40] erspan: fix invalid erspan version. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu ERSPAN only support version 1 and 2. When packets send to an erspan device which does not have proper version number set, drop the packet. In real case, we observe multicast packets sent to the erspan pernet device, erspan0, which does not have erspan version configured. Reported-by: Greg Rose Signed-off-by: William Tu Acked-by: William Tu --- datapath/linux/compat/ip_gre.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 9240ab2..484a890 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1006,10 +1006,12 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, erspan_build_header(skb, ntohl(tunnel->parms.o_key), tunnel->index, truncate, true); - else + else if (tunnel->erspan_ver == 2) erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), tunnel->dir, tunnel->hwid, truncate, true); + else + goto free_skb; tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));