From patchwork Wed Apr 25 16:21: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: 904608 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="fqho6NLO"; 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 40WQmX5Yz5z9ryk for ; Thu, 26 Apr 2018 02:35:40 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id ACC22BB3; Wed, 25 Apr 2018 16:21: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 2CBB0955 for ; Wed, 25 Apr 2018 16:21:58 +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 BC29E42D for ; Wed, 25 Apr 2018 16:21:56 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id l2so364934pgc.7 for ; Wed, 25 Apr 2018 09:21: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=LD46gTSRutkxOQTkIt3XBrjJw0AeGtIIFZIE7jBeH/w=; b=fqho6NLOHOM9ASByhL+1mK2XNF728XHOQ+xntF3wpSF7d0EI2FNXYXrffvgQZ33rkq frojKwMTZCqFAdPBEPqDHerb+WNlvPET/WEWBujsSjYrwnfp6NcPX9PTBpnoEc/SJXwm J+iWwziNee4GvIYoG4BY+MGrYnMW1MfZgM1RJTtQOmlTYXVY1CyPWDTP0vPO6gDL/nW+ fz7aj6/v2HXn8G9QcNP1795G6o6CpUtAZNx1+GE3kw6AXAano/ko1EC0XBktgc3lcDXg fRCSrgjrYeiY90PeBljeCuA8reiuDMFQ2Lg/FNp4qfSD61HRASQCtPE6c1zwKxk0vt7i 9JBw== 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=LD46gTSRutkxOQTkIt3XBrjJw0AeGtIIFZIE7jBeH/w=; b=UrLBUNNvNitw3Ng5txyTIsaLlR6nLbv9nwZojmtpFH0wsj7kFIL8lp/EgPDNohPrHm DLz+30UDfAd741A0mWET046jmvCVTnQSQF/Euzpvr5w8DVjZxkkhmFBFZs71IR8Cl+47 GuigwnSG93eKE5ovknARhEzzUfSEWsOm6ulEWyK+pb3pZCD9HPHcccQ6SbSDLUdMxS9G I++dE7VYzx6B/UoEYN285FDb02ttE8XNv6jFPwf9ScRqc3+ybieASkITo5sfNXFNxVu3 KmqfD7wUt2ezgyKr4ywnV/aGVm8aYxccMW+OZjoVKdLop1/mhd8HjvoXSemfG6fJpHxx V9eA== X-Gm-Message-State: ALQs6tB2Zy4CKafW6ZXxNCRwbORJJLOvSt7zWPkXhCTt7P5KR9+opssX r5atInMZTgWXer1SJV4A3F27YA== X-Google-Smtp-Source: AB8JxZqeZajt6pU242BKKhYuCD2pkWmwpAo0TokjYGrC4gZTYHT1P7P4MckxkhIvq1RAWLcmj7qtvg== X-Received: by 10.98.74.80 with SMTP id x77mr9088505pfa.142.1524673315621; Wed, 25 Apr 2018 09:21:55 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:21:55 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:39 -0700 Message-Id: <1524673309-30044-2-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 01/11] 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 4e32591..15c0d69 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 */ @@ -492,9 +488,7 @@ static const struct net_device_ops gre_tap_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = ip_tunnel_change_mtu, -#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 @@ -511,13 +505,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 34f8232..f7e48ff 100644 --- a/datapath/linux/compat/lisp.c +++ b/datapath/linux/compat/lisp.c @@ -593,10 +593,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 2189476..405d0d7 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 Wed Apr 25 16:21: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: 904614 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="szOIm36Z"; 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 40WQsV3vX6z9rxx for ; Thu, 26 Apr 2018 02:39:58 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A9854D3C; Wed, 25 Apr 2018 16:22: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 BF6C5D10 for ; Wed, 25 Apr 2018 16:22: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 6B9E2477 for ; Wed, 25 Apr 2018 16:21:59 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id f189so6544084pfa.7 for ; Wed, 25 Apr 2018 09:21: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=bDTNROkPyw1WsKkAdB+VVVge3MZgZhEqNIhfGVFMNyw=; b=szOIm36Zl2Aucd3k4QZgkS8bX6E5qn/PGE2z4ltiZaIOfE8reL+nv8JEcATd6Fibaf nsX/PUQsvyvT7aWVqqU4EjgkHGH65tzD0yhKHnUdWpMJBNSmwxzu6z7R4tCnomuxNF3k vsTo4II8UOkEm6zqqAMVNCWV/gt1VeZh42Hu+HSANHhPFJ3LFt0ogjE/WQ+3yPCGyz1u BiOmFols6+YQwdbi63kv122fQ8mF3N1TD557IjoN5J58vHmDT0lAQnXmZzCbxngr0/Eh AdrwOIp9AosvPY6PPgIJ+9+p6vFVRbQtkjHjTVL61OJbke0oDllN0epTJZQGqwjwsGHD C/aw== 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=bDTNROkPyw1WsKkAdB+VVVge3MZgZhEqNIhfGVFMNyw=; b=ZpgOK+MmTmqjIFBA9b3cSyCtq2mO6BQSO2Ei9IMphDvkxSrzktwJTHrE8uUui4/hNC h80e21zBsuGQTnJ3FjgLVZEE52EJrg7xo9R3KcO9tzlGUb+w6MR/8CXAIg+CuPzimWjC RO7eGFqVhYXuyEmuBVxBUWNtgmPk1eB1KBzFL3K3OZ4KIGIx/dRtqu3Z8zN7Y9piuncq S4iVGfVOq259HF3c9ncbhLZKcUcQjj7Rm0v07BockGts7/TMvs9C9q1qtVjd4ihVjTL/ 0QNGwsNIJUNDhFVtZ+ko1Rx+hCl+rGYsdnibQde/G62Tj28X2hTSQh+IYAWyIwLUoO7E o8jg== X-Gm-Message-State: ALQs6tC36tmoXbAXBfljVJCsq1PMhIoVwDQ8uERmORCxkK+KhSadv72W El8gsVTnF/QFqZBhnbqrwlIRaA== X-Google-Smtp-Source: AIpwx48GT8WGE9g8D452YV//8MSSCXFdhv48q1GI0xg8P8AilCcdAnx+CZLGAKzSjAbEjpGze26zfA== X-Received: by 10.98.107.138 with SMTP id g132mr28208561pfc.163.1524673317037; Wed, 25 Apr 2018 09:21:57 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:21:56 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:40 -0700 Message-Id: <1524673309-30044-3-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 02/11] 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 --- 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 dd264b3..c37316e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -814,7 +814,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 15c0d69..43d1d91 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) +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_KEY | TUNNEL_CSUM | TUNNEL_SEQ); + tpi.key = tunnel_id_to_key32(key->tun_id); + tpi.seq = htonl(tunnel->o_seqno++); + + gre_build_header(skb, &tpi, tunnel_hlen); + + 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,22 +983,176 @@ 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, .ndo_change_mtu = ip_tunnel_change_mtu, - .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); @@ -505,6 +1161,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[]) { @@ -550,6 +1216,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; } @@ -571,13 +1239,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 }, @@ -588,11 +1260,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, @@ -606,6 +1295,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) { @@ -646,6 +1351,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"); @@ -665,6 +1390,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; @@ -673,22 +1550,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); @@ -697,8 +1583,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 Wed Apr 25 16:21: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: 904609 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="k3nIjKRs"; 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 40WQnD3cmhz9s1s for ; Thu, 26 Apr 2018 02:36:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D8BF1CFB; Wed, 25 Apr 2018 16:22: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 94DCD9C1 for ; Wed, 25 Apr 2018 16:21:59 +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 81C6B42D for ; Wed, 25 Apr 2018 16:21:58 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id j11so15648731pff.10 for ; Wed, 25 Apr 2018 09:21: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=B2qFmB7cB4M5dlSitGMq7Cps+1Vxv85005Udivf/d/8=; b=k3nIjKRswuV5xmZPoXmqtUDyUwlBF5Un/LFL23sF/KiHQ185+BMcZI+ZBcBOpaeYqV UKL9fuG+7GRih/AInAy72DJyEiWfiG8CcknvJIGZBkQqmPRJsbdiwT941/T4YtWv+SBp ACCXWwQyab6M75Av2FOFWJZ0cSpZr8bVt588jJkYC2czZbdf4Gn8ruWh1TeIHDCW8Qtv mgi5QRMlXzYfzXNJTlhV5j3kSJqR8KOsTic4/opeDMhgJQ5iMlilu/+dLhqU4KXfsyvp SZ9I2p3vrLlIbM5XzgaISEOM2qqJl4PC6cP6gTwvUujxwxK7Fa+Pt4yHmxjg0TLDwWXd djHQ== 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=B2qFmB7cB4M5dlSitGMq7Cps+1Vxv85005Udivf/d/8=; b=DTeTbhWWXbyuar5qcSaHmdE1u5rJta3SnvJz7M6o83UX6ODIa6QQOANaVwK5ViIp28 dXkW6W5VCHbDX4EZcQELIc+3dHj0N8VRB/bb9BW+yByC8momLuFxo0AZYxQOeTcDi0Gr fx4+IK58wMpdI9Wy2zlLpfpGObZhQT/2alMF/Qn2Ovw5Sxw5ZwPke7LejOzFbwxYet1h kvHfZYwfSrKO3XxUEQtJ3spT5ZSm5lFlTqDu6kgUZ03+5Il0Yl77DfSwNtFCSu+ZXyCz gRqFHqPLnUW469S5wS5VeP0V5EFmeqqNkqp+OVxdDvIZFE5lixp5LYGklx6bf2OpG8AQ g5ZQ== X-Gm-Message-State: ALQs6tBXf7wm8QN/Q4kxyzJmg3u/m3wFt/ytpSiqXbBXvXrepIRVIw6o ehvBaLOVhPtnkZLWJXPsHCWQ4w== X-Google-Smtp-Source: AB8JxZqKXDpQlraK1OgUojA4gHLfckQe9DmE6c0qACMqemztYA88AeYLcV7LXt8GlPwOMKaDzaTT9Q== X-Received: by 10.98.9.145 with SMTP id 17mr7607937pfj.34.1524673317901; Wed, 25 Apr 2018 09:21:57 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:21:57 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:41 -0700 Message-Id: <1524673309-30044-4-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 03/11] 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 --- 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 43d1d91..483c904 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1548,7 +1548,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) @@ -1576,7 +1576,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 Wed Apr 25 16:21: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: 904610 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="kGtNkQ9h"; 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 40WQnm4xn9z9s0t for ; Thu, 26 Apr 2018 02:36:44 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B27A0CFA; Wed, 25 Apr 2018 16:22:02 +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 DCE819C1 for ; Wed, 25 Apr 2018 16:21:59 +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 8DC175C3 for ; Wed, 25 Apr 2018 16:21:59 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id h69so15653936pfe.13 for ; Wed, 25 Apr 2018 09:21: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=j/HTTTL/EENJTyARkzbvUKLL3yWLNglrJG4aj7dJMH4=; b=kGtNkQ9hXrsIaobc4b3XtQe+JuNNMkvC6OCIYgtMsOXybgKGXtSZLtCxuOhm2PXj7z BDeUVFasspgXeAoehYZfKY6Z5thg8kecJRzR3PSJcSmK6k/WSXQvL74vxJIzBt0xs/Yw gDOLWZAz56w9zNi9A9fgPLPgyYDfs3c0BqUO4IqIKW95FxCt5xTLdPxOCeq+eyw8x6Ch hkM38hl8pCzgw2dG7TVKNLvx/6fXuifU4p/UXE9te6+c/C7sbCyAaaYFk/B3h4W324/x JWvh6vUgUFxIFWK3hjF1PxQwnBFZNGVNRoal5b1/FqlS5jSChmIYQ7fiFNE967WD6m9F b/Fw== 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=j/HTTTL/EENJTyARkzbvUKLL3yWLNglrJG4aj7dJMH4=; b=gobZ9cnqUpLSwsV7uw1/aDmhqrxQXu/2J8ebDk5UDtPO+kKopvs0u3jbBWOnERrOGc tM85XK5BiRrTUFfQJd2CEmHrUSgbDVq1hdAuVDytGep/4AokGbNLvynZK9glfi1d/oyE ugoymLHsugjTNNpkf0jG0LwrkH9oE2zdhdfz7AQkbkEsWwlN7GzSaYOaBBi2wZZ00VeE 17pCKVnLqQLLCnDT4aqfYW/hObkacIt2bi6RhgbBwM5AmSU1jDBpGVzaldvJloY8omNy 0HI2/QujqQPuxJF0aUugTVJ8jYMLU9ER2gvtbgeRXOS3gbrAqJTi85NB5wiiCGjNZZoK +BmQ== X-Gm-Message-State: ALQs6tA58ZH/2zshfBIryVqs0dI/aJpc1FNv1jbh+qX1unrkGnC3+epa Nl1HeRaM/3PLhDqXG0H6J/u6aQ== X-Google-Smtp-Source: AIpwx48mansjqUZDKmk7evOXtbD9Sgac8Q6MnHIJ875Ze2NL76aewyDU9mpSAxWPlQVWcLma2rFT0Q== X-Received: by 10.98.113.196 with SMTP id m187mr25549562pfc.216.1524673318930; Wed, 25 Apr 2018 09:21:58 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:21:58 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:42 -0700 Message-Id: <1524673309-30044-5-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 04/11] 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 --- 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 483c904..961d4cc 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 Wed Apr 25 16:21: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: 904611 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="okHhirgc"; 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 40WQpH3vylz9s0t for ; Thu, 26 Apr 2018 02:37:11 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 9088DD02; Wed, 25 Apr 2018 16:22: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 021159C1 for ; Wed, 25 Apr 2018 16:22:01 +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 81FC542D for ; Wed, 25 Apr 2018 16:22:00 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id i6so13689891pgv.3 for ; Wed, 25 Apr 2018 09:22: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=R82p04WZHyKQmAWZx7R/qe03qDiNR77zeelAjUfsypM=; b=okHhirgc2RTyjAQqLK7ebmZjUzRi6xmXqaOrnIB6j29WgAOcqqi/K/LZc7xdvP+uvf MFEumgza3ymzwqeFChKzRbT3p+SNCdpY/VCdzaeHaPS1UZfLup/2aFiWU7frqGT+dHqu g6I18sqjUOZTgIipotO5HogYXwVS+BV0edU6VJTwD0UoFioPJSyvCk0klgXAcjpMdFWY QMQ55dz5PPId/rbHvwmxuxOUAeJxPjxmulfoSBL1RHhLxiDA561lJvsiMRk0sIhSLygJ JYbIofIkIABlVSwLW6W75dDlM1abbyjjIrWwG4LTr18l03T81X5aaic4ypUj5O56MLhQ NnPw== 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=R82p04WZHyKQmAWZx7R/qe03qDiNR77zeelAjUfsypM=; b=Gwir2EUz4BPgHT9NzCyvb2RpcDgsGfXhg43VesnH4q0BC23z4dfXyOebWNRTi39zlw vtd0cKKpzaKpNEHNyawedd/nRKBNiK8ATWuJ0qujUMhOv+VG/NJ9hrAnZtNnclPZ6JgL mO3Uh8uPCtf+p+qUfhU4LRGKtDSYDLYnxHDCMok9n6AEFhPU4PKR1UZCwZF6Xuej/iPw MyIi7wcmsoSHKemr5Kzr4bJKCOPw8lDll+6TiCPuFMo7v6a7we7CLNvtfcmgTmzOD+le hHF4vp9WXTb+1nBxCiB4KEccHyMhaANjiKx0QHUrjIewk2FNF0cM6GpIeKDWPcC200Dh T/Yw== X-Gm-Message-State: ALQs6tBUeNMKI85zVFjp4YX37uPBIorKQDpAIEMufmR3WubxuflTbMFW dxbSsz93JKo0HStIrfx3pk0yNA== X-Google-Smtp-Source: AB8JxZppIcG7xFn2R4HWwSIo2uAlQ/+5HIteA7hxMilEyCSkyddtr/SpMw5G2pkPOt0wDl4qUBfVaQ== X-Received: by 10.167.131.24 with SMTP id t24mr6289134pfm.245.1524673319800; Wed, 25 Apr 2018 09:21:59 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:21:59 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:43 -0700 Message-Id: <1524673309-30044-6-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 05/11] 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 --- 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 961d4cc..1295fc5 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 Wed Apr 25 16:21: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: 904612 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="eOQWhkQc"; 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 40WQrK3m3qz9rxx for ; Thu, 26 Apr 2018 02:38:57 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E8D57CFC; Wed, 25 Apr 2018 16:22: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 CF3CABC2 for ; Wed, 25 Apr 2018 16:22:01 +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 6B63E42D for ; Wed, 25 Apr 2018 16:22:01 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id f15so15662660pfn.0 for ; Wed, 25 Apr 2018 09:22: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=htdMQfAMCRCdV6e3KpQojUguSmx+knu7u1XIzuseakU=; b=eOQWhkQcHSl+9GR3EDf3FxPAX+aheO8AGfE8jWLC7Pp/m9stl3cv86ltFu/7XEifpY vVHl3iJvBiYenP5t0YhPfVpKpYxAt5j/vHG/8chzUml9j07wbVee5pO/yf0OyKuBullE fw5wolcniD4ORi2GRu69Z7v65w2+21oKdxHte6L4bUZyM7ZswiUxx948kJUdGFc6B83L lXf3BCfsxvq/sGVNRe20ntfvoNGj193afVPZ6dMNrYOjsKZj4iKPSK2QW0krC1AjqOge 7oith5BpUvDJMnK0S7e0mA/rgyrR4Pl4gtQwEoptpjxR5jZrKbKhVlNnRUMmSo6GMUPE L0Fw== 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=htdMQfAMCRCdV6e3KpQojUguSmx+knu7u1XIzuseakU=; b=duzjySqrQruu8GXKNDf9Znif4DcTKxLaN83njdxniX30o3nG66W3Z979voBqZvio6b KrOUAkF70mZn3q71UzacZc4s/SIFlgEfvLrfHQNSgL41vwm9XWTOD0TQE5LhIJ4JKG3P ERXwLKTGBY5Nb/M4HaDZzghyku8nnE7qFDqojDaGQCkUgU9yqyp2Up9y1gTs+eh3BXFD oO5EUJ27XkSegnW0L1oVAzm2d0YBlTqetxc/K72n3L+WVYzSCwgAvEiAXZC/VXkzJhEq 2C/fqcYr0ofzFKS7m0pNAdBnd4TRpAWY9utySBlwNDth5uH+7V3zyFl97zH5snabfWZy ll4w== X-Gm-Message-State: ALQs6tD8zPD3AfKLqSmtPmKA4ACoZWuv2gbDiyJ+Z18Cfs3mjUPVzfzj Km187QGE9xcV/txWsBeykOVjBg== X-Google-Smtp-Source: AIpwx4+gKkRJteexkmcGgs5malQ+f9BKeEZj51pgSei9+76HeaUyuVKSSP/ooa7ohvUjHNZWr6ImnA== X-Received: by 10.98.76.68 with SMTP id z65mr28806889pfa.181.1524673320672; Wed, 25 Apr 2018 09:22:00 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.21.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:00 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:44 -0700 Message-Id: <1524673309-30044-7-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 06/11] 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 --- 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 1295fc5..2377d82 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 Wed Apr 25 16:21: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: 904613 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="c9dGhWMC"; 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 40WQs10KxTz9rxx for ; Thu, 26 Apr 2018 02:39:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D6E49D38; Wed, 25 Apr 2018 16:22: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 EFD79D02 for ; Wed, 25 Apr 2018 16:22: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 B0F9E42D for ; Wed, 25 Apr 2018 16:22:02 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id f15so15662696pfn.0 for ; Wed, 25 Apr 2018 09:22: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=60l29I6DNs8SnJDaOAPkEmK3w8D0zz87LyZk9oEa7e8=; b=c9dGhWMCNEDO/f+5QxBNcaUEaqJsPNk+fTBuAHnnb3o8jUv/gev0IYph2jAhAMB27x SX5WtPU1phUSj6Rv79HR7u4KX+mF/eSdaxvzqhTdATrZltesmGOwkRJBnd6nflglvUNM +76U/kv4hY1KpZFGNgSzPw7e9tgW6o0vHCf8kGpl16PzhQUVY8JNqxGS+YrJmcQmplRn UohfAAuq5IEaJNBT1sSoovOxpA027fA/WPxEJA4BFZRhSAdo/bZhUtIxX8Sm7Hk/Ead5 o09EAhPbm2pOl70BGexvpJzZpgqf9IGBujFhh1hp/avPWMvAiccs7SCR53JFEOX2wD8E CXuA== 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=60l29I6DNs8SnJDaOAPkEmK3w8D0zz87LyZk9oEa7e8=; b=RfZJtVScd8SmwaO41eklYthF5zHKDBaYY6kOnAeueuZkoT1WrcIRviVRBI89P6FfMG Sh/VPKbJLDvYe0o+lUUxGfAFxsljpD4r2QOehq3t7+rz+xTL0nc9rk+qEg3CNOrDget5 4aXK4WOmKNqutWZK7wQ8Bz30QWI/27sBrB5G2bgfFYs7584gDk/nNlfAM1dEyywO8WD0 ulR0NxvNQcMt5koK66EPVPnh3aLgBNoz832vLTUe0ijuvWG3WrnBCfBycASg+nnicCch yCEIMnhDYSCsvK26GsIx1Rx+22UYElPhzuCzDUF9JXuFccgt8HNZE1jfN4S/D+h8T+N0 65GA== X-Gm-Message-State: ALQs6tDavUzAg6pbC/7iZD8xgwQ67vAIOuaPftgQ5HXT4QKBNXguuVmw eT5eYgJZOjgZbhM6BXtwvAOtbg== X-Google-Smtp-Source: AB8JxZoUYwIN2Jgkkx18WQb6o104q+0k9MxLuRHyM2OufT6mXFOyuyjXuloWuE0d7qowXT9OjglM6Q== X-Received: by 10.167.128.82 with SMTP id y18mr4217410pfm.194.1524673322087; Wed, 25 Apr 2018 09:22:02 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.22.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:01 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:45 -0700 Message-Id: <1524673309-30044-8-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 07/11] 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 --- 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 2377d82..caa6e6c 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 Wed Apr 25 16:21: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: 904615 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="tMuZgrND"; 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 40WQt567jrz9rxx for ; Thu, 26 Apr 2018 02:40:29 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 84101D34; Wed, 25 Apr 2018 16:22: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 E266AD13 for ; Wed, 25 Apr 2018 16:22: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 A410142D for ; Wed, 25 Apr 2018 16:22:03 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id o16so15647249pfk.9 for ; Wed, 25 Apr 2018 09:22: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=W74VEz7oOiEpY0icdc4YAhGxcz5T1MZcv06JWaW+L5A=; b=tMuZgrNDoJ4KlcLMfFdhsYBac3imhHZQ0RkAWvF6V/nu2Alk6TPxZX6er3yryR0nqE sXmO9KScd6QBDjCyceEKvgOFb+LFL7tk/iWGuuRh6lbuLi63p5z8lOyzrzJQEO9wrja8 sdqREGks0xCBR0pRR3V6EQ+rjmYmlSPBNDYoyghJar3iDoWT+W71aN7wup5u8B0lrpLG 7z2HZgTIMBxgiLOsqVnG2Qce6OgENkbNMhW/VnN5taC0V7su8d1YrN0LCS4I5xvmThDz 9+2vxr52W2ClITEsg119pLTMobxhdJU2KGyBue0/1dlxj0Y3Rw+gX4XihHyG5Y29RxNP XW+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=W74VEz7oOiEpY0icdc4YAhGxcz5T1MZcv06JWaW+L5A=; b=ge+MlGL7aWnNsVsqwKzuq102MbCOSiM4JRL698WIUvrM6WIITd52MtNuCYbQM7JZlr 6RtOUJ/W+2m0ePTV9eycZq2uKvXZ/FUbcJtuM2F4GQ+vfPqzqT82i6OxtGzwcqDHp4ww zo2tEjK6tr52EZ7FrFr1nSoWMpUnVnUvaboQKAil2gNSNW+MC5YYqSeQghK5oTwCePCP ZNrz30wYnLQzHQnXFrBkNlKTQT9QiyBE7se7jWcEotdw/MMaWBhF7PBI1RvL0V/aDEos ay+KILW0f/rK5+NptLUv8s/1rYEJnNZXCidEQp6IconiJxrVa4qlp9wSILo4QHUiuscg MNWw== X-Gm-Message-State: ALQs6tAcii8eD5W7rT3x6t7mMXIJoVcAUtkpikD0nABeQTByOhXava2m j2L7c26ZZLNDdonHik66VROZTw== X-Google-Smtp-Source: AIpwx48PSzDiuYMH6Ny5SWViTORIVdnguF4VUrwb9NO9Q6Zogr0CmgmACN8sZCN+DvtINtD6SPVF4Q== X-Received: by 10.99.125.19 with SMTP id y19mr24213838pgc.160.1524673323003; Wed, 25 Apr 2018 09:22:03 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.22.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:02 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:46 -0700 Message-Id: <1524673309-30044-9-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 08/11] 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 --- 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 caa6e6c..7a4b5af 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 Wed Apr 25 16:21: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: 904616 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="ddGbhpDQ"; 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 40WQtd4vcrz9rxx for ; Thu, 26 Apr 2018 02:40:57 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5C55AD48; Wed, 25 Apr 2018 16:22: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 B965BCF6 for ; Wed, 25 Apr 2018 16:22:04 +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 6F5EB42D for ; Wed, 25 Apr 2018 16:22:04 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id a13so9231835pgu.4 for ; Wed, 25 Apr 2018 09:22: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=oI0DdHYnukjfFAbQ149mToF49Sg6qMjVvHI3V5T/9b0=; b=ddGbhpDQx0ibLzK0YBUTgBiG4K2TJZLXqHI4Cj2aRivBvCFtZO/0B+YSviu96HO1Sy aTjxWENpy+CiL2iKTy4n4P72xmoEQdZr+pxIkVBSnSfEY6dzKhLKW4N6kKgqaCU1rDR7 VNBWPhoCqeFPgLmPGn2AccfSb4c5P5pTO42ivEHwwKyaKB9fLOrkn1sRNg+Hj+26yUqj OYQXZrMUhVZcRBKSJiP1uogjXdrlmo5f6yyHEAoPzj7WYS9KbPSjbTcQo4XtYYBcQSr1 Zy9qs8e7aCu+tCrBY2KtMgwrdD+qSiUHJnhHZWnLPj2kviYdxHTS2fMT6v1ActW8BzZ+ aqeg== 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=oI0DdHYnukjfFAbQ149mToF49Sg6qMjVvHI3V5T/9b0=; b=QoV4uM8c5uieGAPYQO9VxdSwb9+uK3kMFKVPjAMO9snD9E0XsJ710GhhU4SO8ZIdXA Gy1h7ccP/ti9W9m6uVBOwhTzWWX0ra1rB4Z8ZnKdq8RZVBheHap+QudsL6OwEIa7EUFJ zONKZtvJw0U5L5TUOxktU2lVqq+Y+QwIiTJqq151nJumoZnL19cuO/YZcxSoYb3bVm4y VbdiBNCrYC8gmUlFmkXB8NfRMmWMFGHCQtZ+6OGotcagyek8R2edoXEp39HklpfLTeCN PwR9g3yv6nA0W8W6JAf08K63UCrPwoWkbNF+bGBXE1JXc/c20wqaG1R53mGn2i+8U4pu ypxQ== X-Gm-Message-State: ALQs6tCUYpMjm1jIHLBdNg+YZpHNewSce4yjGHtQ5aIqw8AK0zBc6at5 ljzoP9WYOfLK4xiqYt0SV4+D3g== X-Google-Smtp-Source: AIpwx48m5Dfjw6tmVVBh3eeIHWqKhiHKzVA+Lav4PSZyms3dhwTE5BTq+5hVsZDd0qLGFAs40MqLbA== X-Received: by 10.98.2.72 with SMTP id 69mr28572425pfc.12.1524673323798; Wed, 25 Apr 2018 09:22:03 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.22.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:03 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:47 -0700 Message-Id: <1524673309-30044-10-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 09/11] 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 --- 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 7a4b5af..2d6625c 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 Wed Apr 25 16:21: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: 904617 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="HIWPrvsk"; 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 40WQvH6XZmz9rxx for ; Thu, 26 Apr 2018 02:41:31 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3AF06D36; Wed, 25 Apr 2018 16:22: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 D3F2CD28 for ; Wed, 25 Apr 2018 16:22:05 +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 70AA242D for ; Wed, 25 Apr 2018 16:22:05 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id e12so13682193pgn.9 for ; Wed, 25 Apr 2018 09:22: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=E69iqNnIdxaZARpOpQINBpaCXljfFdE3IxSXg6JXkZo=; b=HIWPrvskb2Kiqmb7pGDJDugioLBfd5tYKiVI8Ww5N/wHVNzo/I/VuOHK/OxU/vdUNx VmRgsQxRiWHRk4wKL/sV5fZaRpgejv9fTpWpYqdPtkSWfa75UtKvQ2L8jVr+3T/PN5EP xm/IdAJTBDMoUM/Js8Y332xNIXV6oSn0r2fSQdhf5E26599ff4khsDXdiI9EGaxjrLjB ztNqVRXBIinC0+zh2iy0zIs9+i8yNyMi2YW8veGhe7r5PBaT7BXmeWIKhaFQpXX5wLrr UHIoDh8DdrxDcELxPHMGYfpxMFh2DbcktPwTqDvkhwTG8jZit61NPnyDQRH/kd5++MD6 mZYw== 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=E69iqNnIdxaZARpOpQINBpaCXljfFdE3IxSXg6JXkZo=; b=hZdsa/0sT04tQbG5ML31XugfEcaUdszofWT0iKY7dka1RCC0x+HFkVo0gjbll7ZEDz C+4+G5/rwJzcXikXaatT6n3nn4p5NH1xoTkUn5nfhU+/C91kgIT8gh/tt0emUZF8G4M9 7kTEa81i86ip/XLFw0MoK5VGy559cwwS4hmnPjJOhytl1JAYj7IFcoyA/O9sbZv3d1lG j80FTh6PZ0QcZjd0rFOc0UMeX2U7QqORbclQXZvbxT74CwrwZgaDin9VVB6I1/eiWmxM ikQI6ZHdI2DKlBMALJjJJOO6OMrKgQCAgNnAb6OVbOJvBExspJZVKk0beSOEzYkVm1dc nRFA== X-Gm-Message-State: ALQs6tCSVwhdtpB7nh40UADNa2atFvgkDkt5LICFwAP1qStDliUAVg8L urDPkroULI/D5wd/DZiLuHiMoA== X-Google-Smtp-Source: AIpwx4/dzfscioxJXXH3cN6CsM8FUPKgxzzmRAhlBHlmuphnnxjHmbEsdWPoZ2XkKCINL8JOTTqYtw== X-Received: by 10.99.64.3 with SMTP id n3mr24195901pga.13.1524673324658; Wed, 25 Apr 2018 09:22:04 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.22.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:04 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:48 -0700 Message-Id: <1524673309-30044-11-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 10/11] 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 --- 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 2d6625c..80be7e8 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 Wed Apr 25 16:21:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 904618 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="qnt1qJOs"; 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 40WQw10WCQz9rxx for ; Thu, 26 Apr 2018 02:42:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4F6C9D53; Wed, 25 Apr 2018 16:22:11 +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 B803DD2A for ; Wed, 25 Apr 2018 16:22:06 +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 6D472477 for ; Wed, 25 Apr 2018 16:22:06 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id a13so9231914pgu.4 for ; Wed, 25 Apr 2018 09:22: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=JGvAf7gbc/c2t3rkerhiBTJCzfIOTPKS5l6i9IBEpNE=; b=qnt1qJOscQTVSjQnIkEYkullFf1apLUxC/X9mmxLRxyrmjHgIgbU7BB807mPCUADlo LIp57QWncy3+mgdYmMmeU1i8lkatwUVTPZz7nkHeSlmqYo0+w7SkpC+x/nW6UG7iXjxs 53nULVb5Xohm5DUevFZga5Ekw9oSDXGzaSqQHRJvWXOHKl1Qp6LKvh+K9MTv8ROo1CWZ dCBDiU7PLWGDU9YAqQnh6WyYX5mE+ibaoMgR0uvThPW5+Mp7OLtXEFpLSwq9pYu40bmg Oj3NFL+89cyFNRVy4Hx/040PI7bCeolX9RQxx0gh0odTLYXgE90G/DIIgZLp4s6YNVuq Rd7Q== 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=JGvAf7gbc/c2t3rkerhiBTJCzfIOTPKS5l6i9IBEpNE=; b=p5c2/aXVxGwWnWUARDkn23Y9M1cFEfggcJ+YoeCgmrgO2Xy2J3nKn/O0h2BffcLSEe JnHweVngN3Ks6zTCzP957nVq6lmyprZwSwfvbuNzaHx8zgxVeV5iMzfnuN2vgewY+chz o68ZYhRG/4HYrvEPWXYcvEw46dn8L++M+s6FF0bkESwsYd28EFlemRh1f5hllbRCylHI OdzUwQgbOJer1B1Qaj0B+VUZcmzTqpmhQh7zwOwZnPjcO210Xp4fJFe3juCxG5/GG1U4 tm9Vs72z+2k6Lcd2dSbMbQzPYuBSEDRI+oQJbLf9BtFq8Vv9ZA9J/K4flGuePZSWWz7/ Rf/w== X-Gm-Message-State: ALQs6tDgwIKPMQHNiFFtS+1AfkVbRD8e96cCgYwgzD1lB8pdcLX6JnkK kypDmE63wmwwTK12khbcgGTtgw== X-Google-Smtp-Source: AIpwx49/On4MnyR/ZRZziftgJbQXywbaLEKnhIv8wFO6rpvCG8gyi0KpO1I+0tYzJV/Sn+uadlM4rw== X-Received: by 10.167.128.207 with SMTP id a15mr28256835pfn.116.1524673325688; Wed, 25 Apr 2018 09:22:05 -0700 (PDT) Received: from gizo.domain (67-5-146-204.ptld.qwest.net. [67.5.146.204]) by smtp.gmail.com with ESMTPSA id o64sm32800694pfb.62.2018.04.25.09.22.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Apr 2018 09:22:05 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org, pshelar@ovn.org Date: Wed, 25 Apr 2018 09:21:49 -0700 Message-Id: <1524673309-30044-12-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1524673309-30044-1-git-send-email-gvrose8192@gmail.com> References: <1524673309-30044-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 11/11] 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 --- 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 80be7e8..c8126ff 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;