From patchwork Fri May 18 01:57:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915933 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="UKL/h0AO"; 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 40nBDL5lWrz9s1w for ; Fri, 18 May 2018 11:58:58 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 29615DDD; Fri, 18 May 2018 01:58:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id F2451EE0 for ; Fri, 18 May 2018 01:58:24 +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 848FC6DB for ; Fri, 18 May 2018 01:58:23 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id v63-v6so2957630pfk.8 for ; Thu, 17 May 2018 18:58:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iYOSj8PEEuNe50fP3PddKF9HVz/hjRJf8qZkd0VME+I=; b=UKL/h0AO9QV4cHHlbfbFkEDVxZ3Ib/9TRMVBhO3RghTWVN9DjMOThzDxcNnmxJedAZ U62eofgfE8AwmdPqwFijdlIppDRmah6J6vugxlFWy1OY8FVEen0bVINREyWSxLiujRYd 67sRhlQe0QUfrQ6dgBMCdG/75K5SsiafTt+GUv50gbgP1QpiUfir+FhxRj84ql2Otemi 34CDbR+z67zT0W5hHNWExbcangMx0hEpjuAGSGxRddHH9ukElZz1wEAeAQFd5buWIdup frUcD4vxvei3nQ+s/zAH21xyY0i324nblf7mMyUjQwkICfL4JrxgkrAZKlTk3meJ1CN7 cEEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iYOSj8PEEuNe50fP3PddKF9HVz/hjRJf8qZkd0VME+I=; b=s0Mvu7DKKXvuFbZmeiJi5/IcJZQoKMQDZTCopFVzosjhoCUGiwy0frvgYdcvns7H9N eNraR8bsKdAnD8GpQ4csp8+3hhJnmyK7kJFoCV9wk6lRvpDB8m4OnVtfOnjelPaWdGZm 2Wb0X77U8Dwa3qc0uENlUd786aFIei1Uf4S81J0Gc+9NE0mOQ3amfl7nHhrfpVu4c8s1 bFL8krSw9uBnU7tSCjFc2HYCDrjsM89PTLfh/bovifx9f8AGKN+hdLrUVNJ3UqNDtJCK mmJmh9LfipPDRG9bv+Sp7v3POIgaE3T/6bCzX0fpxp6x6HQJH6jj1yqFVRZCnkxj3PCk KB9w== X-Gm-Message-State: ALKqPwdmYBjeh/QNQVV6rh8qdTxuA7Xgig8kAzDTsZ/KlN8xqcqpUiD2 9cVZ4q/1JQ1GnvLEfxv7P7RZfQ== X-Google-Smtp-Source: AB8JxZpDS3A1gUNg/m7wgtQhaapnUJTQRWkXujJqAg/mddM/Tn1ab/kd+Ql2R4LCGE7IyC7R4Czcag== X-Received: by 2002:a63:61c8:: with SMTP id v191-v6mr5911603pgb.184.1526608702235; Thu, 17 May 2018 18:58:22 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:21 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:14 -0700 Message-Id: <1526608674-12702-2-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 01/41] compat: Remove unsupported kernel compat code X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Anything less than 3.10 isn't supported since a couple of releases ago so remove the dead code. Signed-off-by: Greg Rose --- datapath/linux/compat/include/linux/etherdevice.h | 30 ------ datapath/linux/compat/include/linux/if_vlan.h | 11 --- datapath/linux/compat/include/linux/kconfig.h | 8 -- datapath/linux/compat/include/linux/kernel.h | 38 -------- .../linux/compat/include/linux/netdev_features.h | 19 ---- datapath/linux/compat/include/linux/netdevice.h | 5 - datapath/linux/compat/include/linux/skbuff.h | 7 -- datapath/linux/compat/include/linux/workqueue.h | 4 - datapath/linux/compat/include/net/checksum.h | 6 -- datapath/linux/compat/include/net/dst.h | 28 +----- datapath/linux/compat/include/net/genetlink.h | 11 --- datapath/linux/compat/include/net/ip6_route.h | 23 ----- datapath/linux/compat/include/net/ip_tunnels.h | 4 - datapath/linux/compat/include/net/ipv6.h | 15 --- .../include/net/netfilter/nf_conntrack_zones.h | 2 - datapath/linux/compat/include/net/netlink.h | 15 --- datapath/linux/compat/include/net/route.h | 105 --------------------- datapath/linux/compat/ip_gre.c | 11 --- datapath/linux/compat/ip_tunnel.c | 8 +- datapath/linux/compat/lisp.c | 2 - datapath/linux/compat/stt.c | 6 -- datapath/linux/compat/udp_tunnel.c | 2 - datapath/linux/compat/utils.c | 22 ----- 23 files changed, 2 insertions(+), 380 deletions(-) diff --git a/datapath/linux/compat/include/linux/etherdevice.h b/datapath/linux/compat/include/linux/etherdevice.h index 850b779..4b27074 100644 --- a/datapath/linux/compat/include/linux/etherdevice.h +++ b/datapath/linux/compat/include/linux/etherdevice.h @@ -4,36 +4,6 @@ #include #include_next -#ifndef HAVE_ETH_HW_ADDR_RANDOM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - dev_hw_addr_random(dev, dev->dev_addr); -} -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) -#define eth_mac_addr rpl_eth_mac_addr -static inline int eth_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; -#ifdef NET_ADDR_RANDOM - dev->addr_assign_type &= ~NET_ADDR_RANDOM; -#endif - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} -#endif - #ifndef HAVE_ETHER_ADDR_COPY static inline void ether_addr_copy(u8 *dst, const u8 *src) { diff --git a/datapath/linux/compat/include/linux/if_vlan.h b/datapath/linux/compat/include/linux/if_vlan.h index fc95b04..2cf18e5 100644 --- a/datapath/linux/compat/include/linux/if_vlan.h +++ b/datapath/linux/compat/include/linux/if_vlan.h @@ -90,17 +90,6 @@ static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -static inline struct sk_buff *rpl___vlan_hwaccel_put_tag(struct sk_buff *skb, - __be16 vlan_proto, - u16 vlan_tci) -{ - return __vlan_hwaccel_put_tag(skb, vlan_tci); -} - -#define __vlan_hwaccel_put_tag rpl___vlan_hwaccel_put_tag -#endif - #ifndef HAVE_ETH_TYPE_VLAN /** * eth_type_vlan - check for valid vlan ether type. diff --git a/datapath/linux/compat/include/linux/kconfig.h b/datapath/linux/compat/include/linux/kconfig.h index 5717a26..d3fa57a 100644 --- a/datapath/linux/compat/include/linux/kconfig.h +++ b/datapath/linux/compat/include/linux/kconfig.h @@ -3,14 +3,6 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -#define CONFIG_NET_IPGRE_DEMUX 1 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) -#include_next -#endif - #ifndef IS_ENABLED /* diff --git a/datapath/linux/compat/include/linux/kernel.h b/datapath/linux/compat/include/linux/kernel.h index 5c4269b..2e81abc 100644 --- a/datapath/linux/compat/include/linux/kernel.h +++ b/datapath/linux/compat/include/linux/kernel.h @@ -8,44 +8,6 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -#define pr_warn pr_warning -#endif - -/* - * Print a one-time message (analogous to WARN_ONCE() et al): - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) -#undef printk_once -#define printk_once(fmt, ...) \ -({ \ - static bool __print_once; \ - \ - if (!__print_once) { \ - __print_once = true; \ - printk(fmt, ##__VA_ARGS__); \ - } \ -}) - -#define pr_emerg_once(fmt, ...) \ - printk_once(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) -#define pr_alert_once(fmt, ...) \ - printk_once(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) -#define pr_crit_once(fmt, ...) \ - printk_once(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) -#define pr_err_once(fmt, ...) \ - printk_once(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) -#define pr_warn_once(fmt, ...) \ - printk_once(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) -#define pr_notice_once(fmt, ...) \ - printk_once(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) -#define pr_info_once(fmt, ...) \ - printk_once(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) -#define pr_cont_once(fmt, ...) \ - printk_once(KERN_CONT pr_fmt(fmt), ##__VA_ARGS__) - -#endif - #ifndef USHRT_MAX #define USHRT_MAX ((u16)(~0U)) #define SHRT_MAX ((s16)(USHRT_MAX>>1)) diff --git a/datapath/linux/compat/include/linux/netdev_features.h b/datapath/linux/compat/include/linux/netdev_features.h index a39bd4a..411f294 100644 --- a/datapath/linux/compat/include/linux/netdev_features.h +++ b/datapath/linux/compat/include/linux/netdev_features.h @@ -1,18 +1,7 @@ #ifndef __LINUX_NETDEV_FEATURES_WRAPPER_H #define __LINUX_NETDEV_FEATURES_WRAPPER_H -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) #include_next -#endif - -#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) -/* On RHEL 6, netdev features are defined in netdevice.h header. */ -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_TX -#endif #ifndef NETIF_F_GSO_GRE #define NETIF_F_GSO_GRE 0 @@ -81,14 +70,6 @@ NETIF_F_GSO_MPLS) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) -#define SKB_GSO_GRE 0 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) -#define SKB_GSO_UDP_TUNNEL 0 -#endif - #ifndef HAVE_NETIF_F_GSO_GRE_CSUM #define SKB_GSO_GRE_CSUM 0 #endif diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 9d3b249..29ef6c7 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -37,11 +37,6 @@ struct net; alloc_netdev_mq(sizeof_priv, name, setup, 1) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#define unregister_netdevice_queue(dev, head) unregister_netdevice(dev) -#define unregister_netdevice_many(head) -#endif - #ifndef HAVE_DEV_DISABLE_LRO extern void dev_disable_lro(struct net_device *dev); #endif diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 2910f3f..149ef28 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -212,13 +212,6 @@ static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask) #define skb_get_hash skb_get_rxhash #endif /* HAVE_SKB_GET_HASH */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) -static inline void skb_tx_error(struct sk_buff *skb) -{ - return; -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) */ - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #define skb_zerocopy_headlen rpl_skb_zerocopy_headlen unsigned int rpl_skb_zerocopy_headlen(const struct sk_buff *from); diff --git a/datapath/linux/compat/include/linux/workqueue.h b/datapath/linux/compat/include/linux/workqueue.h index 461fefd..ed573c2 100644 --- a/datapath/linux/compat/include/linux/workqueue.h +++ b/datapath/linux/compat/include/linux/workqueue.h @@ -3,8 +3,4 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_work(wq, dw) schedule_work(dw); -#endif - #endif diff --git a/datapath/linux/compat/include/net/checksum.h b/datapath/linux/compat/include/net/checksum.h index 398df93..d1f1125 100644 --- a/datapath/linux/compat/include/net/checksum.h +++ b/datapath/linux/compat/include/net/checksum.h @@ -36,10 +36,4 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to) #define CSUM_MANGLED_0 ((__force __sum16)0xffff) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -#define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16 -void rpl_inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, - const __be32 *from, const __be32 *to, - int pseudohdr); -#endif #endif /* checksum.h */ diff --git a/datapath/linux/compat/include/net/dst.h b/datapath/linux/compat/include/net/dst.h index 5ec3d30..af78a6c 100644 --- a/datapath/linux/compat/include/net/dst.h +++ b/datapath/linux/compat/include/net/dst.h @@ -4,13 +4,6 @@ #include #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(3,0,20) - -#define dst_get_neighbour_noref dst_get_neighbour - -#endif - #ifndef HAVE_SKB_DST_ACCESSOR_FUNCS static inline void skb_dst_drop(struct sk_buff *skb) @@ -30,19 +23,7 @@ static inline void skb_dst_drop(struct sk_buff *skb) #define DST_NOCOUNT 0 #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) -{ - nskb->_skb_dst = refdst; - dst_clone(skb_dst(nskb)); -} - -static inline void refdst_drop(unsigned long refdst) { } -static inline void skb_dst_set_noref(struct sk_buff *skb, - struct dst_entry *dst) { } -static inline void dst_init_metrics(struct dst_entry *dst, const u32 *metrics, - bool read_only) { } -#elif !defined(HAVE___SKB_DST_COPY) +#if !defined(HAVE___SKB_DST_COPY) static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) { nskb->_skb_refdst = refdst; @@ -51,13 +32,6 @@ static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -static inline void dst_entries_add(struct dst_ops *ops, int count) -{ - atomic_add(count, &ops->entries); -} -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) static const u32 rpl_dst_default_metrics[RTAX_MAX + 1] = { /* This initializer is needed to force linker to place this variable diff --git a/datapath/linux/compat/include/net/genetlink.h b/datapath/linux/compat/include/net/genetlink.h index b05eae5..602ce38 100644 --- a/datapath/linux/compat/include/net/genetlink.h +++ b/datapath/linux/compat/include/net/genetlink.h @@ -6,17 +6,6 @@ #include #include_next -/* - * 15e473046cb6e5d18a4d0057e61d76315230382b renames pid to portid - * the affected structures are - * netlink_skb_parms::pid -> portid - * genl_info::snd_pid -> snd_portid - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -#define snd_portid snd_pid -#define portid pid -#endif - #ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY struct rpl_genl_family { struct genl_family compat_family; diff --git a/datapath/linux/compat/include/net/ip6_route.h b/datapath/linux/compat/include/net/ip6_route.h index e49ca39..7c78fd5 100644 --- a/datapath/linux/compat/include/net/ip6_route.h +++ b/datapath/linux/compat/include/net/ip6_route.h @@ -7,29 +7,6 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) - -static inline -struct dst_entry *rpl_ip6_route_output(struct net *net, const struct sock *sk, - struct flowi6 *fl6) -{ - struct flowi fl; - - memset(&fl, 0, sizeof(fl)); - fl.oif = fl6->flowi6_oif; - fl.fl6_dst = fl6->daddr; - fl.fl6_src = fl6->saddr; - fl.mark = fl6->flowi6_mark; - fl.proto = fl6->flowi6_proto; - - return ip6_route_output(net, (struct sock *) sk, &fl); -} -#define ip6_route_output rpl_ip6_route_output - -#define ip6_dst_hoplimit(dst) dst_metric(dst, RTAX_HOPLIMIT) - -#endif /* 2.6.39 */ - #ifndef HAVE_NF_IPV6_OPS_FRAGMENT int rpl_ip6_fragment(struct sock *sk, struct sk_buff *skb, int (*output)(OVS_VPORT_OUTPUT_PARAMS)); diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index ae60f09..68dbd7c 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -301,11 +301,7 @@ int rpl_ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p); #define ip_tunnel_dellink rpl_ip_tunnel_dellink -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head); -#else -void rpl_ip_tunnel_dellink(struct net_device *dev); -#endif #define ip_tunnel_init_net rpl_ip_tunnel_init_net int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, diff --git a/datapath/linux/compat/include/net/ipv6.h b/datapath/linux/compat/include/net/ipv6.h index 48a307a..7fc0339 100644 --- a/datapath/linux/compat/include/net/ipv6.h +++ b/datapath/linux/compat/include/net/ipv6.h @@ -26,21 +26,6 @@ extern int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff, int *fragflg); #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) -static inline u32 ipv6_addr_hash(const struct in6_addr *a) -{ -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 - const unsigned long *ul = (const unsigned long *)a; - unsigned long x = ul[0] ^ ul[1]; - - return (u32)(x ^ (x >> 32)); -#else - return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^ - a->s6_addr32[2] ^ a->s6_addr32[3]); -#endif -} -#endif - #ifndef HAVE___IPV6_ADDR_JHASH static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 unused) { diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h index fb43acb..d46c098 100644 --- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_zones.h @@ -3,9 +3,7 @@ #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) #include_next -#endif #ifndef HAVE_NF_CT_ZONE_INIT diff --git a/datapath/linux/compat/include/net/netlink.h b/datapath/linux/compat/include/net/netlink.h index ba24a34..d42bf10 100644 --- a/datapath/linux/compat/include/net/netlink.h +++ b/datapath/linux/compat/include/net/netlink.h @@ -16,21 +16,6 @@ static inline __be16 nla_get_be16(const struct nlattr *nla) } #endif /* !HAVE_NLA_GET_BE16 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -/* This function was introduced in 2.6.31, but initially it performed an - * unaligned access, so we replace it up to 2.6.34 where it was fixed. */ -#define nla_get_be64 rpl_nla_get_be64 -static inline __be64 nla_get_be64(const struct nlattr *nla) -{ - __be64 tmp; - - /* The additional cast is necessary because */ - nla_memcpy(&tmp, (struct nlattr *) nla, sizeof(tmp)); - - return tmp; -} -#endif - #ifndef HAVE_NLA_PUT_BE16 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { diff --git a/datapath/linux/compat/include/net/route.h b/datapath/linux/compat/include/net/route.h index 8f336b6..9e4a1f1 100644 --- a/datapath/linux/compat/include/net/route.h +++ b/datapath/linux/compat/include/net/route.h @@ -3,109 +3,4 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -struct flowi_common { - int flowic_oif; - __u32 flowic_mark; - __u8 flowic_tos; - __u8 flowic_proto; -}; - -union flowi_uli { - struct { - __be16 dport; - __be16 sport; - } ports; - - struct { - __u8 type; - __u8 code; - } icmpt; - - struct { - __le16 dport; - __le16 sport; - } dnports; - - __be32 spi; - __be32 gre_key; - - struct { - __u8 type; - } mht; -}; - -struct flowi4 { - struct flowi_common __fl_common; -#define flowi4_oif __fl_common.flowic_oif -#define flowi4_iif __fl_common.flowic_iif -#define flowi4_mark __fl_common.flowic_mark -#define flowi4_tos __fl_common.flowic_tos -#define flowi4_scope __fl_common.flowic_scope -#define flowi4_proto __fl_common.flowic_proto -#define flowi4_flags __fl_common.flowic_flags -#define flowi4_secid __fl_common.flowic_secid -#define flowi4_tun_key __fl_common.flowic_tun_key - - union flowi_uli uli; -#define fl4_gre_key uli.gre_key - - /* (saddr,daddr) must be grouped, same order as in IP header */ - __be32 saddr; - __be32 daddr; - -} __attribute__((__aligned__(BITS_PER_LONG/8))); - -struct flowi6 { - struct flowi_common __fl_common; -#define flowi6_oif __fl_common.flowic_oif -#define flowi6_iif __fl_common.flowic_iif -#define flowi6_mark __fl_common.flowic_mark -#define flowi6_tos __fl_common.flowic_tos -#define flowi6_scope __fl_common.flowic_scope -#define flowi6_proto __fl_common.flowic_proto -#define flowi6_flags __fl_common.flowic_flags -#define flowi6_secid __fl_common.flowic_secid -#define flowi6_tun_key __fl_common.flowic_tun_key - struct in6_addr daddr; - struct in6_addr saddr; - __be32 flowlabel; - union flowi_uli uli; -#define fl6_sport uli.ports.sport -#define fl6_dport uli.ports.dport -#define fl6_icmp_type uli.icmpt.type -#define fl6_icmp_code uli.icmpt.code -#define fl6_ipsec_spi uli.spi -#define fl6_mh_type uli.mht.type -#define fl6_gre_key uli.gre_key -} __attribute__((__aligned__(BITS_PER_LONG/8))); - -static inline struct rtable *rpl_ip_route_output_key(struct net *net, struct flowi4 *flp) -{ - struct rtable *rt; - /* Tunnel configuration keeps DSCP part of TOS bits, But Linux - * router expect RT_TOS bits only. - */ - - struct flowi fl = { .nl_u = { .ip4_u = { - .daddr = flp->daddr, - .saddr = flp->saddr, - .tos = RT_TOS(flp->flowi4_tos) } }, - .mark = flp->flowi4_mark, - .proto = flp->flowi4_proto }; - - if (unlikely(ip_route_output_key(net, &rt, &fl))) - return ERR_PTR(-EADDRNOTAVAIL); - flp->saddr = fl.nl_u.ip4_u.saddr; - return rt; -} -#define ip_route_output_key rpl_ip_route_output_key -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) -static inline int ip4_dst_hoplimit(const struct dst_entry *dst) -{ - return dst_metric(dst, RTAX_HOPLIMIT); -} -#endif #endif diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 2f297a5..4304862 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -365,16 +365,12 @@ static void __gre_tunnel_init(struct net_device *dev) dev->mtu = ETH_DATA_LEN - t_hlen - 4; dev->features |= GRE_FEATURES; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= GRE_FEATURES; -#endif if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { /* TCP offload with GRE SEQ is not supported. */ dev->features |= NETIF_F_GSO_SOFTWARE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= NETIF_F_GSO_SOFTWARE; -#endif /* Can use a lockless transmit, unless we generate * output sequences */ @@ -496,9 +492,7 @@ static const struct net_device_ops gre_tap_netdev_ops = { #else .ndo_change_mtu = ip_tunnel_change_mtu, #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif #ifdef HAVE_NDO_GET_IFLINK .ndo_get_iflink = ip_tunnel_get_iflink, #endif @@ -515,13 +509,8 @@ static void ipgre_tap_setup(struct net_device *dev) ip_tunnel_setup(dev, gre_tap_net_id); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) -#else -static int ipgre_newlink(struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) -#endif { struct ip_tunnel_parm p; int err; diff --git a/datapath/linux/compat/ip_tunnel.c b/datapath/linux/compat/ip_tunnel.c index be82b55..ebd1544 100644 --- a/datapath/linux/compat/ip_tunnel.c +++ b/datapath/linux/compat/ip_tunnel.c @@ -168,11 +168,7 @@ static void ip_tunnel_dev_free(struct net_device *dev) free_netdev(dev); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head) -#else -void rpl_ip_tunnel_dellink(struct net_device *dev) -#endif { struct ip_tunnel *tunnel = netdev_priv(dev); struct ip_tunnel_net *itn; @@ -180,9 +176,7 @@ void rpl_ip_tunnel_dellink(struct net_device *dev) itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); ip_tunnel_del(itn, netdev_priv(dev)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) - unregister_netdevice_queue(dev, head); -#endif + unregister_netdevice_queue(dev, head); } int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c index 4882a63..41531ad 100644 --- a/datapath/linux/compat/lisp.c +++ b/datapath/linux/compat/lisp.c @@ -597,10 +597,8 @@ static void lisp_setup(struct net_device *dev) dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_GSO_SOFTWARE; -#endif #ifdef USE_UPSTREAM_TUNNEL netif_keep_dst(dev); #endif diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c index ee1c7aa..69859e2 100644 --- a/datapath/linux/compat/stt.c +++ b/datapath/linux/compat/stt.c @@ -239,9 +239,7 @@ static void copy_skb_metadata(struct sk_buff *to, struct sk_buff *from) to->priority = from->priority; to->mark = from->mark; to->vlan_tci = from->vlan_tci; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) to->vlan_proto = from->vlan_proto; -#endif skb_copy_secmark(to, from); } @@ -762,10 +760,8 @@ static int stt_can_offload(struct sk_buff *skb, __be16 l3_proto, u8 l4_proto) if (skb->len + STT_HEADER_LEN + sizeof(struct iphdr) > 65535) return 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (skb_vlan_tag_present(skb) && skb->vlan_proto != htons(ETH_P_8021Q)) return 0; -#endif return 1; } @@ -792,7 +788,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, int min_headroom) { int err; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (skb_vlan_tag_present(skb) && skb->vlan_proto != htons(ETH_P_8021Q)) { min_headroom += VLAN_HLEN; @@ -812,7 +807,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb, int min_headroom) goto error; } } -#endif if (skb_is_gso(skb)) { struct sk_buff *nskb; diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c index 23801bb..852069f 100644 --- a/datapath/linux/compat/udp_tunnel.c +++ b/datapath/linux/compat/udp_tunnel.c @@ -130,9 +130,7 @@ void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock, udp_sk(sk)->encap_type = cfg->encap_type; udp_sk(sk)->encap_rcv = cfg->encap_rcv; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) udp_sk(sk)->encap_destroy = cfg->encap_destroy; -#endif #ifdef HAVE_UDP_TUNNEL_SOCK_CFG_GRO_RECEIVE udp_sk(sk)->gro_receive = cfg->gro_receive; udp_sk(sk)->gro_complete = cfg->gro_complete; diff --git a/datapath/linux/compat/utils.c b/datapath/linux/compat/utils.c index c9546ea..a4a98ba 100644 --- a/datapath/linux/compat/utils.c +++ b/datapath/linux/compat/utils.c @@ -18,28 +18,6 @@ #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) -void rpl_inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, - const __be32 *from, const __be32 *to, - int pseudohdr) -{ - __be32 diff[] = { - ~from[0], ~from[1], ~from[2], ~from[3], - to[0], to[1], to[2], to[3], - }; - if (skb->ip_summed != CHECKSUM_PARTIAL) { - *sum = csum_fold(csum_partial(diff, sizeof(diff), - ~csum_unfold(*sum))); - if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) - skb->csum = ~csum_partial(diff, sizeof(diff), - ~skb->csum); - } else if (pseudohdr) - *sum = ~csum_fold(csum_partial(diff, sizeof(diff), - csum_unfold(*sum))); -} -EXPORT_SYMBOL_GPL(rpl_inet_proto_csum_replace16); -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) bool rpl___net_get_random_once(void *buf, int nbytes, bool *done, From patchwork Fri May 18 01:57:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915940 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="BUaPIe+H"; 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 40nBHn3FGNz9s37 for ; Fri, 18 May 2018 12:01:57 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A1F84106D; Fri, 18 May 2018 01:58:34 +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 32549F47 for ; Fri, 18 May 2018 01:58:30 +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 F27BF196 for ; Fri, 18 May 2018 01:58:25 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id e1-v6so2608420pga.6 for ; Thu, 17 May 2018 18:58:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=++inPSDS43Z0+rJd8Rp9AGOo20Kw4zZ04iuZEHmOBo4=; b=BUaPIe+HkPoKGrzYbrHUxjX7yH8CRkGRK8jXa2OPVeyegO5IGktdL86/YuUfvKFQBc zLqY0tg7u5eeDXX5LzGF4ik3yXQjZzG+XYBOygvEuCRSck904j5+HZ8djMZfEzowZNj5 k3ONTr+NBaCBapq4PwQVOVsguEQIHEoIzooOlIXepP0BjFVUaPN3tF46hkAJ/TKustDo ud/5Z+aZm8qk3mFhJtE/XhPUJ5ULsNUR2hPmrzzwjOGOz6iCsk1bjNXs5bSaYkj2Lma6 X5IdUQPwJnWruovgrN7jC3B8l9HHC9nsS+CiWl+jwIPFZziUrbOdzQfYeTzU4xTWPFTr Wvmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=++inPSDS43Z0+rJd8Rp9AGOo20Kw4zZ04iuZEHmOBo4=; b=VS8cEIH9FLZd4qsXFVHqORk6PG9uBg81Oz/CLzzp8gvijwAB7RSzxqKZ0TppvDGb0A Bnu4WkbGfydqPsx0sMjmsDA2aoOYC7m1or8Qw+cKdOFp43qBjWhb4Jmvf0YIW1jRobb7 5n+tGZepsLJnkelqS8giZeBZp44g6VxDxqLkbOOPXerUBD3jpL3SE90Ri5LvCqgnsNcU qwAmn3thHIFoSHWKYmBcZakPKB6idWf34ZkrTVemLGwIlB1l4d/zJ14vGvWuFTH9fL5G l/ITKMQJI5UWvbzfB4e0cK6bcUUwrAMrtWutjTNYOiWftuqlgrL3uJezmUV2JgL6V0wK nNJg== X-Gm-Message-State: ALKqPweScWCZ9haY1vAffsrcWdlC3Y5VK9u+EXaaxN8cDHmFT/ZhfP3o kl/C8XJRPNOUzzXllUHrBzrZuQ== X-Google-Smtp-Source: AB8JxZpnJb6oq+/IwvME71vzUxLo/CuffoBb2y7zgA1d3U4Q6zAiSY5jhrfMLpNXbsl2VB82SvWonQ== X-Received: by 2002:a63:18c:: with SMTP id 134-v6mr5811500pgb.138.1526608703855; Thu, 17 May 2018 18:58:23 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:23 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:15 -0700 Message-Id: <1526608674-12702-3-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 02/41] 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 a2444af..8962862 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -818,7 +818,54 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], frag_percpu_counter_batch[], [OVS_DEFINE([HAVE_FRAG_PERCPU_COUNTER_BATCH])]) - + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [null_compute_pseudo], + [OVS_DEFINE([HAVE_NULL_COMPUTE_PSEUDO])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [__skb_checksum_convert], + [OVS_DEFINE([HAVE_SKB_CHECKSUM_CONVERT])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h], [net_device], + [max_mtu], + [OVS_DEFINE([HAVE_NET_DEVICE_MAX_MTU])]) + OVS_GREP_IFELSE([$KSRC/include/net/erspan.h], + [__LINUX_ERSPAN_H], + [OVS_DEFINE([HAVE_LINUX_ERSPAN_H])]) + OVS_FIND_PARAM_IFELSE([$KSRC/net/ipv6/ip6_gre.c], + [ip6gre_tunnel_validate], [extack], + [OVS_DEFINE([HAVE_IP6GRE_EXTACK])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ip6_tunnel.h], [__ip6_tnl_parm], + [erspan_ver], + [OVS_DEFINE([HAVE_IP6_TNL_PARM_ERSPAN_VER])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [SKB_GSO_IPXIP6], + [OVS_DEFINE([HAVE_SKB_GSO_IPXIP6])]) + OVS_FIND_PARAM_IFELSE([$KSRC/include/net/ipv6.h], + [ip6_make_flowlabel], [fl6], + [OVS_DEFINE([HAVE_IP6_MAKE_FLOWLABEL_FL6])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ipv6.h], [netns_sysctl_ipv6], + [auto_flowlabels], + [OVS_DEFINE([HAVE_NETNS_SYSCTL_IPV6_AUTO_FLOWLABELS])]) + OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], + [netif_keep_dst], + [OVS_DEFINE([HAVE_NETIF_KEEP_DST])]) + OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h], [net_device_ops], + [ndo_get_iflink], + [OVS_DEFINE([HAVE_NDO_GET_IFLINK])]) + OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], + [skb_set_inner_ipproto], + [OVS_DEFINE([HAVE_SKB_SET_INNER_IPPROTO])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [tunnel_encap_types], + [OVS_DEFINE([HAVE_TUNNEL_ENCAP_TYPES])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_IPTUN_ENCAP_TYPE], + [OVS_DEFINE([HAVE_IFLA_IPTUN_ENCAP_TYPE])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_IPTUN_COLLECT_METADATA], + [OVS_DEFINE([HAVE_IFLA_IPTUN_COLLECT_METADATA])]) + OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c], + [parse_gre_header], + [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])]) if cmp -s datapath/linux/kcompat.h.new \ datapath/linux/kcompat.h >/dev/null 2>&1; then diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index 0dbc1ed..e0a90c3 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -104,5 +104,6 @@ openvswitch_headers += \ linux/compat/include/net/netfilter/nf_conntrack_zones.h \ linux/compat/include/net/netfilter/nf_nat.h \ linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \ - linux/compat/include/net/sctp/checksum.h + linux/compat/include/net/sctp/checksum.h \ + linux/compat/include/net/erspan.h EXTRA_DIST += linux/compat/build-aux/export-check-whitelist diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index a341fa3..08a5a30 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -41,91 +41,25 @@ #ifndef USE_UPSTREAM_TUNNEL #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) -#ifndef HAVE_GRE_HANDLE_OFFLOADS - -#ifndef HAVE_GRE_CISCO_REGISTER - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - -#define GREPROTO_CISCO 0 -#define GREPROTO_MAX 1 - -struct gre_protocol { - int (*handler)(struct sk_buff *skb); -}; -static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; - -static int gre_rcv(struct sk_buff *skb) -{ - const struct gre_protocol *proto; - u8 ver; - int ret; - - if (!pskb_may_pull(skb, 12)) - goto drop; - - ver = skb->data[1] & 0x7f; - if (ver >= GREPROTO_MAX) - goto drop; - - rcu_read_lock(); - proto = rcu_dereference(gre_proto[ver]); - if (!proto || !proto->handler) - goto drop_unlock; - ret = proto->handler(skb); - rcu_read_unlock(); - return ret; - -drop_unlock: - rcu_read_unlock(); -drop: - kfree_skb(skb); - return NET_RX_DROP; -} - -static const struct net_protocol net_gre_protocol = { - .handler = gre_rcv, - .netns_ok = 1, -}; - -static int gre_add_protocol(const struct gre_protocol *proto, u8 version) -{ - if (version >= GREPROTO_MAX) - return -EINVAL; - - if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { - pr_err("%s: cannot register gre protocol handler\n", __func__); - return -EAGAIN; - } - - return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? - 0 : -EBUSY; -} - -static int gre_del_protocol(const struct gre_protocol *proto, u8 version) +#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen +#define gre_calc_hlen rpl_ip_gre_calc_hlen +static int rpl_ip_gre_calc_hlen(__be16 o_flags) { - int ret; - - if (version >= GREPROTO_MAX) - return -EINVAL; - - ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? - 0 : -EBUSY; - - if (ret) - return ret; - - synchronize_net(); - - ret = inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); - if (ret) - return ret; + int addend = 4; - return 0; + if (o_flags & TUNNEL_CSUM) + addend += 4; + if (o_flags & TUNNEL_KEY) + addend += 4; + if (o_flags & TUNNEL_SEQ) + addend += 4; + return addend; } -#endif +#ifndef HAVE_GRE_HANDLE_OFFLOADS +#ifndef HAVE_GRE_CISCO_REGISTER +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER static __sum16 check_checksum(struct sk_buff *skb) { __sum16 csum = 0; @@ -148,20 +82,6 @@ static __sum16 check_checksum(struct sk_buff *skb) return csum; } -#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen -static int ip_gre_calc_hlen(__be16 o_flags) -{ - int addend = 4; - - if (o_flags & TUNNEL_CSUM) - addend += 4; - if (o_flags & TUNNEL_KEY) - addend += 4; - if (o_flags & TUNNEL_SEQ) - addend += 4; - return addend; -} - #define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags static __be16 gre_flags_to_tnl_flags(__be16 flags) { @@ -202,13 +122,12 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, tpi->flags = gre_flags_to_tnl_flags(greh->flags); hdr_len = ip_gre_calc_hlen(tpi->flags); + tpi->hdr_len = hdr_len; + tpi->proto = greh->protocol; if (!pskb_may_pull(skb, hdr_len)) return -EINVAL; - greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); - tpi->proto = greh->protocol; - options = (__be32 *)(greh + 1); if (greh->flags & GRE_CSUM) { if (check_checksum(skb)) { @@ -246,20 +165,25 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, return iptunnel_pull_header(skb, hdr_len, tpi->proto, false); } +#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ + static struct gre_cisco_protocol __rcu *gre_cisco_proto; static int gre_cisco_rcv(struct sk_buff *skb) { struct tnl_ptk_info tpi; - bool csum_err = false; struct gre_cisco_protocol *proto; rcu_read_lock(); proto = rcu_dereference(gre_cisco_proto); if (!proto) goto drop; - - if (parse_gre_header(skb, &tpi, &csum_err) < 0) - goto drop; +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + { + bool csum_err = false; + if (parse_gre_header(skb, &tpi, &csum_err) < 0) + goto drop; + } +#endif proto->handler(skb, &tpi); rcu_read_unlock(); return 0; @@ -309,5 +233,101 @@ EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister); #endif /* !HAVE_GRE_CISCO_REGISTER */ #endif +void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct gre_base_hdr *greh; + + skb_push(skb, hdr_len); + + skb_reset_transport_header(skb); + greh = (struct gre_base_hdr *)skb->data; + greh->flags = tnl_flags_to_gre_flags(tpi->flags); + greh->protocol = tpi->proto; + + if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) { + __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); + + if (tpi->flags&TUNNEL_SEQ) { + *ptr = tpi->seq; + ptr--; + } + if (tpi->flags&TUNNEL_KEY) { + *ptr = tpi->key; + ptr--; + } + if (tpi->flags&TUNNEL_CSUM && + !(skb_shinfo(skb)->gso_type & + (SKB_GSO_GRE|SKB_GSO_GRE_CSUM))) { + *ptr = 0; + *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, + skb->len, 0)); + } + } +} +EXPORT_SYMBOL_GPL(rpl_gre_build_header); + +/* Fills in tpi and returns header length to be pulled. */ +int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool *csum_err, __be16 proto, int nhs) +{ + const struct gre_base_hdr *greh; + __be32 *options; + int hdr_len; + + if (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr)))) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb->data + nhs); + if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) + return -EINVAL; + + tpi->flags = gre_flags_to_tnl_flags(greh->flags); + hdr_len = gre_calc_hlen(tpi->flags); + + if (!pskb_may_pull(skb, nhs + hdr_len)) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb->data + nhs); + tpi->proto = greh->protocol; + + options = (__be32 *)(greh + 1); + if (greh->flags & GRE_CSUM) { + if (skb_checksum_simple_validate(skb)) { + *csum_err = true; + return -EINVAL; + } + + skb_checksum_try_convert(skb, IPPROTO_GRE, 0, + null_compute_pseudo); + options++; + } + + if (greh->flags & GRE_KEY) { + tpi->key = *options; + options++; + } else { + tpi->key = 0; + } + if (unlikely(greh->flags & GRE_SEQ)) { + tpi->seq = *options; + options++; + } else { + tpi->seq = 0; + } + /* WCCP version 1 and 2 protocol decoding. + * - Change protocol to IPv4/IPv6 + * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header + */ + if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { + tpi->proto = proto; + if ((*(u8 *)options & 0xF0) != 0x40) + hdr_len += 4; + } + tpi->hdr_len = hdr_len; + return hdr_len; +} +EXPORT_SYMBOL(rpl_gre_parse_header); + #endif /* CONFIG_NET_IPGRE_DEMUX */ #endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h index c989c6e..aaa88db 100644 --- a/datapath/linux/compat/include/linux/if_ether.h +++ b/datapath/linux/compat/include/linux/if_ether.h @@ -23,6 +23,10 @@ #define ETH_P_NSH 0x894F /* Network Service Header */ #endif +#ifndef ETH_P_ERSPAN +#define ETH_P_ERSPAN 0x88BE /* ERSPAN TYPE II */ +#endif + #define inner_eth_hdr rpl_inner_eth_hdr static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 149ef28..45778bd 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -21,6 +21,35 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, #define ignore_df local_df #endif + +#ifndef HAVE_NULL_COMPUTE_PSEUDO +static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto) +{ + return 0; +} +#endif + +#ifndef HAVE_SKB_CHECKSUM_CONVERT +static inline bool __skb_checksum_convert_check(struct sk_buff *skb) +{ + return (skb->ip_summed == CHECKSUM_NONE && skb->csum_valid); +} + +static inline void __skb_checksum_convert(struct sk_buff *skb, + __sum16 check, __wsum pseudo) +{ + skb->csum = ~pseudo; + skb->ip_summed = CHECKSUM_COMPLETE; +} + +#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \ +do { \ + if (__skb_checksum_convert_check(skb)) \ + __skb_checksum_convert(skb, check, \ + compute_pseudo(skb, proto)); \ +} while (0) + +#endif #ifndef HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb, const int offset, void *to, diff --git a/datapath/linux/compat/include/net/dst_metadata.h b/datapath/linux/compat/include/net/dst_metadata.h index e401eb4..93ea954 100644 --- a/datapath/linux/compat/include/net/dst_metadata.h +++ b/datapath/linux/compat/include/net/dst_metadata.h @@ -1,6 +1,11 @@ #ifndef __NET_DST_METADATA_WRAPPER_H #define __NET_DST_METADATA_WRAPPER_H 1 +enum metadata_type { + METADATA_IP_TUNNEL, + METADATA_HW_PORT_MUX, +}; + #ifdef USE_UPSTREAM_TUNNEL #include_next #else @@ -11,19 +16,26 @@ #include #include +struct hw_port_info { + struct net_device *lower_dev; + u32 port_id; +}; + struct metadata_dst { - unsigned long dst; + struct dst_entry dst; + enum metadata_type type; union { struct ip_tunnel_info tun_info; + struct hw_port_info port_info; } u; }; static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen) { - unsigned long *dst; + struct dst_entry *dst; dst = &md_dst->dst; - *dst = 0; + #if 0 dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, DST_METADATA | DST_NOCACHE | DST_NOCOUNT); @@ -105,11 +117,6 @@ void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb, struct metadata_dst *tun_dst); #ifndef HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE -enum metadata_type { - METADATA_IP_TUNNEL, - METADATA_HW_PORT_MUX, -}; - static inline struct metadata_dst * rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags) { diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h new file mode 100644 index 0000000..6c5d3a7 --- /dev/null +++ b/datapath/linux/compat/include/net/erspan.h @@ -0,0 +1,65 @@ +#ifndef USE_UPSTREAM_TUNNEL +#ifndef __LINUX_ERSPAN_H +#define __LINUX_ERSPAN_H + +/* + * GRE header for ERSPAN encapsulation (8 octets [34:41]) -- 8 bytes + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0|0|0|1|0|00000|000000000|00000| Protocol Type for ERSPAN | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (increments per packet per session) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Note that in the above GRE header [RFC1701] out of the C, R, K, S, + * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The + * other fields are set to zero, so only a sequence number follows. + * + * ERSPAN Type II header (8 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS | En|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB + */ + +#define ERSPAN_VERSION 0x1 + +#define VER_MASK 0xf000 +#define VLAN_MASK 0x0fff +#define COS_MASK 0xe000 +#define EN_MASK 0x1800 +#define T_MASK 0x0400 +#define ID_MASK 0x03ff +#define INDEX_MASK 0xfffff + +enum erspan_encap_type { + ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ + ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ + ERSPAN_ENCAP_8021Q = 0x2, /* originally 802.1Q encapsulated */ + ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ +}; + +struct erspan_metadata { + __be32 index; /* type II */ +}; + +struct erspanhdr { + __be16 ver_vlan; +#define VER_OFFSET 12 + __be16 session_id; +#define COS_OFFSET 13 +#define EN_OFFSET 11 +#define T_OFFSET 10 + struct erspan_metadata md; +}; + +#endif +#else +#include_next +#endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 764b9f1..ead86f6 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -28,11 +28,7 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #endif #else - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || \ - defined(HAVE_GRE_CISCO_REGISTER) #include_next -#endif #ifndef HAVE_GRE_CISCO_REGISTER @@ -62,6 +58,10 @@ struct gre_base_hdr { #endif /* HAVE_GRE_CISCO_REGISTER */ +#define gre_build_header rpl_gre_build_header +void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len); + int rpl_ipgre_init(void); void rpl_ipgre_fini(void); @@ -69,6 +69,10 @@ void rpl_ipgre_fini(void); struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type); +#define gre_parse_header rpl_gre_parse_header +int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool *csum_err, __be16 proto, int nhs); + #define gre_fb_xmit rpl_gre_fb_xmit netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #endif /* USE_UPSTREAM_TUNNEL */ @@ -79,4 +83,5 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); + #endif diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 68dbd7c..2685de7 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -8,6 +8,11 @@ * Only function that do not depend on ip_tunnel structure can * be used. Those needs to be explicitly defined in this header file. */ #include_next + +#ifndef TUNNEL_ERSPAN_OPT +#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) +#endif +#define ovs_ip_tunnel_encap ip_tunnel_encap #else #include @@ -18,6 +23,21 @@ #include #include #include +#include + +#ifndef MAX_IPTUN_ENCAP_OPS +#define MAX_IPTUN_ENCAP_OPS 8 +#endif + +#ifndef HAVE_TUNNEL_ENCAP_TYPES +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, +}; + +#define HAVE_TUNNEL_ENCAP_TYPES 1 +#endif #define __iptunnel_pull_header rpl___iptunnel_pull_header int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len, @@ -41,13 +61,17 @@ int ovs_iptunnel_handle_offloads(struct sk_buff *skb, */ #define iptunnel_handle_offloads rpl_iptunnel_handle_offloads struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, - bool csum_help, - int gso_type_mask); + bool csum_help, + int gso_type_mask); #define iptunnel_xmit rpl_iptunnel_xmit void rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, __be16 df, bool xnet); +#define ip_tunnel_xmit rpl_ip_tunnel_xmit +void rpl_ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, const u8 protocol); + #ifndef TUNNEL_CSUM #define TUNNEL_CSUM __cpu_to_be16(0x01) @@ -64,12 +88,17 @@ struct tnl_ptk_info { __be16 proto; __be32 key; __be32 seq; + int hdr_len; }; #define PACKET_RCVD 0 #define PACKET_REJECT 1 +#define PACKET_NEXT 2 #endif +#define IP_TNL_HASH_BITS 7 +#define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) + #ifndef TUNNEL_DONT_FRAGMENT #define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) #endif @@ -91,6 +120,9 @@ struct tnl_ptk_info { #undef TUNNEL_OPTIONS_PRESENT #define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT) +/* Keep error state on tunnel for 30 sec */ +#define IPTUNNEL_ERR_TIMEO (30*HZ) + /* Used to memset ip_tunnel padding. */ #define IP_TUNNEL_KEY_SIZE offsetofend(struct ip_tunnel_key, tp_dst) @@ -131,6 +163,30 @@ struct ip_tunnel_info { u8 mode; }; +/* 6rd prefix/relay information */ +#ifdef CONFIG_IPV6_SIT_6RD +struct ip_tunnel_6rd_parm { + struct in6_addr prefix; + __be32 relay_prefix; + u16 prefixlen; + u16 relay_prefixlen; +}; +#endif + +struct ip_tunnel_encap { + u16 type; + u16 flags; + __be16 sport; + __be16 dport; +}; + +struct ip_tunnel_prl_entry { + struct ip_tunnel_prl_entry __rcu *next; + __be32 addr; + u16 flags; + struct rcu_head rcu_head; +}; + static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info *tun_info) { return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET; @@ -203,39 +259,115 @@ ip_tunnel_dst_cache_usable(const struct sk_buff *skb, } #endif -#define ip_tunnel rpl_ip_tunnel +#define ip_tunnel_dst rpl_ip_tunnel_dst +struct rpl_ip_tunnel_dst { + struct dst_entry __rcu *dst; + __be32 saddr; +}; +#define ip_tunnel rpl_ip_tunnel struct ip_tunnel { + struct ip_tunnel __rcu *next; + struct hlist_node hash_node; struct net_device *dev; struct net *net; /* netns for packet i/o */ - int err_count; /* Number of arrived ICMP errors */ unsigned long err_time; /* Time when the last ICMP error - * arrived - */ + * arrived */ + int err_count; /* Number of arrived ICMP errors */ /* These four fields used only by GRE */ u32 i_seqno; /* The last seen seqno */ u32 o_seqno; /* The last output seqno */ int tun_hlen; /* Precalculated header length */ - int mlink; + + /* These four fields used only by ERSPAN */ + u32 index; /* ERSPAN type II index */ + u8 erspan_ver; /* ERSPAN version */ + u8 dir; /* ERSPAN direction */ + u16 hwid; /* ERSPAN hardware ID */ + + struct dst_cache dst_cache; struct ip_tunnel_parm parms; + int mlink; int encap_hlen; /* Encap header length (FOU,GUE) */ int hlen; /* tun_hlen + encap_hlen */ + struct ip_tunnel_encap encap; - int ip_tnl_net_id; - bool collect_md; + /* for SIT */ +#ifdef CONFIG_IPV6_SIT_6RD + struct ip_tunnel_6rd_parm ip6rd; +#endif + struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */ + unsigned int prl_count; /* # of entries in PRL */ + unsigned int ip_tnl_net_id; + struct gro_cells gro_cells; + __u32 fwmark; + bool collect_md; + bool ignore_df; }; #define ip_tunnel_net rpl_ip_tunnel_net struct ip_tunnel_net { + struct net_device *fb_tunnel_dev; + struct hlist_head tunnels[IP_TNL_HASH_SIZE]; struct ip_tunnel __rcu *collect_md_tun; - struct rtnl_link_ops *rtnl_ops; }; +struct ip_tunnel_encap_ops { + size_t (*encap_hlen)(struct ip_tunnel_encap *e); + int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, + const u8 *protocol, struct flowi4 *fl4); +}; + +extern const struct ip_tunnel_encap_ops __rcu * + rpl_iptun_encaps[MAX_IPTUN_ENCAP_OPS]; + +#define ip_encap_hlen rpl_ip_encap_hlen +static inline int rpl_ip_encap_hlen(struct ip_tunnel_encap *e) +{ + const struct ip_tunnel_encap_ops *ops; + int hlen = -EINVAL; + + if (e->type == TUNNEL_ENCAP_NONE) + return 0; + + if (e->type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_iptun_encaps[e->type]); + if (likely(ops && ops->encap_hlen)) + hlen = ops->encap_hlen(e); + rcu_read_unlock(); + + return hlen; +} + +static inline int ovs_ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, + const u8 *protocol, struct flowi4 *fl4) +{ + const struct ip_tunnel_encap_ops *ops; + int ret = -EINVAL; + + if (t->encap.type == TUNNEL_ENCAP_NONE) + return 0; + + if (t->encap.type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_iptun_encaps[t->encap.type]); + if (likely(ops && ops->build_header)) + ret = ops->build_header(skb, &t->encap, protocol, fl4); + rcu_read_unlock(); + + return ret; +} + #ifndef HAVE_PCPU_SW_NETSTATS #define ip_tunnel_get_stats64 rpl_ip_tunnel_get_stats64 #else @@ -322,6 +454,12 @@ struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev); #define __ip_tunnel_change_mtu rpl___ip_tunnel_change_mtu int rpl___ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); +#define ip_tunnel_lookup rpl_ip_tunnel_lookup +struct ip_tunnel *rpl_ip_tunnel_lookup(struct ip_tunnel_net *itn, + int link, __be16 flags, + __be32 remote, __be32 local, + __be32 key); + static inline int iptunnel_pull_offloads(struct sk_buff *skb) { if (skb_is_gso(skb)) { diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 4304862..3001f3f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -52,6 +52,7 @@ #include #include #include +#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -63,6 +64,10 @@ #include "vport-netdev.h" static int gre_tap_net_id __read_mostly; +static int ipgre_net_id __read_mostly; +static unsigned int erspan_net_id __read_mostly; + +static struct rtnl_link_ops ipgre_link_ops __read_mostly; #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen static int ip_gre_calc_hlen(__be16 o_flags) @@ -78,100 +83,308 @@ static int ip_gre_calc_hlen(__be16 o_flags) return addend; } -#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags -static __be16 tnl_flags_to_gre_flags(__be16 tflags) +/* Returns the least-significant 32 bits of a __be64. */ +static __be32 tunnel_id_to_key(__be64 x) { - __be16 flags = 0; - - if (tflags & TUNNEL_CSUM) - flags |= GRE_CSUM; - if (tflags & TUNNEL_ROUTING) - flags |= GRE_ROUTING; - if (tflags & TUNNEL_KEY) - flags |= GRE_KEY; - if (tflags & TUNNEL_SEQ) - flags |= GRE_SEQ; - if (tflags & TUNNEL_STRICT) - flags |= GRE_STRICT; - if (tflags & TUNNEL_REC) - flags |= GRE_REC; - if (tflags & TUNNEL_VERSION) - flags |= GRE_VERSION; +#ifdef __BIG_ENDIAN + return (__force __be32)x; +#else + return (__force __be32)((__force u64)x >> 32); +#endif +} - return flags; +/* Called with rcu_read_lock and BH disabled. */ +static int gre_err(struct sk_buff *skb, u32 info, + const struct tnl_ptk_info *tpi) +{ + return PACKET_REJECT; } -static __be64 key_to_tunnel_id(__be32 key) +static struct dst_ops md_dst_ops = { + .family = AF_UNSPEC, +}; + +#ifndef DST_METADATA +#define DST_METADATA 0x0080 +#endif + +static void rpl__metadata_dst_init(struct metadata_dst *md_dst, + enum metadata_type type, u8 optslen) + { -#ifdef __BIG_ENDIAN - return (__force __be64)((__force u32)key); -#else - return (__force __be64)((__force u64)key << 32); + struct dst_entry *dst; + + dst = &md_dst->dst; + dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, + DST_METADATA | DST_NOCOUNT); + +#if 0 + /* unused in OVS */ + dst->input = dst_md_discard; + dst->output = dst_md_discard_out; #endif + memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst)); + md_dst->type = type; } -/* Returns the least-significant 32 bits of a __be64. */ -static __be32 tunnel_id_to_key(__be64 x) +static struct metadata_dst *erspan_rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, + gfp_t flags) { -#ifdef __BIG_ENDIAN - return (__force __be32)x; -#else - return (__force __be32)((__force u64)x >> 32); -#endif + struct metadata_dst *md_dst; + + md_dst = kmalloc(sizeof(*md_dst) + optslen, flags); + if (!md_dst) + return NULL; + + rpl__metadata_dst_init(md_dst, type, optslen); + + return md_dst; +} +static inline struct metadata_dst *rpl_tun_rx_dst(int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = erspan_rpl_metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC); + if (!tun_dst) + return NULL; + + tun_dst->u.tun_info.options_len = 0; + tun_dst->u.tun_info.mode = 0; + return tun_dst; +} +static inline struct metadata_dst *rpl__ip_tun_set_dst(__be32 saddr, + __be32 daddr, + __u8 tos, __u8 ttl, + __be16 tp_dst, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = rpl_tun_rx_dst(md_size); + if (!tun_dst) + return NULL; + + ip_tunnel_key_init(&tun_dst->u.tun_info.key, + saddr, daddr, tos, ttl, + 0, 0, tp_dst, tunnel_id, flags); + return tun_dst; } -static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +static inline struct metadata_dst *rpl_ip_tun_rx_dst(struct sk_buff *skb, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + const struct iphdr *iph = ip_hdr(skb); + + return rpl__ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, + 0, flags, tunnel_id, md_size); +} + +static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, + int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst; + struct metadata_dst *tun_dst = NULL; struct ip_tunnel_net *itn; - const struct iphdr *iph; struct ip_tunnel *tunnel; + struct erspanhdr *ershdr; + const struct iphdr *iph; + __be32 session_id; + __be32 index; + int len; - if (tpi->proto != htons(ETH_P_TEB)) - return PACKET_REJECT; + itn = net_generic(net, erspan_net_id); + iph = ip_hdr(skb); + len = gre_hdr_len + sizeof(*ershdr); - itn = net_generic(net, gre_tap_net_id); + if (unlikely(!pskb_may_pull(skb, len))) + return -ENOMEM; iph = ip_hdr(skb); - tunnel = rcu_dereference(itn->collect_md_tun); + ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len); + + /* The original GRE header does not have key field, + * Use ERSPAN 10-bit session ID as key. + */ + tpi->key = cpu_to_be32(get_session_id(ershdr)); + /* OVS doesn't set tunnel key - so don't bother with it */ + tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, + tpi->flags, + iph->saddr, iph->daddr, 0); + if (tunnel) { - __be16 flags; - __be64 tun_id; - int err; - - if (iptunnel_pull_offloads(skb)) - return PACKET_REJECT; - - skb_pop_mac_header(skb); - flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); - tun_id = key_to_tunnel_id(tpi->key); - ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); - - skb_reset_network_header(skb); - err = IP_ECN_decapsulate(iph, skb); - if (unlikely(err)) { - if (err > 1) { - ++tunnel->dev->stats.rx_frame_errors; - ++tunnel->dev->stats.rx_errors; + if (__iptunnel_pull_header(skb, + gre_hdr_len + sizeof(*ershdr), + htons(ETH_P_TEB), + false, false) < 0) + goto drop; + + if (tunnel->collect_md) { + struct ip_tunnel_info *info; + struct erspan_metadata *md; + __be64 tun_id; + __be16 flags; + + tpi->flags |= TUNNEL_KEY; + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ip_tun_rx_dst(skb, flags, tun_id, sizeof(*md)); + if (!tun_dst) return PACKET_REJECT; - } + + md = ip_tunnel_info_opts(&tun_dst->u.tun_info); + md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); + + info = &tun_dst->u.tun_info; + info->key.tun_flags |= TUNNEL_ERSPAN_OPT; + info->options_len = sizeof(*md); + } + + skb_reset_mac_header(skb); + ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + kfree(tun_dst); + return PACKET_RCVD; + } +drop: + kfree_skb(skb); + return PACKET_RCVD; +} + + +static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) +{ + struct metadata_dst tun_dst; + const struct iphdr *iph; + struct ip_tunnel *tunnel; + + iph = ip_hdr(skb); + tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, + iph->saddr, iph->daddr, tpi->key); + + if (tunnel) { + if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, + raw_proto, false) < 0) + goto drop; + + if (tunnel->dev->type != ARPHRD_NONE) + skb_pop_mac_header(skb); + else + skb_reset_mac_header(skb); + if (tunnel->collect_md) { + __be16 flags; + __be64 tun_id; + + flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); + tun_id = key32_to_tunnel_id(tpi->key); + ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); } ovs_ip_tunnel_rcv(tunnel->dev, skb, &tun_dst); return PACKET_RCVD; } - return PACKET_REJECT; + return PACKET_NEXT; + +drop: + kfree_skb(skb); + return PACKET_RCVD; +} + + +static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct net *net = dev_net(skb->dev); + struct ip_tunnel_net *itn; + int res; + + if (tpi->proto == htons(ETH_P_TEB)) + itn = net_generic(net, gre_tap_net_id); + else + itn = net_generic(net, ipgre_net_id); + + res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); + if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { + /* ipgre tunnels in collect metadata mode should receive + * also ETH_P_TEB traffic. + */ + itn = net_generic(net, ipgre_net_id); + res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); + } + return res; } -static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, + __be16 proto) { - if (ipgre_rcv(skb, tpi) == PACKET_RCVD) + struct ip_tunnel *tunnel = netdev_priv(dev); + struct tnl_ptk_info tpi; + + tpi.flags = tunnel->parms.o_flags; + tpi.proto = proto; + tpi.key = tunnel->parms.o_key; + if (tunnel->parms.o_flags & TUNNEL_SEQ) + tunnel->o_seqno++; + tpi.seq = htonl(tunnel->o_seqno); + + /* Push GRE header. */ + gre_build_header(skb, &tpi, tunnel->hlen); + + ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); +} + +#ifndef HAVE_DEMUX_PARSE_GRE_HEADER +static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) +{ + struct tnl_ptk_info tpi; + bool csum_err = false; + int hdr_len; + + hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); + if (hdr_len < 0) + goto drop; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { + if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) + return 0; + } + + if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) + return 0; +drop: + + kfree_skb(skb); + return 0; +} +#else +static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *__tpi) +{ + struct tnl_ptk_info tpi = *__tpi; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { + if (erspan_rcv(skb, &tpi, 0) == PACKET_RCVD) + return 0; + goto drop; + } + + if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD) return 0; +drop: + kfree_skb(skb); return 0; } +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) /* gre_handle_offloads() has different return type on older kernsl. */ @@ -342,6 +555,83 @@ err_free_skb: } EXPORT_SYMBOL(rpl_gre_fb_xmit); +static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, + __be16 proto) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct erspan_metadata *md; + struct rtable *rt = NULL; + struct tnl_ptk_info tpi; + bool truncate = false; + struct flowi4 fl; + int tunnel_hlen; + int version; + __be16 df; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET)) + goto err_free_skb; + + key = &tun_info->key; + md = ip_tunnel_info_opts(tun_info); + if (!md) + goto err_free_rt; + + /* ERSPAN has fixed 8 byte GRE header */ + version = md->version; + tunnel_hlen = 8 + erspan_hdr_len(version); + + rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); + if (!rt) + return; + + if (gre_handle_offloads(skb, false)) + goto err_free_rt; + + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); + truncate = true; + } + + if (version == 1) { + erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), + ntohl(md->u.index), truncate, true); + tpi.hdr_len = ERSPAN_V1_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN); + } else if (version == 2) { + erspan_build_header_v2(skb, + ntohl(tunnel_id_to_key32(key->tun_id)), + md->u.md2.dir, + get_hwid(&md->u.md2), + truncate, true); + tpi.hdr_len = ERSPAN_V2_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN2); + } else { + goto err_free_rt; + } + + tpi.flags = TUNNEL_SEQ; + tpi.key = tunnel_id_to_key32(key->tun_id); + tpi.seq = htonl(tunnel->o_seqno++); + + gre_build_header(skb, &tpi, 8); + + df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; + + iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, + key->tos, key->ttl, df, false); + return; + +err_free_rt: + ip_rt_put(rt); +err_free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; +} + #define GRE_FEATURES (NETIF_F_SG | \ NETIF_F_FRAGLIST | \ NETIF_F_HIGHDMA | \ @@ -354,23 +644,27 @@ static void __gre_tunnel_init(struct net_device *dev) int t_hlen; tunnel = netdev_priv(dev); - tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->tun_hlen = ip_gre_calc_hlen(tunnel->parms.o_flags); + tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; t_hlen = tunnel->hlen + sizeof(struct iphdr); - dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; - dev->mtu = ETH_DATA_LEN - t_hlen - 4; - dev->features |= GRE_FEATURES; dev->hw_features |= GRE_FEATURES; if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { - /* TCP offload with GRE SEQ is not supported. */ - dev->features |= NETIF_F_GSO_SOFTWARE; - dev->hw_features |= NETIF_F_GSO_SOFTWARE; + /* TCP offload with GRE SEQ is not supported, nor + * can we support 2 levels of outer headers requiring + * an update. + */ + if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || + (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; + } + /* Can use a lockless transmit, unless we generate * output sequences */ @@ -378,19 +672,31 @@ static void __gre_tunnel_init(struct net_device *dev) } } -/* Called with rcu_read_lock and BH disabled. */ -static int gre_err(struct sk_buff *skb, u32 info, - const struct tnl_ptk_info *tpi) -{ - return PACKET_REJECT; -} - static struct gre_cisco_protocol ipgre_protocol = { .handler = gre_rcv, .err_handler = gre_err, .priority = 1, }; +static int __net_init ipgre_init_net(struct net *net) +{ + return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); +} + +static void __net_exit ipgre_exit_net(struct net *net) +{ + struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); + + ip_tunnel_delete_net(itn, &ipgre_link_ops); +} + +static struct pernet_operations ipgre_net_ops = { + .init = ipgre_init_net, + .exit = ipgre_exit_net, + .id = &ipgre_net_id, + .size = sizeof(struct ip_tunnel_net), +}; + static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) { __be16 flags; @@ -433,14 +739,129 @@ out: return ipgre_tunnel_validate(tb, data); } -static void ipgre_netlink_parms(struct net_device *dev, - struct nlattr *data[], - struct nlattr *tb[], - struct ip_tunnel_parm *parms) +enum { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) + IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) + IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) + IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) + IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, +#endif +}; + +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_INDEX + 1) + +static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + __be16 flags = 0; + int ret; + + if (!data) + return 0; + + ret = ipgre_tap_validate(tb, data); + if (ret) + return ret; + + /* ERSPAN should only have GRE sequence and key flag */ + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (flags != (GRE_SEQ | GRE_KEY)) + return -EINVAL; + + /* ERSPAN Session ID only has 10-bit. Since we reuse + * 32-bit key field as ID, check it's range. + */ + if (data[IFLA_GRE_IKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_OKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) + return -EINVAL; + + return 0; +} + +static int ipgre_netlink_parms(struct net_device *dev, + struct nlattr *data[], + struct nlattr *tb[], + struct ip_tunnel_parm *parms) { + struct ip_tunnel *t = netdev_priv(dev); + memset(parms, 0, sizeof(*parms)); parms->iph.protocol = IPPROTO_GRE; + + if (!data) + return 0; + + if (data[IFLA_GRE_LINK]) + parms->link = nla_get_u32(data[IFLA_GRE_LINK]); + + if (data[IFLA_GRE_IFLAGS]) + parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); + + if (data[IFLA_GRE_OFLAGS]) + parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); + + if (data[IFLA_GRE_IKEY]) + parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); + + if (data[IFLA_GRE_OKEY]) + parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); + + if (data[IFLA_GRE_LOCAL]) + parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); + + if (data[IFLA_GRE_REMOTE]) + parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); + + if (data[IFLA_GRE_TTL]) + parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); + + if (data[IFLA_GRE_TOS]) + parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); + + if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { + if (t->ignore_df) + return -EINVAL; + parms->iph.frag_off = htons(IP_DF); + } + + if (data[IFLA_GRE_COLLECT_METADATA]) { + t->collect_md = true; + if (dev->type == ARPHRD_IPGRE) + dev->type = ARPHRD_NONE; + } + + if (data[IFLA_GRE_IGNORE_DF]) { + if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) + && (parms->iph.frag_off & htons(IP_DF))) + return -EINVAL; + t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); + } + + if (data[IFLA_GRE_ERSPAN_INDEX]) { + t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + + if (t->index & ~INDEX_MASK) + return -EINVAL; + } + + return 0; } static int gre_tap_init(struct net_device *dev) @@ -462,6 +883,87 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static inline u8 tos_to_cos(u8 tos) +{ + u8 dscp, cos; + + dscp = tos >> 2; + cos = dscp >> 3; + return cos; +} + +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, bool truncate) +{ + struct iphdr *iphdr = ip_hdr(skb); + struct ethhdr *eth = eth_hdr(skb); + enum erspan_encap_type enc_type; + struct erspanhdr *ershdr; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + + enc_type = ERSPAN_ENCAP_NOVLAN; + + /* If mirrored packet has vlan tag, extract tci and + * perserve vlan header in the mirrored frame. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + enc_type = ERSPAN_ENCAP_INFRAME; + } + + skb_push(skb, sizeof(*ershdr)); + ershdr = (struct erspanhdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr)); + + ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION << VER_OFFSET)); + ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) | + (enc_type << EN_OFFSET & EN_MASK) | + ((truncate << T_OFFSET) & T_MASK)); + ershdr->md.index = htonl(index & INDEX_MASK); +} + +static netdev_tx_t erspan_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + bool truncate = false; + + if (gre_handle_offloads(skb, false)) + goto free_skb; + + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; + + if (skb->len > dev->mtu) { + pskb_trim(skb, dev->mtu); + truncate = true; + } + + /* Push ERSPAN header */ + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate); + tunnel->parms.o_flags &= ~TUNNEL_KEY; + __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); + return NETDEV_TX_OK; + +free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +} + +static netdev_tx_t __erspan_fb_xmit(struct sk_buff *skb) +{ + erspan_fb_xmit(skb, skb->dev, skb->protocol); + return NETDEV_TX_OK; +} + int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -481,9 +983,140 @@ int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(ovs_gre_fill_metadata_dst); +static int erspan_tunnel_init(struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + int t_hlen; + + tunnel->tun_hlen = 8; + tunnel->parms.iph.protocol = IPPROTO_GRE; + t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr); + + dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; + dev->mtu = ETH_DATA_LEN - t_hlen - 4; + dev->features |= GRE_FEATURES; + dev->hw_features |= GRE_FEATURES; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + return ip_tunnel_init(dev); +} + +static int ipgre_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + const void *daddr, const void *saddr, unsigned int len) +{ + struct ip_tunnel *t = netdev_priv(dev); + struct iphdr *iph; + struct gre_base_hdr *greh; + + iph = (struct iphdr *)__skb_push(skb, t->hlen + sizeof(*iph)); + greh = (struct gre_base_hdr *)(iph+1); + greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); + greh->protocol = htons(type); + + memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); + + /* Set the source hardware address. */ + if (saddr) + memcpy(&iph->saddr, saddr, 4); + if (daddr) + memcpy(&iph->daddr, daddr, 4); + if (iph->daddr) + return t->hlen + sizeof(*iph); + + return -(t->hlen + sizeof(*iph)); +} + +static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) +{ + const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); + memcpy(haddr, &iph->saddr, 4); + return 4; +} + +static const struct header_ops ipgre_header_ops = { + .create = ipgre_header, + .parse = ipgre_header_parse, +}; + +static int ipgre_tunnel_init(struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + struct iphdr *iph = &tunnel->parms.iph; + + __gre_tunnel_init(dev); + + memcpy(dev->dev_addr, &iph->saddr, 4); + memcpy(dev->broadcast, &iph->daddr, 4); + + dev->flags = IFF_NOARP; + netif_keep_dst(dev); + dev->addr_len = 4; + + if (!tunnel->collect_md) { + dev->header_ops = &ipgre_header_ops; + } + + return ip_tunnel_init(dev); +} + +static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *tnl_params; + + if (tunnel->collect_md) { + gre_fb_xmit(skb); + return NETDEV_TX_OK; + } + + if (dev->header_ops) { + /* Need space for new headers */ + if (skb_cow_head(skb, dev->needed_headroom - + (tunnel->hlen + sizeof(struct iphdr)))) + goto free_skb; + + tnl_params = (const struct iphdr *)skb->data; + + /* Pull skb since ip_tunnel_xmit() needs skb->data pointing + * to gre header. + */ + skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); + skb_reset_mac_header(skb); + } else { + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; + + tnl_params = &tunnel->parms.iph; + } + + if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) + goto free_skb; + + __gre_xmit(skb, dev, tnl_params, skb->protocol); + return NETDEV_TX_OK; + +free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +} + +static const struct net_device_ops ipgre_netdev_ops = { + .ndo_init = ipgre_tunnel_init, + .ndo_uninit = rpl_ip_tunnel_uninit, + .ndo_start_xmit = ipgre_xmit, + .ndo_change_mtu = ip_tunnel_change_mtu, + .ndo_get_stats64 = ip_tunnel_get_stats64, +#ifdef HAVE_GET_LINK_NET + .ndo_get_iflink = ip_tunnel_get_iflink, +#endif +}; + static const struct net_device_ops gre_tap_netdev_ops = { .ndo_init = gre_tap_init, - .ndo_uninit = ip_tunnel_uninit, + .ndo_uninit = rpl_ip_tunnel_uninit, .ndo_start_xmit = gre_dev_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -492,15 +1125,38 @@ static const struct net_device_ops gre_tap_netdev_ops = { #else .ndo_change_mtu = ip_tunnel_change_mtu, #endif - .ndo_get_stats64 = ip_tunnel_get_stats64, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, #ifdef HAVE_NDO_GET_IFLINK - .ndo_get_iflink = ip_tunnel_get_iflink, + .ndo_get_iflink = rpl_ip_tunnel_get_iflink, #endif #ifdef HAVE_NDO_FILL_METADATA_DST .ndo_fill_metadata_dst = gre_fill_metadata_dst, #endif }; +static const struct net_device_ops erspan_netdev_ops = { + .ndo_init = erspan_tunnel_init, + .ndo_uninit = rpl_ip_tunnel_uninit, + .ndo_start_xmit = erspan_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip_tunnel_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = rpl_ip_tunnel_get_iflink, +#endif +#ifdef HAVE_NDO_FILL_METADATA_DST + .ndo_fill_metadata_dst = gre_fill_metadata_dst, +#endif +}; + +static void ipgre_tunnel_setup(struct net_device *dev) +{ + dev->netdev_ops = &ipgre_netdev_ops; + dev->type = ARPHRD_IPGRE; + ip_tunnel_setup(dev, ipgre_net_id); +} + static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); @@ -509,6 +1165,16 @@ static void ipgre_tap_setup(struct net_device *dev) ip_tunnel_setup(dev, gre_tap_net_id); } +static void erspan_setup(struct net_device *dev) +{ + eth_hw_addr_random(dev); + ether_setup(dev); + dev->netdev_ops = &erspan_netdev_ops; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + ip_tunnel_setup(dev, erspan_net_id); +} + static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { @@ -554,6 +1220,8 @@ static size_t ipgre_get_size(const struct net_device *dev) nla_total_size(2) + /* IFLA_GRE_COLLECT_METADATA */ nla_total_size(0) + + /* IFLA_GRE_ERSPAN_INDEX */ + nla_total_size(4) + 0; } @@ -575,13 +1243,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) !!(p->iph.frag_off & htons(IP_DF)))) goto nla_put_failure; + if (t->index) + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + goto nla_put_failure; + return 0; nla_put_failure: return -EMSGSIZE; } -static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { +static const struct nla_policy ipgre_policy[RPL_IFLA_GRE_MAX + 1] = { [IFLA_GRE_LINK] = { .type = NLA_U32 }, [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, @@ -592,11 +1264,28 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { [IFLA_GRE_TTL] = { .type = NLA_U8 }, [IFLA_GRE_TOS] = { .type = NLA_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, +}; + +static struct rtnl_link_ops ipgre_link_ops __read_mostly = { + .kind = "gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = ipgre_tunnel_setup, + .validate = ipgre_tunnel_validate, + .newlink = ipgre_newlink, + .dellink = ip_tunnel_dellink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip_tunnel_get_link_net, +#endif }; static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { .kind = "ovs_gretap", - .maxtype = IFLA_GRE_MAX, + .maxtype = RPL_IFLA_GRE_MAX, .policy = ipgre_policy, .priv_size = sizeof(struct ip_tunnel), .setup = ipgre_tap_setup, @@ -610,6 +1299,22 @@ static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { #endif }; +static struct rtnl_link_ops erspan_link_ops __read_mostly = { + .kind = "erspan", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ipgre_policy, + .priv_size = sizeof(struct ip_tunnel), + .setup = erspan_setup, + .validate = erspan_validate, + .newlink = ipgre_newlink, + .dellink = ip_tunnel_dellink, + .get_size = ipgre_get_size, + .fill_info = ipgre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip_tunnel_get_link_net, +#endif +}; + struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { @@ -650,6 +1355,26 @@ out: } EXPORT_SYMBOL_GPL(rpl_gretap_fb_dev_create); +static int __net_init erspan_init_net(struct net *net) +{ + return ip_tunnel_init_net(net, erspan_net_id, + &erspan_link_ops, NULL); +} + +static void __net_exit erspan_exit_net(struct net *net) +{ + struct ip_tunnel_net *itn = net_generic(net, erspan_net_id); + + ip_tunnel_delete_net(itn, &erspan_link_ops); +} + +static struct pernet_operations erspan_net_ops = { + .init = erspan_init_net, + .exit = erspan_exit_net, + .id = &erspan_net_id, + .size = sizeof(struct ip_tunnel_net), +}; + static int __net_init ipgre_tap_init_net(struct net *net) { return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); @@ -669,6 +1394,158 @@ static struct pernet_operations ipgre_tap_net_ops = { .size = sizeof(struct ip_tunnel_net), }; +static struct net_device *erspan_fb_dev_create(struct net *net, + const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip_tunnel *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &erspan_link_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->collect_md = true; + /* Configure flow based GRE device. */ + err = ipgre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); + if (err) + goto out; + + return dev; +out: + ip_tunnel_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_erspan_vport_ops; + +static struct vport *erspan_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_erspan_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = erspan_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *erspan_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = erspan_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +#ifndef OVS_VPORT_TYPE_ERSPAN +/* Until integration is done... */ +#define OVS_VPORT_TYPE_ERSPAN 107 /* ERSPAN tunnel. */ +#endif +static struct vport_ops ovs_erspan_vport_ops = { + .type = OVS_VPORT_TYPE_ERSPAN, + .create = erspan_create, + .send = __erspan_fb_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + +static struct vport_ops ovs_ipgre_vport_ops; + +static struct vport *ipgre_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_ipgre_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *ipgre_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = ipgre_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +static struct vport_ops ovs_ipgre_vport_ops = { + .type = OVS_VPORT_TYPE_GRE, + .create = ipgre_create, + .send = gre_fb_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + int rpl_ipgre_init(void) { int err; @@ -677,22 +1554,31 @@ int rpl_ipgre_init(void) if (err < 0) goto pnet_tap_faied; + err = register_pernet_device(&erspan_net_ops); + if (err < 0) + goto pnet_erspan_failed; + + err = register_pernet_device(&ipgre_net_ops); + if (err < 0) + goto pnet_ipgre_failed; + err = gre_cisco_register(&ipgre_protocol); if (err < 0) { pr_info("%s: can't add protocol\n", __func__); goto add_proto_failed; } - err = rtnl_link_register(&ipgre_tap_ops); - if (err < 0) - goto tap_ops_failed; - pr_info("GRE over IPv4 tunneling driver\n"); + + ovs_vport_ops_register(&ovs_ipgre_vport_ops); + ovs_vport_ops_register(&ovs_erspan_vport_ops); return 0; -tap_ops_failed: - gre_cisco_unregister(&ipgre_protocol); add_proto_failed: + unregister_pernet_device(&ipgre_net_ops); +pnet_ipgre_failed: + unregister_pernet_device(&erspan_net_ops); +pnet_erspan_failed: unregister_pernet_device(&ipgre_tap_net_ops); pnet_tap_faied: pr_err("Error while initializing GRE %d\n", err); @@ -701,8 +1587,11 @@ pnet_tap_faied: void rpl_ipgre_fini(void) { - rtnl_link_unregister(&ipgre_tap_ops); + ovs_vport_ops_unregister(&ovs_erspan_vport_ops); + ovs_vport_ops_unregister(&ovs_ipgre_vport_ops); gre_cisco_unregister(&ipgre_protocol); + unregister_pernet_device(&ipgre_net_ops); + unregister_pernet_device(&erspan_net_ops); unregister_pernet_device(&ipgre_tap_net_ops); } diff --git a/datapath/linux/compat/ip_tunnel.c b/datapath/linux/compat/ip_tunnel.c index ebd1544..58870bc 100644 --- a/datapath/linux/compat/ip_tunnel.c +++ b/datapath/linux/compat/ip_tunnel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Nicira, Inc. + * Copyright (c) 2013,2018 Nicira, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -52,7 +51,6 @@ #include #include #include -#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -63,18 +61,107 @@ #include "compat.h" #ifndef USE_UPSTREAM_TUNNEL +const struct ip_tunnel_encap_ops __rcu * + rpl_iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly; + +static unsigned int rpl_ip_tunnel_hash(__be32 key, __be32 remote) +{ + return hash_32((__force u32)key ^ (__force u32)remote, + IP_TNL_HASH_BITS); +} + +static bool rpl_ip_tunnel_key_match(const struct ip_tunnel_parm *p, + __be16 flags, __be32 key) +{ + if (p->i_flags & TUNNEL_KEY) { + if (flags & TUNNEL_KEY) + return key == p->i_key; + else + /* key expected, none present */ + return false; + } else + return !(flags & TUNNEL_KEY); +} + +static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, + struct ip_tunnel_parm *parms) +{ + unsigned int h; + __be32 remote; + __be32 i_key = parms->i_key; + + if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) + remote = parms->iph.daddr; + else + remote = 0; + + if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI)) + i_key = 0; + + h = rpl_ip_tunnel_hash(i_key, remote); + return &itn->tunnels[h]; +} + static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t) { + struct hlist_head *head = ip_bucket(itn, &t->parms); + if (t->collect_md) rcu_assign_pointer(itn->collect_md_tun, t); - else - WARN_ONCE(1, "%s: collect md not set\n", t->dev->name); + hlist_add_head_rcu(&t->hash_node, head); } static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t) { if (t->collect_md) rcu_assign_pointer(itn->collect_md_tun, NULL); + hlist_del_init_rcu(&t->hash_node); +} + +static struct net_device *__ip_tunnel_create(struct net *net, + const struct rtnl_link_ops *ops, + struct ip_tunnel_parm *parms) +{ + int err; + struct ip_tunnel *tunnel; + struct net_device *dev; + char name[IFNAMSIZ]; + + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else { + if (strlen(ops->kind) > (IFNAMSIZ - 3)) { + err = -E2BIG; + goto failed; + } + strlcpy(name, ops->kind, IFNAMSIZ); + strncat(name, "%d", 2); + } + + ASSERT_RTNL(); + dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); + if (!dev) { + err = -ENOMEM; + goto failed; + } + dev_net_set(dev, net); + + dev->rtnl_link_ops = ops; + + tunnel = netdev_priv(dev); + tunnel->parms = *parms; + tunnel->net = net; + + err = register_netdevice(dev); + if (err) + goto failed_free; + + return dev; + +failed_free: + free_netdev(dev); +failed: + return ERR_PTR(err); } static inline void init_tunnel_flow(struct flowi4 *fl4, @@ -118,6 +205,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev) } if (dev->type != ARPHRD_ETHER) dev->flags |= IFF_POINTOPOINT; + + dst_cache_reset(&tunnel->dst_cache); } if (!tdev && tunnel->parms.link) @@ -162,6 +251,222 @@ int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) return rpl___ip_tunnel_change_mtu(dev, new_mtu, true); } +static int rpl_tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct rtable *rt, __be16 df, + const struct iphdr *inner_iph) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; + int mtu; + + if (df) + mtu = dst_mtu(&rt->dst) - dev->hard_header_len + - sizeof(struct iphdr) - tunnel->hlen; + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + + if (skb->protocol == htons(ETH_P_IP)) { + if (!skb_is_gso(skb) && + (inner_iph->frag_off & htons(IP_DF)) && + mtu < pkt_size) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + return -E2BIG; + } + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) { + struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); + + if (rt6 && mtu < dst_mtu(skb_dst(skb)) && + mtu >= IPV6_MIN_MTU) { + if ((tunnel->parms.iph.daddr && + !ipv4_is_multicast(tunnel->parms.iph.daddr)) || + rt6->rt6i_dst.plen == 128) { + rt6->rt6i_flags |= RTF_MODIFIED; + dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); + } + } + + if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && + mtu < pkt_size) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -E2BIG; + } + } +#endif + return 0; +} + +void rpl_ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + const struct iphdr *tnl_params, const u8 protocol) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *inner_iph; + struct flowi4 fl4; + u8 tos, ttl; + __be16 df; + struct rtable *rt; /* Route to the other host */ + unsigned int max_headroom; /* The extra header space needed */ + __be32 dst; + bool connected; + + inner_iph = (const struct iphdr *)skb_inner_network_header(skb); + connected = (tunnel->parms.iph.daddr != 0); + + dst = tnl_params->daddr; + if (dst == 0) { + /* NBMA tunnel */ + + if (skb_dst(skb) == NULL) { + dev->stats.tx_fifo_errors++; + goto tx_error; + } + + if (skb->protocol == htons(ETH_P_IP)) { + rt = skb_rtable(skb); + dst = rt_nexthop(rt, inner_iph->daddr); + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) { + const struct in6_addr *addr6; + struct neighbour *neigh; + bool do_tx_error_icmp; + int addr_type; + + neigh = dst_neigh_lookup(skb_dst(skb), + &ipv6_hdr(skb)->daddr); + if (neigh == NULL) + goto tx_error; + + addr6 = (const struct in6_addr *)&neigh->primary_key; + addr_type = ipv6_addr_type(addr6); + + if (addr_type == IPV6_ADDR_ANY) { + addr6 = &ipv6_hdr(skb)->daddr; + addr_type = ipv6_addr_type(addr6); + } + + if ((addr_type & IPV6_ADDR_COMPATv4) == 0) + do_tx_error_icmp = true; + else { + do_tx_error_icmp = false; + dst = addr6->s6_addr32[3]; + } + neigh_release(neigh); + if (do_tx_error_icmp) + goto tx_error_icmp; + } +#endif + else + goto tx_error; + + connected = false; + } + + tos = tnl_params->tos; + if (tos & 0x1) { + tos &= ~0x1; + if (skb->protocol == htons(ETH_P_IP)) { + tos = inner_iph->tos; + connected = false; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); + connected = false; + } + } + + init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, + tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); + + if (ovs_ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) + goto tx_error; + + rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) : + NULL; + + if (!rt) { + rt = ip_route_output_key(tunnel->net, &fl4); + + if (IS_ERR(rt)) { + dev->stats.tx_carrier_errors++; + goto tx_error; + } + if (connected) + dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, + fl4.saddr); + } + + if (rt->dst.dev == dev) { + ip_rt_put(rt); + dev->stats.collisions++; + goto tx_error; + } + + if (rpl_tnl_update_pmtu(dev, skb, rt, + tnl_params->frag_off, inner_iph)) { + ip_rt_put(rt); + goto tx_error; + } + + if (tunnel->err_count > 0) { + if (time_before(jiffies, + tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { + tunnel->err_count--; + + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + dst_link_failure(skb); + } else + tunnel->err_count = 0; + } + + tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); + ttl = tnl_params->ttl; + if (ttl == 0) { + if (skb->protocol == htons(ETH_P_IP)) + ttl = inner_iph->ttl; +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) + ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; +#endif + else + ttl = ip4_dst_hoplimit(&rt->dst); + } + + df = tnl_params->frag_off; + if (skb->protocol == htons(ETH_P_IP)) + df |= (inner_iph->frag_off&htons(IP_DF)); + + max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + + rt->dst.header_len; + if (max_headroom > dev->needed_headroom) + dev->needed_headroom = max_headroom; + + if (skb_cow_head(skb, dev->needed_headroom)) { + ip_rt_put(rt); + dev->stats.tx_dropped++; + kfree_skb(skb); + return; + } + + iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol, + tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); + + return; + +#if IS_ENABLED(CONFIG_IPV6) +tx_error_icmp: + dst_link_failure(skb); +#endif +tx_error: + dev->stats.tx_errors++; + kfree_skb(skb); +} +EXPORT_SYMBOL_GPL(rpl_ip_tunnel_xmit); + static void ip_tunnel_dev_free(struct net_device *dev) { free_percpu(dev->tstats); @@ -183,24 +488,63 @@ int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, struct rtnl_link_ops *ops, char *devname) { struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); + struct ip_tunnel_parm parms; + unsigned int i; - itn->collect_md_tun = NULL; - itn->rtnl_ops = ops; - return 0; + for (i = 0; i < IP_TNL_HASH_SIZE; i++) + INIT_HLIST_HEAD(&itn->tunnels[i]); + + if (!ops) { + itn->fb_tunnel_dev = NULL; + return 0; + } + + memset(&parms, 0, sizeof(parms)); + if (devname) + strlcpy(parms.name, devname, IFNAMSIZ); + + rtnl_lock(); + itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); + /* FB netdevice is special: we have one, and only one per netns. + * * Allowing to move it to another netns is clearly unsafe. + * */ + if (!IS_ERR(itn->fb_tunnel_dev)) { + itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); + ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); + } + rtnl_unlock(); + + return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev); } static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, struct rtnl_link_ops *ops) { - struct ip_tunnel *t; - - t = rtnl_dereference(itn->collect_md_tun); - if (!t) - return; - unregister_netdevice_queue(t->dev, head); + struct net *net = dev_net(itn->fb_tunnel_dev); + struct net_device *dev, *aux; + int h; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == ops) + unregister_netdevice_queue(dev, head); + + for (h = 0; h < IP_TNL_HASH_SIZE; h++) { + struct ip_tunnel *t; + struct hlist_node *n; + struct hlist_head *thead = &itn->tunnels[h]; + + hlist_for_each_entry_safe(t, n, thead, hash_node) + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, head); + } } -void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops) +void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, + struct rtnl_link_ops *ops) { LIST_HEAD(list); @@ -251,20 +595,41 @@ int rpl_ip_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; + int err; - dev->destructor = ip_tunnel_dev_free; - dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = ip_tunnel_dev_free; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip_tunnel_dev_free; +#endif + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + + err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (err) { + free_percpu(dev->tstats); + return err; + } + + err = gro_cells_init(&tunnel->gro_cells, dev); + if (err) { + dst_cache_destroy(&tunnel->dst_cache); + free_percpu(dev->tstats); + return err; + } + tunnel->dev = dev; tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); iph->version = 4; iph->ihl = 5; - if (tunnel->collect_md) + if (tunnel->collect_md) { dev->features |= NETIF_F_NETNS_LOCAL; - + netif_keep_dst(dev); + } return 0; } @@ -300,4 +665,94 @@ struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev) return tunnel->net; } +struct ip_tunnel *rpl_ip_tunnel_lookup(struct ip_tunnel_net *itn, + int link, __be16 flags, + __be32 remote, __be32 local, + __be32 key) +{ + unsigned int hash; + struct ip_tunnel *t, *cand = NULL; + struct hlist_head *head; + + hash = rpl_ip_tunnel_hash(key, remote); + head = &itn->tunnels[hash]; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (local != t->parms.iph.saddr || + remote != t->parms.iph.daddr || + !(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else + cand = t; + } + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (remote != t->parms.iph.daddr || + t->parms.iph.saddr != 0 || + !(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + + hash = rpl_ip_tunnel_hash(key, 0); + head = &itn->tunnels[hash]; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && + (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) + continue; + + if (!(t->dev->flags & IFF_UP)) + continue; + + if (!rpl_ip_tunnel_key_match(&t->parms, flags, key)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + + if (flags & TUNNEL_NO_KEY) + goto skip_key_lookup; + + hlist_for_each_entry_rcu(t, head, hash_node) { + if (t->parms.i_key != key || + t->parms.iph.saddr != 0 || + t->parms.iph.daddr != 0 || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->parms.link == link) + return t; + else if (!cand) + cand = t; + } + +skip_key_lookup: + if (cand) + return cand; + + if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP) + return netdev_priv(itn->fb_tunnel_dev); + + + return NULL; +} +EXPORT_SYMBOL_GPL(rpl_ip_tunnel_lookup); + #endif diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index 7ade6c1..90e838a 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -129,6 +129,47 @@ error: } EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads); +struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, + bool csum_help, + int gso_type_mask) +{ + int err; + + if (likely(!skb->encapsulation)) { + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } + + if (skb_is_gso(skb)) { + err = skb_unclone(skb, GFP_ATOMIC); + if (unlikely(err)) + goto error; + skb_shinfo(skb)->gso_type |= gso_type_mask; + return skb; + } + + /* If packet is not gso and we are resolving any partial checksum, + * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL + * on the outer header without confusing devices that implement + * NETIF_F_IP_CSUM with encapsulation. + */ + if (csum_help) + skb->encapsulation = 0; + + if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) { + err = skb_checksum_help(skb); + if (unlikely(err)) + goto error; + } else if (skb->ip_summed != CHECKSUM_PARTIAL) + skb->ip_summed = CHECKSUM_NONE; + + return skb; +error: + kfree_skb(skb); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(rpl_iptunnel_handle_offloads); + int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto, bool raw_proto, bool xnet) { From patchwork Fri May 18 01:57:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915934 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="ECdqNVxM"; 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 40nBDw1vjNz9s37 for ; Fri, 18 May 2018 11:59:28 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 50C90F78; Fri, 18 May 2018 01:58:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D4CC0F06 for ; Fri, 18 May 2018 01:58:25 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f68.google.com (mail-pl0-f68.google.com [209.85.160.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 612F3196 for ; Fri, 18 May 2018 01:58:25 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id c19-v6so3630527pls.6 for ; Thu, 17 May 2018 18:58:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3AhCPdXExstoJPOCSXgFhWRbkNt9zropDNLIUUxWUUY=; b=ECdqNVxMQTo4xifUGacgcLZcLEUM8LFQb2OeHdw78mv4cHbJWnGyu9Sq0TG24/VVz3 7ICPSs9sP/NOXFfOYlKnJkKXF9Eay1Ev39rf5TG7WTbtARvMqgQhUq389IfqjQkRy20u KI8+IYAFzI3xfHHOkb9vJC6lEB4UnWH4Lw4uex9+3FpSR0klJ3Y7pAOY7JgQp7XS61T7 svYWhdijLDfAnAswxEGNZdD1o+j10nXeCKh4FOLqoOAkr2+NByZGste6EhHroG+c0sRM yZJPIGGrLXAH1JM4Mlvf+L9jJxR0eod1K+flS5DET1w3kDzNAKW44YmXVFDgsm/ggkoO mHCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3AhCPdXExstoJPOCSXgFhWRbkNt9zropDNLIUUxWUUY=; b=t2e/TGYHs7w5ogRNLepL581kwFtYl1H4mfidY4m0aVAhlYG3DR12Gk7M2wFU/LkC27 F++x/dhpjKl94BTXxLHTascbOHhOHzCJWPDHhvKUk7fe0/1nF+H50HoF4UR3LXJjf/IZ rSxKhXZ05kd6SeTv5CNJy/Wo9Nmpm4CanGahSONkYqxRw3r4UcBruqIfJGjqoajQz+9E l2+X40ErzGjM5xxir1h+PyO62YTnwaO3YpJOYAu6axWOGPrZCOodvMlDmq34etAiz9oY 93DltxyTjYk5I48GSilvu43G3etxGveXwZhcO/8/EwpCkRtkMqhl1uP8X8JH8UhFEKm2 gO6A== X-Gm-Message-State: ALKqPweu047wkoCYqhtWoIDqUgqpupAq+3EdJRlPWzEKY07yChxo9nvw CA+PTfHNOnn9YFLWUslrVlUsZg== X-Google-Smtp-Source: AB8JxZpcbVnCEMyBlDsORSTyWVhES0dDQbTaIhQUbj1nBAqs8zTsQzoTgHhCcapDjU0WKLgjPuHSzA== X-Received: by 2002:a17:902:28a7:: with SMTP id f36-v6mr7494176plb.155.1526608704747; Thu, 17 May 2018 18:58:24 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:24 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:16 -0700 Message-Id: <1526608674-12702-4-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 03/41] 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 3001f3f..3bd6e92 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1552,7 +1552,7 @@ int rpl_ipgre_init(void) err = register_pernet_device(&ipgre_tap_net_ops); if (err < 0) - goto pnet_tap_faied; + goto pnet_tap_failed; err = register_pernet_device(&erspan_net_ops); if (err < 0) @@ -1580,7 +1580,7 @@ pnet_ipgre_failed: unregister_pernet_device(&erspan_net_ops); pnet_erspan_failed: unregister_pernet_device(&ipgre_tap_net_ops); -pnet_tap_faied: +pnet_tap_failed: pr_err("Error while initializing GRE %d\n", err); return err; } From patchwork Fri May 18 01:57:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915935 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="hhmcQpQd"; 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 40nBFX0jBhz9s1w for ; Fri, 18 May 2018 12:00:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6F61B101B; Fri, 18 May 2018 01:58:30 +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 97664A59 for ; Fri, 18 May 2018 01:58:26 +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 490586DB for ; Fri, 18 May 2018 01:58:26 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id q22-v6so2956430pff.11 for ; Thu, 17 May 2018 18:58:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4n0nesw0F3u/hOaK6QQCezt7Am7mNS4v8hfUTzSw1h0=; b=hhmcQpQdWUiU28XnpCZUBJ4ZhACHwA0arecv/B16zZm2BuTHUHX5S+EW7kHs5MpL07 +6vHwN8P44uTvS8cq1KZ3dGzSHJ1fL/A+8+eNhHjbGF024JVl7oyIRQYI+XbLGDjhjd+ Du25pcJuRGB86/UmsOsO7ApFNzkLdDckRAaJMiGsCvQWul+Hev3N9VVP7JFtPKe+W5f4 Cwe2/VQ/qAYuubOtgCQEBFl8KGZ2WIUR4D67bk9OTF+62rXbWkut9VsAt95LuBmDRCRr RAk8r+tavpX3KpPfCcWudhYLuBSsgbs8nXiO6Uz8IjfHosUHBLAiPum3HVxR5B63hcjA y9YQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4n0nesw0F3u/hOaK6QQCezt7Am7mNS4v8hfUTzSw1h0=; b=mpOWO6o1TMLgc14EgVBFeJSKQpI5/6t33XoZ/7UnneXly+4HlNdj+v9qKtO7Qrdux5 3d716KFLdsaqd8EBWZxGHlJpqL9Xz/AhEKhO5n28I3dtLDruj/sat3bawTo93qUUqccL RR1TvifncIeMu3vrvtcTTyg/Sq063zJ0NBr5Kr6G/AgsP7XvqnLwEMrpWPuD4ZuPkJ8T wj5A4j1rNUGkqOzLeXRBLd+aYdW1fr9fnNnC6i23YO0ImO9Ya5eEt5XXtQMIVGDBBgCo oxUOkXQv69R9XIv1P1iFKNkvpcIMhUEaaisMChc8p10pYtXhf0p+c/iZnKQJru8jwRCM XWhA== X-Gm-Message-State: ALKqPwd93OY5hrcTQiaMDU3G8Dmxzf8JJLBMcHNPcku8yB5wRLDdr7qg Xh0yCeMwE1/ZKaZ2iLrPNHjhWg== X-Google-Smtp-Source: AB8JxZoby8MmiCSq4SPeMJIBMiH5QUuqkTBqbD5BWgigqfUGyhAP1H09pU/emsANVJxuRY4EziD8tA== X-Received: by 2002:a63:6887:: with SMTP id d129-v6mr5989997pgc.128.1526608705636; Thu, 17 May 2018 18:58:25 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:25 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:17 -0700 Message-Id: <1526608674-12702-5-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 04/41] 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 3bd6e92..e30e428 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -488,6 +488,54 @@ static struct rtable *gre_get_rt(struct sk_buff *skb, return ip_route_output_key(net, fl); } +static struct rtable *prepare_fb_xmit(struct sk_buff *skb, + struct net_device *dev, + struct flowi4 *fl, + int tunnel_hlen) +{ + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct rtable *rt = NULL; + int min_headroom; + bool use_cache; + int err; + + tun_info = skb_tunnel_info(skb); + key = &tun_info->key; + use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); + + if (use_cache) + rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr); + if (!rt) { + rt = gre_get_rt(skb, dev, fl, key); + if (IS_ERR(rt)) + goto err_free_skb; + if (use_cache) + dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, + fl->saddr); + } + + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + + tunnel_hlen + sizeof(struct iphdr); + if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { + int head_delta = SKB_DATA_ALIGN(min_headroom - + skb_headroom(skb) + + 16); + err = pskb_expand_head(skb, max_t(int, head_delta, 0), + 0, GFP_ATOMIC); + if (unlikely(err)) + goto err_free_rt; + } + return rt; + +err_free_rt: + ip_rt_put(rt); +err_free_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return NULL; +} + netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb) { struct net_device *dev = skb->dev; From patchwork Fri May 18 01:57:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915936 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="YjoyuLwW"; 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 40nBG55Q4bz9s1w for ; Fri, 18 May 2018 12:00:29 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7607F101D; Fri, 18 May 2018 01:58:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 02679F14 for ; Fri, 18 May 2018 01:58:28 +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 571776F8 for ; Fri, 18 May 2018 01:58:27 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id x9-v6so2967806pfm.2 for ; Thu, 17 May 2018 18:58:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=edeez9fy38gf9EZLZKIZcll5SBU3o48OpsQqTqCa8i0=; b=YjoyuLwW8bRH+ZY/fICwuftqomSt72GPNRBgIzUJ6NmNtDCRCF0eN4/KXg12dGFkVh gG84NK3te+Dq1rg+rsodFNkmwTUroyn2R4QtVtkLQgOZE2WmPFSXngvWaZdK/h5wSU5r ttcdCpHcm4NBXPXDEFwEkwifrh3U2viFe/7TzlJZMUHohYzX63Lx2svaJ5663PMloFvW mIfcVzCySMh/TvvE+dIZW3VkAB47aItR+EIUsl3FSmRo2sTFnToCGH+rwv2XLoAW91BZ vKLxoH6LqzqsqNpR3q1ILHFWjHyRBxarGaDfNcsjPDU1QAX0u+f12URdoHb4c0JBOpW2 bGIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=edeez9fy38gf9EZLZKIZcll5SBU3o48OpsQqTqCa8i0=; b=pJmbUmEPVrUFsis7arkArlm0eZqC6gEhnuJ3LuKYUExZYujNNjtd/jrTtUlU1AJaQr ZgncrpItdl5Z8nhQlKplLvpaHStEs9zx5qyeGv4V+84NdjDgYEINBaxzCvUgA+k20kOK 20yKEDyDQAzn+gQMGwXGTeU5oMW4NXKpyHG5MRSNL9dckyBss81R+Bu/aBX1Q2wFyo3G v412iuR0+coWzUA03lolesWo1e2JW25hCIYM7g6lEV5ePtM+dv0DOgPotBhujTL6YNkP JxPc7zEW9CFedudlayvW1Tia6vKKB5Mrxlr2ouosbFqsvntczLx62oispisZ5Llp3x5S b47g== X-Gm-Message-State: ALKqPwcuxPorTW+RRksRtMbi9bd5qmFCg5IfUZyi1lxLwOP1RgHFe3BP 3uoGbuB5qskmyN2DbTABsYTTSA== X-Google-Smtp-Source: AB8JxZp79bJiAQITOcHgecCCWW66Q3CrVUss03dfA7yHBXb37pKFRVaapw/qRT413Xe5GSObOnF0ag== X-Received: by 2002:a65:4a87:: with SMTP id b7-v6mr5868656pgu.271.1526608706657; Thu, 17 May 2018 18:58:26 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:26 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:18 -0700 Message-Id: <1526608674-12702-6-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 05/41] 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 e30e428..a5ec59c 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -93,6 +93,9 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, bool truncate); + /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) @@ -187,7 +190,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst *tun_dst = NULL; + struct metadata_dst tun_dst; struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; struct erspanhdr *ershdr; @@ -823,18 +826,17 @@ static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) return ret; /* ERSPAN should only have GRE sequence and key flag */ - flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); - flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); - if (flags != (GRE_SEQ | GRE_KEY)) + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (!data[IFLA_GRE_COLLECT_METADATA] && + flags != (GRE_SEQ | GRE_KEY)) return -EINVAL; /* ERSPAN Session ID only has 10-bit. Since we reuse * 32-bit key field as ID, check it's range. */ - if (data[IFLA_GRE_IKEY] && - (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) - return -EINVAL; - if (data[IFLA_GRE_OKEY] && (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) return -EINVAL; @@ -983,6 +985,11 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, struct ip_tunnel *tunnel = netdev_priv(dev); bool truncate = false; + if (tunnel->collect_md) { + erspan_fb_xmit(skb, dev, skb->protocol); + return NETDEV_TX_OK; + } + if (gre_handle_offloads(skb, false)) goto free_skb; From patchwork Fri May 18 01:57:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915937 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="dVOb3oAT"; 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 40nBGh6zpZz9s1w for ; Fri, 18 May 2018 12:01:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 621A01050; Fri, 18 May 2018 01:58:32 +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 D0522A59 for ; Fri, 18 May 2018 01:58:28 +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 65E1B6F3 for ; Fri, 18 May 2018 01:58:28 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id l2-v6so2603798pgc.7 for ; Thu, 17 May 2018 18:58:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5ZYWYIQnLYcN5JRanLVr/Od++GuLKbBc+0VVprZvyv0=; b=dVOb3oATVaJty4hmHgSkIl0G9InpSV+zCQxQYZB8ymVUEKP5rhLU/uTAEMXm2HYkWt ACqkRQyjTzfzveUUoV+0KO8MGu0MQjChzsE2SGAL/Nbt52u5A4Vnlu11kII20nReMnPy F1dAUqY7aZrhFbC0eLpt4fDMUttb5F6kbCUl6iiwoCpykLDsAugIn/Lm6IcvMXXAZJm4 0+41SdLD4dpYlSNrPfe9qfOyI23l64qXOw6rki+yBoaPahoabm+e8/5XKTsWMwMPlrGL SsJ5XdFhqYWlVVdmjs7Uf0towCKN0BSe9nNOfWfDzPxn+0ElskfBj6Td00ZyArSQ7Xho KadQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5ZYWYIQnLYcN5JRanLVr/Od++GuLKbBc+0VVprZvyv0=; b=s6AFR5r4e4gImxngwJnY3c4NqvdArjupkf35XGBpaJp87wCzi71BuqxZKjKFMhdS96 48O+JumLwtOi7rNtF5CndCYEisAXLcRQiJOKNoAQONz6IjHi+Klp5Qj4RAPTJEhgpVZu olVkgVaNyB4a0SEmccTpFB/W7CiopzN32K0oTAbmOAzdCMvk72beVdLHzYE+mNCwe6/4 TSRZ+0LhuNhlnCyxujyeIIwsqznI1lxUx6xx9djdzex6MaAkYtruE4ZKyhOsRMdKm725 j9oCSWvgVSQISiM5mgN7FqyeWxyCXHv2v4ChPW3yhDWVTeYx+edaBHLuN+5bQMwKDIaN rmCw== X-Gm-Message-State: ALKqPwef8hSckGCpRosUNrkbOWGjMqvvVpmcD0Vpp0Vci5c2KYos3HuH m7qB1gU2ew/De2cTDZ0XTxWTzQ== X-Google-Smtp-Source: AB8JxZqpDEN+EXezHaGS6NEM1X25mtX9S4UcWNA1QBbdi874hwfQb0MSph5iihkohN9s18zCvaV6iw== X-Received: by 2002:a63:a06a:: with SMTP id u42-v6mr5625478pgn.389.1526608707657; Thu, 17 May 2018 18:58:27 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:27 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:19 -0700 Message-Id: <1526608674-12702-7-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 06/41] 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 a5ec59c..77d430e 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -996,8 +996,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, if (skb_cow_head(skb, dev->needed_headroom)) goto free_skb; - if (skb->len > dev->mtu) { - pskb_trim(skb, dev->mtu); + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); truncate = true; } From patchwork Fri May 18 01:57:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915938 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="bSzhLUy1"; 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 40nBHD2HFgz9s37 for ; Fri, 18 May 2018 12:01:28 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 60C281054; Fri, 18 May 2018 01:58:33 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 03526F5D for ; Fri, 18 May 2018 01:58:30 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B58AA6F3 for ; Fri, 18 May 2018 01:58:29 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id c11-v6so3630868plr.5 for ; Thu, 17 May 2018 18:58:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+4gwZ/YT8fTkXmnFJi/mh4xs6by5eXesmR5SjzufJb0=; b=bSzhLUy1DBDDksZBefjZTi3jDiNhlvP261Gj8T+BpwiuaeKsJYMK7WTckd0ips2Saz 9Xid0yFfyZXvb2hDfxSgXFz25AvNTGTUV3fE4bwYHCjo2NlZPdHxu9hFPXjYlazFcqGv y3DDPAcfOvDSbaGmG2BUBZ2aafRXxGgHvrKqDAJIJjCY0qjiM+IiJbCgaS0b40+3VZHA HC87ECQnU1g1O36c75Mi++A7PcxPyAZkZ+CngGNTtbhCuuIokaQ483dh1hKQv5l4AJMs N80dTXx8Kl3ZckTnyQs3pCmD3v6iDlB65/WorUNFdohA16c/XxjRrtaGbI8cDFpOawAg UUow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+4gwZ/YT8fTkXmnFJi/mh4xs6by5eXesmR5SjzufJb0=; b=QGOeTlrxUHUYZQU58Qx0Rz9KhWumJEiDWgOpYYP05xrH9U9M9zOxP01Xo7Fl8Slr8a waD0ctJe2qEX4ih8U1i3oQFaGAduEPTRBOS3s2Ceyxb8ehBBu9YlWJ3W2XgfOJ5gzDtw Zx2LPauBtrpof88d0vGGdksTw0adh3il7ztg7Nr8/kAvxrLRIZEkEP5iFKogSg/YNmq1 shZSX/JcLudrTzgYUFGPhpbdfgybiAJHHa2hpnLVxIdAdVtmiy1LLOEaQkNX1UXGcmbc UaMX+2lynSqzFmsxTp+sf5i2uvx8qT02XWBXjH1S9zLUIl+1kvBivjK014dhztFbmtpY OA3w== X-Gm-Message-State: ALKqPwcrMJDY64w3aaSUof3/zQBeiF6+x68yiin3vscBjSLwoUHpF189 YAT9P02PfyLGn1NkYb6cFJ96rA== X-Google-Smtp-Source: AB8JxZqk3GrGB51btRfhK4Yj0VGkCdOU2CKG0YpPXRpjHlBUd76wQISxWCdKWE2aL3UKtnxChfDVVQ== X-Received: by 2002:a17:902:8f97:: with SMTP id z23-v6mr7611746plo.329.1526608709109; Thu, 17 May 2018 18:58:29 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:28 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:20 -0700 Message-Id: <1526608674-12702-8-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 07/41] 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 77d430e..1a8dc76 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -195,7 +195,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, struct ip_tunnel *tunnel; struct erspanhdr *ershdr; const struct iphdr *iph; - __be32 session_id; __be32 index; int len; From patchwork Fri May 18 01:57:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915941 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="cYYQIT5s"; 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 40nBJQ1J7Wz9s1w for ; Fri, 18 May 2018 12:02:30 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 14FFB1056; Fri, 18 May 2018 01:58:37 +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 43646FF1 for ; Fri, 18 May 2018 01:58:31 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id EE456196 for ; Fri, 18 May 2018 01:58:30 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id w19-v6so3630458plq.4 for ; Thu, 17 May 2018 18:58:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DAP8s1FTQPQd2Sl1OV9NRPCXD6MxrYhzc5r6pMbggc8=; b=cYYQIT5smG+0cQ2x8F+XXGMegAuws+BFJnZHe+qJ7dWMdbGWtJfeNGpUTuArW6m5Ci C27yV7McayiYJSs0nSmh/wQxBdRA7AzwNvRDl5ElGka+iMG/S9yFxqZ01tAhW6z1wcGn vLbeeVgYDNfMYDRZs8wfDfN9leUdc+ExpQSoa888P0a9IZCVT3Q4wNufVxk5HpM0yWNs ukk7V6aFRcJ/FXeutrh1sFYhNk6qLANVnhe6CBUCNn+CbReZ1nfjUuU7TMY4iUmoEm4H cOoNRwSCmPnJ1AfpnD6jybWzMMUbj9mJmmtwTprTK1hmZOxlLrl57eToQgVAHly7SRiD 7q3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DAP8s1FTQPQd2Sl1OV9NRPCXD6MxrYhzc5r6pMbggc8=; b=LFsCQ8UzpLJPt1yC9bxo9TcCQ82hMkf0+3VGfs8h66a+AodRGeAIwYYP4MmM9HhpCd u7b42Mr6KKQ9UZtGZAYyPFspVY6x9PLqobt3UooYHcoCH06QdK7vTvm0u9nNySFl+9an O7a+/I7UgsiZGR5UW0fdVc8vOdEcJEOEcKR5qnGc8aM6KT8dF3a58Ad5gpNcjoPtDXih geW521iaVmIgJ15U5eI7gMK/yBEQ+9NuGImbynYV2l2iyGfhgU92wjodyo8DEfWliwbE 99zdPQyXdp+2nDlIwroF4qLtEwDIbdjSvwr1DMWIGOHaIqDlhHP0AlQb68UO8cyxG0cb bMaw== X-Gm-Message-State: ALKqPwf//724Td+3vn1n/xhpYVq0x/1PS9jwmcBAFHpclNri8fuBhEY4 PkM7BwTNUjw2LNXms+hzIMUirQ== X-Google-Smtp-Source: AB8JxZoQvvsyDnhFz5GpXSMP1Lubxbyk0U1fi+zVPFO7eutzJ5ur0eTHib3ylyujHxKZqyht/yyTsQ== X-Received: by 2002:a17:902:462:: with SMTP id 89-v6mr7403733ple.300.1526608710345; Thu, 17 May 2018 18:58:30 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:29 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:21 -0700 Message-Id: <1526608674-12702-9-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 08/41] 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 1a8dc76..70c6a9f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1044,7 +1044,9 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; - t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr); + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + + sizeof(struct erspanhdr); + t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; dev->mtu = ETH_DATA_LEN - t_hlen - 4; From patchwork Fri May 18 01:57:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915942 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="P8bu3cHG"; 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 40nBK069KJz9s37 for ; Fri, 18 May 2018 12:03:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8590F10A2; Fri, 18 May 2018 01:58:38 +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 791EF1054 for ; Fri, 18 May 2018 01:58:32 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 443956DB for ; Fri, 18 May 2018 01:58:32 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id n10-v6so3632459plp.0 for ; Thu, 17 May 2018 18:58:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=yENfHRcWPB6V05ndWQ5og4kMvSKNSF6aw52F6qH+O4s=; b=P8bu3cHGuz/gnUJqYJxE6CXffeiNCiWArrah9/6rasxh3mExhu0VLw2dD+lwUGgzl0 c9M5+gm6i1dutBlQRHvLRr01SJi6iov2UlwCHCn/qoLFxM5Gz65USsYRG6a7caJkUvjH 7bG4FqmODHKF3UDkU4LXOskJtvc5sJ/LhKHDOVsBgCda4oy1DUiTXyK0XSdd3p+3077I XJgoS6ipkeLFsue3u8snhilxs3c6+7qivcXYh4reRJTWznfQhQI/EJA+u9DcZm0QFAIM vwwlI/lAGGo9qFMMNcqowJlzAVwrMg3AAbMjDB6Bo8uqQqbN6HA0Yd2izkDPLtHxUVnq sPxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=yENfHRcWPB6V05ndWQ5og4kMvSKNSF6aw52F6qH+O4s=; b=GBszQuDSj6yROBsWCOmPibnUOFrPQYr1vfBNsrQaewliOYfjb1uvVoXWwr63JEtb/e sNPKN4TWMTle9N2PCXxNbPvatOaF2RCnM/IAnbH/DSUADzMwr6lKtIv8T7Ud7VcAW5mq EZXC5dH/Tmw6yDqd9oZydE0ITI67EUjgEkeggY+9s0hq1aAG3OdShLwO+Mk+Zz28hclP 5lUGoKVAxCBoqr5fsAYVpWKl9UnuV9usFme2yafkrvUTtk8N2Wx6CQaU/kCzv1tFMNae pm4cb88tmWqcB+04bff1NqHwYQFUCmOvhUoAIbHLKFdt6ZqfDUK+lhEK9oWR2OxXUK7N O7Tg== X-Gm-Message-State: ALKqPwemzjgULgapcTGsfGCDAFXF5pkZdBbUxuiGslteWv46lOr9od/m LBkdZKv59wOmaxE0g8JtHVNWkA== X-Google-Smtp-Source: AB8JxZqEWWnLwTiiR0LxsnZa4F0IqTPxw80hUaaVqBfhaTO/ulirPUjosb2aML/CCVkY7T32jWdFIg== X-Received: by 2002:a17:902:a717:: with SMTP id w23-v6mr7473965plq.130.1526608711648; Thu, 17 May 2018 18:58:31 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:31 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:22 -0700 Message-Id: <1526608674-12702-10-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 09/41] 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 70c6a9f..19e78af 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1053,6 +1053,7 @@ static int erspan_tunnel_init(struct net_device *dev) dev->features |= GRE_FEATURES; dev->hw_features |= GRE_FEATURES; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); return ip_tunnel_init(dev); } From patchwork Fri May 18 01:57:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915946 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="kNqWmn3p"; 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 40nBKc5NPbz9s3B for ; Fri, 18 May 2018 12:03:32 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5E27310AC; Fri, 18 May 2018 01:58:40 +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 DA994105F for ; Fri, 18 May 2018 01:58:33 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f68.google.com (mail-pl0-f68.google.com [209.85.160.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7498A6DB for ; Fri, 18 May 2018 01:58:33 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id v24-v6so3631951plo.3 for ; Thu, 17 May 2018 18:58:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=babftoUnK0pk26h1AJsGLjEqIvzFlZ3FZ7vywR6MyU0=; b=kNqWmn3pfdNU/gRL10Skx7IizeepK2CGs0QsQXw4FPb+pXNv8s2ofJcwp46y2Lhcn4 DIRhldyDGdQz/Ee+gTxoL1NxgyUQ0MdhmqtWIRGmaBtjEkEtpd3jieYqosD5yMmeDaYc Tal09QZVGkrUP4/gaDwbOTGNi+xCfmBynJm2VfZqM//SEPi6hJRaTDyxWsXHtlnSqdMA SoACWzjHleaUZsZmEhIB2nhEcHcvLLb/fdCriYKVLNMazCqNVIOnqOsHwHHRR8g3Ahcd AerKYPFrxhbkYD7h+mN8t4daED8eFeYe2zTeu+earBBdH3Cxn+7ojaqyezV0B0//A8O+ fNTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=babftoUnK0pk26h1AJsGLjEqIvzFlZ3FZ7vywR6MyU0=; b=m0vLhxGAh8KQmq7DvMZF1KQl/m9X4YKkoxkTRUm3oaZJiHb+jWvfPGBfEKAS/vXsnv LASx8oGwXcq8RBPaamwmj6wEVcwu3W8cyO/WVbSiNwXca1fpi9FSMOe9IevMqqlm0+ml ulvD7PPnXWLLkkUoKG5qTxs1AkD73IUYQOexprkzm/NEhvxVqhTQlvkGHxxdTKYd8BIZ RXlkDzVfP0Utye8j3Rz+5kjRRAdDuW79xLGGAvhhzDeNFnuOKkGpmb3sHpXbXet4I0qY ZCfguvyCHGWXh1Rdeqp0q1Wmc9sup0bBdMULpOtuKL6DVcxDpr2knIoQsEZDCVX8lguK wu2Q== X-Gm-Message-State: ALKqPwdC4LfjD8IpIOTaEQcinmlzNyYpTVhIrHw7DSxItV1vT6Kg8CqI 2WipHLrp5jjK0SItm5muwKoRzQ== X-Google-Smtp-Source: AB8JxZqIG2CEx+SpzjRaYdmjLZcELUiKJAIEb+Em2fFdqK0WFikBboh7f0ThoJ81Feepml4U8Q3c9Q== X-Received: by 2002:a17:902:1025:: with SMTP id b34-v6mr7397683pla.207.1526608712736; Thu, 17 May 2018 18:58:32 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:32 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:23 -0700 Message-Id: <1526608674-12702-11-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 10/41] 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 19e78af..7160e37 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -66,6 +66,9 @@ static int gre_tap_net_id __read_mostly; static int ipgre_net_id __read_mostly; static unsigned int erspan_net_id __read_mostly; +static void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, + bool truncate, bool is_ipv4); static struct rtnl_link_ops ipgre_link_ops __read_mostly; @@ -93,9 +96,6 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } -static void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, bool truncate); - /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) @@ -932,52 +932,6 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline u8 tos_to_cos(u8 tos) -{ - u8 dscp, cos; - - dscp = tos >> 2; - cos = dscp >> 3; - return cos; -} - -static void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, bool truncate) -{ - struct iphdr *iphdr = ip_hdr(skb); - struct ethhdr *eth = eth_hdr(skb); - enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; - struct qtag_prefix { - __be16 eth_type; - __be16 tci; - } *qp; - u16 vlan_tci = 0; - - enc_type = ERSPAN_ENCAP_NOVLAN; - - /* If mirrored packet has vlan tag, extract tci and - * perserve vlan header in the mirrored frame. - */ - if (eth->h_proto == htons(ETH_P_8021Q)) { - qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); - vlan_tci = ntohs(qp->tci); - enc_type = ERSPAN_ENCAP_INFRAME; - } - - skb_push(skb, sizeof(*ershdr)); - ershdr = (struct erspanhdr *)skb->data; - memset(ershdr, 0, sizeof(*ershdr)); - - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION << VER_OFFSET)); - ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) | - (enc_type << EN_OFFSET & EN_MASK) | - ((truncate << T_OFFSET) & T_MASK)); - ershdr->md.index = htonl(index & INDEX_MASK); -} - static netdev_tx_t erspan_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1001,7 +955,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, } /* Push ERSPAN header */ - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate); + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + truncate, true); tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); return NETDEV_TX_OK; From patchwork Fri May 18 01:57:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915948 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="qZ1QCDwC"; 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 40nBL96MJKz9s19 for ; Fri, 18 May 2018 12:04:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 728BE10B0; Fri, 18 May 2018 01:58:41 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 93F431060 for ; Fri, 18 May 2018 01:58:34 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com [209.85.160.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 465956F3 for ; Fri, 18 May 2018 01:58:34 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id 30-v6so3612862pld.13 for ; Thu, 17 May 2018 18:58:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=VZz/zuNPtgeUnXbCsL0xG7uI3C3TsChxgcO2OJIDHk0=; b=qZ1QCDwChv5AV88QyZXwE4y5XSlEzHWCahb+tl3gq8Ks7wsPpj4JCRRTUfXHD9y67l 1e464gbOILmUVrl8I82d1JNFKm3DF5UdIkBu4ZQIRFDzieDJCOwOExWdreluBTVOS4JB lbyZ55w194mCbkv03ifN3elf8KCvqZDSLqBrkwoS+3FMHLGDPtIDm8kNuVgyOeKsz+3l nNjX1Wq3AMOtV6jz28ILRwuYT11U+2mn7G6wRCUZaSgoHv/cd5bSTKI+3orGl1H8N6d/ oEKbodLxe/2Txy/Z+U62TIsHypLRQa+AhsNRM3OAS3fgI1nC2kDAewOBXvN+iNHYSChA KAnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=VZz/zuNPtgeUnXbCsL0xG7uI3C3TsChxgcO2OJIDHk0=; b=I52cZwecCa4htqSS/6yFwijj0acFzQtiCIpkdVr/tnQSSFLhbGgKUBxsEbHUuyL7K7 uMdVBBJWLYtCDY5prHfPFApSKvCIDf6DnekMUa5OcrgJCuMogexa4zTuJd93VK0ZAeYe CY1tw+LALS+Oqjic8p0YSlbQcTk7QKGW2OTVJu30K4HLzwEXnaV8skydlytvgc08DIjT lczD/MsfAVCx2ZXwVx+LHdMwinlK4GWBg1A3EUJp+TmtoR6nt9BMEE0hIyXgeIal4ERR 0wjZ7RG04W8IaFcucZmWfayOU9ZgwchpI/MBFNkeGAU+5UQD9FRyHgYBQ2axZBhFKhFe WWUw== X-Gm-Message-State: ALKqPwfufCqolKi4KAK0/S61vuH1RWtc5YC39/eHBTZ7rq+DesW7e6si j+6S2kNsE9cVb/XJEMK8vb3eYA== X-Google-Smtp-Source: AB8JxZr90phTuECVL1KgncevzzFnif6EdNp7CxkvYT8/XTA7ffVJq/dPSBMww+EMl4jpruZnb1p+kw== X-Received: by 2002:a17:902:1007:: with SMTP id b7-v6mr7329803pla.88.1526608713632; Thu, 17 May 2018 18:58:33 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:33 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:24 -0700 Message-Id: <1526608674-12702-12-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 11/41] 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 7160e37..dbe86c4 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -190,23 +190,26 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst; + struct metadata_dst tun_dst = NULL; + struct erspan_base_hdr *ershdr; + struct erspan_metadata *pkt_md; struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; - struct erspanhdr *ershdr; const struct iphdr *iph; - __be32 index; + int ver; int len; itn = net_generic(net, erspan_net_id); iph = ip_hdr(skb); len = gre_hdr_len + sizeof(*ershdr); + /* Check based hdr len */ if (unlikely(!pskb_may_pull(skb, len))) return -ENOMEM; iph = ip_hdr(skb); - ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len); + ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); + ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; /* The original GRE header does not have key field, * Use ERSPAN 10-bit session ID as key. @@ -218,8 +221,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, iph->saddr, iph->daddr, 0); if (tunnel) { + len = gre_hdr_len + erspan_hdr_len(ver); + if (unlikely(!pskb_may_pull(skb, len))) + return -ENOMEM; + if (__iptunnel_pull_header(skb, - gre_hdr_len + sizeof(*ershdr), + len, htons(ETH_P_TEB), false, false) < 0) goto drop; @@ -1000,7 +1007,7 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + - sizeof(struct erspanhdr); + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; From patchwork Fri May 18 01:57:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915949 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="iktKkQx6"; 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 40nBLl4WNTz9s19 for ; Fri, 18 May 2018 12:04:31 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5782810BE; Fri, 18 May 2018 01:58:42 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 250A8104E for ; Fri, 18 May 2018 01:58:36 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com [209.85.160.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 57EA66F9 for ; Fri, 18 May 2018 01:58:35 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id 30-v6so3612889pld.13 for ; Thu, 17 May 2018 18:58:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ch/Ijbyju0qXNruIlO9+hqUVEfO2KACK90ZRNPjX/x8=; b=iktKkQx6kSOUt/oj5Krwpd5IunVPeUJ0YRVDI4tmiPyyYu333+VwPyzeLDidMO7FHO NRElUifxQbC6esz7cXdI+9MOjtn/2gVAJsmBX/PiTwy1OKhIRZ0o8w+P6paB0hVnk/29 TRwVVvwGfcDBCofFYnr7WHy+Zq0W4a+I7NWF00J11RkIqoNarYxUqycKiX1O/3SKaa8P 0HVoOy2tpOxuYytiqeFxXFaZe/hTutdj4swHm8FqzbIqkIGzsuj0J7gbf+8heWDmS+ZR RehkLQsNhh8J+N3tptlFEO4WbU/tHhItXWGgE5uf2r90pob1DJo1sdy647x0mOJm2T8K ijNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ch/Ijbyju0qXNruIlO9+hqUVEfO2KACK90ZRNPjX/x8=; b=GuYjzN2jJgc0zhAOgEcnKyve0lcz36Tuf/D1+gUevn9uYHYYmbkLwaWnwugjLjQn2Z ej/yMZxaNYPPSJZtJzUpxbzkCSuaUtHl3mh5g5DLFu8yGNqRaR5UwIHaa1fC9hpZhOJL M6biT8gJMYJk253wmyxUtYnvHCnPN4GCpK52MB7pdegSJ8eB5tnXB4Xptq2e98ihUYtL 5wdo0eW6so/VHFdtiLGwynOMGmv0xKN8X5TRfk6V4hYKL2mj/yGgL10jp+qe+YYwBRKU dju/sMJUVhUFDvSGApHFroEK1XGWFLqg8iDFhq3x55Y7XlQTwc2XtPT8ofjJAv4zfKNa TP0A== X-Gm-Message-State: ALKqPwe+R4FOO72IIlGLb3aBBAtZrFUtmaDbfDKycdmUp/RVv77CRdk4 bqRbK3feaUhfd/zzBWaRGrjTlQ== X-Google-Smtp-Source: AB8JxZr1NksuefZYgUKEJ97cc0eNb/OxH+rElwKcSInxW+4yA98HQB231qYWZzW6WooTmw+5pOtzZg== X-Received: by 2002:a17:902:5602:: with SMTP id h2-v6mr7637603pli.115.1526608714677; Thu, 17 May 2018 18:58:34 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:34 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:25 -0700 Message-Id: <1526608674-12702-13-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Haishuang Yan Subject: [ovs-dev] [PATCH V2 12/41] ip_gre: fix wrong return value of erspan_rcv X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Haishuang Yan Upstream commit: commit c05fad5713b81b049ec6ac4eb2d304030b1efdce Author: Haishuang Yan Date: Fri Dec 15 10:46:16 2017 +0800 ip_gre: fix wrong return value of erspan_rcv If pskb_may_pull return failed, return PACKET_REJECT instead of -ENOMEM. Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Cc: William Tu Signed-off-by: Haishuang Yan Acked-by: William Tu Signed-off-by: David S. Miller Cc: Haishuang Yan Signed-off-by: Greg Rose --- datapath/linux/compat/ip_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index dbe86c4..c7912cf 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -223,7 +223,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, if (tunnel) { len = gre_hdr_len + erspan_hdr_len(ver); if (unlikely(!pskb_may_pull(skb, len))) - return -ENOMEM; + return PACKET_REJECT; if (__iptunnel_pull_header(skb, len, From patchwork Fri May 18 01:57:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915950 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="SkQeIejq"; 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 40nBMK3Lwnz9s19 for ; Fri, 18 May 2018 12:05:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3EA6410C5; Fri, 18 May 2018 01:58:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 9B3EC1056 for ; Fri, 18 May 2018 01:58:36 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com [209.85.160.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 40A87196 for ; Fri, 18 May 2018 01:58:36 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id 30-v6so3612911pld.13 for ; Thu, 17 May 2018 18:58:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WSq9UNQii/GCudQpDqunj6VsmutUNUv34agFnRFVc2I=; b=SkQeIejqGph5LeitSXkdnCq0u1ZytMHzLZd0vKGwBk1DVCWe2VLE6AdA1QTOWZp2Iu xFwxUnVs7nzmK83dep5Qz9vYGe014b6JECBFOeDyjrS1DtoZV4nCfsxGCJ8R9qCifc36 SleSUWX3TOJNP5BeNI9doXtvPP3CxC6rsNiiyO2EzjkvweM86xrfMtO9cri0mXudCrTL epguGJ8cH4xJ7UL5mDG+3V0lrrnXzdYq9UHjzI9X6ugYZcKVJxkcZ1GJftCaMuGvmLpk q9mBr+6tJflU/XPfBR3zRlYwEMyPyUfCgOBjSFZHK8uQHa5I+gShPhNM9PQeicWiZle3 R2Wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WSq9UNQii/GCudQpDqunj6VsmutUNUv34agFnRFVc2I=; b=BzQFN8BHh4uFQ2YfMVMvNvdB7nsLw0hzx0EEm9RYDV9C+lyiFQzoeIE5AmvO1AuZ01 mDfdDiJQaGXPLOIFJQ+VpovqrPT577yVEsFaXu5yae6hXzVuWi0ODC8dV7YWdcNyaPGF q13vu/K9JwkNjEovGZkkwF1tp7n24+kNTeTl4O5Oh1CFk5CNvp2db+whiAOkXJQwwrbw mnk2oirY6QR4qo9MzRCPRkAH/OsnIg1lL3gCfVZZ2Eo4ahq2lcQB46XC18cg2Q5sp9HY nLSPFpXkwenSY/lG1n2Aa2FMUt93vw3+4YwLVcIHClufj1xP5SjhkOlmpiGyZSCiHCdO dfdA== X-Gm-Message-State: ALKqPwfzPfWOfWrSZ3I9Cpk0wHY+Lv9Cj08v8wI2EaOdI823lcR6/GBI 7aOqrJRG+JpPEznBDUxd7GoCGQ== X-Google-Smtp-Source: AB8JxZo+dc/SoTEkDhbQz+MHwy47UWYxeMYisHRHb61dwDV6GIgmWvaZbZ2cKBSchueCgVnwta0LWw== X-Received: by 2002:a17:902:968d:: with SMTP id n13-v6mr7316308plp.168.1526608715490; Thu, 17 May 2018 18:58:35 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:35 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:26 -0700 Message-Id: <1526608674-12702-14-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 13/41] ip_gre: erspan: reload pointer after pskb_may_pull X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d91e8db5b629a3c8c81db4dc317a66c7b5591821 Author: William Tu Date: Fri Dec 15 14:27:44 2017 -0800 net: erspan: reload pointer after pskb_may_pull pskb_may_pull() can change skb->data, so we need to re-load pkt_md and ershdr at the right place. Fixes: 94d7d8f29287 ("ip6_gre: add erspan v2 support") Fixes: f551c91de262 ("net: erspan: introduce erspan v2 for ip_gre") Signed-off-by: William Tu Cc: Haishuang Yan Signed-off-by: David S. Miller Only the ip_gre portion of the upstream commit. The ipv6 portion is pulled in with later patch in series. Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip_gre.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index c7912cf..028586c 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -225,6 +225,9 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, if (unlikely(!pskb_may_pull(skb, len))) return PACKET_REJECT; + ershdr = (struct erspan_base_hdr *)skb->data; + pkt_md = (struct erspan_metadata *)(ershdr + 1); + if (__iptunnel_pull_header(skb, len, htons(ETH_P_TEB), From patchwork Fri May 18 01:57:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915951 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="ZgRjNKAi"; 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 40nBNf66qmz9s37 for ; Fri, 18 May 2018 12:06:10 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id BB4FB10B3; Fri, 18 May 2018 01:58:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 926D0107E for ; Fri, 18 May 2018 01:58:37 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 21B726F8 for ; Fri, 18 May 2018 01:58:37 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id a14-v6so2966123pfi.1 for ; Thu, 17 May 2018 18:58:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=kquidjQ5Vnu6ceI5R0QyNVt1ojyw0m3pIIJCds7JAoQ=; b=ZgRjNKAirGy6HG2lxLYNSRzPnxF+tFMFhylyQ/nDZw9STA+a4eiyTlo3HPMSLNwgEj ZuObh0fBXIZNP4GvDSQhmMz1NjN6uxomU1a+nxtUpMbYwwFMdiFmFXBbMbF/LseJab2C lvJCQhrEvkunrhd+maryTtJ0oNKxT4DIWJPGF24gaGBVqsMpMw07vz8tT/XadmwZqgTt zByuZaMCqnw4QNizI8akJBGk5b6bRVdEZl5mJUySlWbmjpMikhXD6kBwtAFYhUBVQFvL WFEE1+Dm8F62p6eM+xdcuSmDixmq+NV29HHkWSJTQ5VZ6chzkq5b4szBVd+O8lVtIVNY frzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=kquidjQ5Vnu6ceI5R0QyNVt1ojyw0m3pIIJCds7JAoQ=; b=KlZt/6ecJ+W4yC1dfub6lnRcey3pgI+w/WajbD7kCDopYUrlu6dutbYkTKf0C2iE6L psESKmg+mCAqpZojEq/f5udJWjwNGElqgQBhW1DRl0pK7wG5o6EXuMQYFC0T7aviOpKL Yr/S2DvQ2+d9pnfcKYrMr3aYL5FqJ3oMxcLgxVIPtmxC68nWFaF6Xn9868EadOTEvg9F ag4vJo/5G8QZGCWUBV3UHOMWK3MmLJdtJceFou/wrZA7Nc/ht3guthVgoJcSTGw/PEI2 dokVSR52KgV8tEXnypNDKob/qsmAEuUtWEJvGvw4mIVYer29zZ9+0oEGN2Rd11S/Bl19 Hrmw== X-Gm-Message-State: ALKqPwdYvCWGikA9dYFGAQghld40jOxymqjaROTjUpMAQFjeozCG8+EY YuXv6CF1AzaiUNijBdTApGmARw== X-Google-Smtp-Source: AB8JxZpUhbuPqApU9RIzR0JyOUQIAOryAt7J5yRquf4r8qg88YYi263Ci+ZzVEi9rPLBcTxktByX0w== X-Received: by 2002:a63:77c9:: with SMTP id s192-v6mr5959294pgc.364.1526608716452; Thu, 17 May 2018 18:58:36 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:36 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:27 -0700 Message-Id: <1526608674-12702-15-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 14/41] ip_gre: remove the incorrect mtu limit for ipgre tap X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Xin Long Upstream commit: commit cfddd4c33c254954927942599d299b3865743146 Author: Xin Long Date: Mon Dec 18 14:24:35 2017 +0800 ip_gre: remove the incorrect mtu limit for ipgre tap ipgre tap driver calls ether_setup(), after commit 61e84623ace3 ("net: centralize net_device min/max MTU checking"), the range of mtu is [min_mtu, max_mtu], which is [68, 1500] by default. It causes the dev mtu of the ipgre tap device to not be greater than 1500, this limit value is not correct for ipgre tap device. Besides, it's .change_mtu already does the right check. So this patch is just to set max_mtu as 0, and leave the check to it's .change_mtu. Fixes: 61e84623ace3 ("net: centralize net_device min/max MTU checking") Reported-by: Jianlin Shi Signed-off-by: Xin Long Signed-off-by: David S. Miller Cc: Xin Long Signed-off-by: Greg Rose --- datapath/linux/compat/ip_gre.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 028586c..f849971 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -367,6 +367,7 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) return 0; + goto drop; } if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) @@ -390,7 +391,6 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *__tpi) if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD) return 0; - drop: kfree_skb(skb); @@ -1182,6 +1182,7 @@ static void ipgre_tunnel_setup(struct net_device *dev) static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); + dev->max_mtu = 0; dev->netdev_ops = &gre_tap_netdev_ops; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ip_tunnel_setup(dev, gre_tap_net_id); From patchwork Fri May 18 01:57:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915952 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="mUvtHlN1"; 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 40nBPD3NP0z9s19 for ; Fri, 18 May 2018 12:06:40 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B74D010D0; Fri, 18 May 2018 01:58:47 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8D78810A3 for ; Fri, 18 May 2018 01:58:38 +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 3F7936DB for ; Fri, 18 May 2018 01:58:38 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id a14-v6so2966165pfi.1 for ; Thu, 17 May 2018 18:58:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HZK7C8YNQRG2Iqi/YKxcnbsTb2OFcwVj0I4V6oqEb7s=; b=mUvtHlN1nm4qMu8v+wZFofI8fpoMjuEJkvffv+x2tw+mRyKj9oLFNaI09biSIT5djw LXplEtwOMXqW4yMjcONV1I6GCZiogcKRXAtfRdZTkYqWVuH+6HXa9qqJMeZmPYZ1q4uf kQXH8L9bGu1lxhXKGpogv10wB0/RiIBpM9R2ItuMr64820KmPR1dJftKkniJ61Z/9+Xd 9E2IlSeOCbvxDRGcxlp5/iNOd7MKpL+pj19TyQWsUhzAQS/lzYnVmEoS3qli6aweIqt9 QOKSCBCNqxopkhgI8os11btf2xk05H86pLDEJkXwNk7Ro/N5A7fhodbcye73rR1ILd6A rd9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HZK7C8YNQRG2Iqi/YKxcnbsTb2OFcwVj0I4V6oqEb7s=; b=lybST7GwCGJoTRRxHZB6Qp1Si/AF37r/k+L3tmdNzJ0P6KKjxtVX6Cnz6FkZ4wmAdP XJbJz6AbX/tEKwk8xKO3efwoSLSN+5FREYGDMynAN/RrIxXRvTp88AFgXJ5SOkMBLz2N ex8wpNtxl90t26r04h4R4p7tln+M1w1tPQDlK+hMCssv2hARBXx28PpM5hXT2djsAo8i 2yu6vIPdnrpFOgH0ycV+v6r2nGXUn2ntLh6NjJ86MVX92NvB9l7ZPBDmiJyJR1VrfcXO X1HKyw60cdRlC+PMQcPcRWFMCEbHZl6ROIZHygIWQNoiBZtxgr+fugpvh5wYdQ91QWy9 wM5w== X-Gm-Message-State: ALKqPweb9Q28gLCupJ4LZpFazuT+JdCS7+OBDL+RZ6V1MLeAIcXxhOsZ /0M41NODEUsb+1DYg+gg7PBfyQ== X-Google-Smtp-Source: AB8JxZr2LCm/sLVSnjw4Cph23u5P8xeTDhRew5LHEnovsK7o6419kNB0OLDEfzylxPTCS4byceDDHA== X-Received: by 2002:a65:51cd:: with SMTP id i13-v6mr4765031pgq.359.1526608717590; Thu, 17 May 2018 18:58:37 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:37 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:28 -0700 Message-Id: <1526608674-12702-16-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 15/41] compat: Move function to header X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org tnl_flags_to_gre_flags is also needed in both ip_gre.c and gre.c on some kernels. Move it from ip_gre.c to the common header. Signed-off-by: Greg Rose --- datapath/linux/compat/include/net/gre.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index ead86f6..e2473f2 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -30,6 +30,29 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #else #include_next +#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags +static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) +{ + __be16 flags = 0; + + if (tflags & TUNNEL_CSUM) + flags |= GRE_CSUM; + if (tflags & TUNNEL_ROUTING) + flags |= GRE_ROUTING; + if (tflags & TUNNEL_KEY) + flags |= GRE_KEY; + if (tflags & TUNNEL_SEQ) + flags |= GRE_SEQ; + if (tflags & TUNNEL_STRICT) + flags |= GRE_STRICT; + if (tflags & TUNNEL_REC) + flags |= GRE_REC; + if (tflags & TUNNEL_VERSION) + flags |= GRE_VERSION; + + return flags; +} + #ifndef HAVE_GRE_CISCO_REGISTER /* GRE demux not available, implement our own demux. */ From patchwork Fri May 18 01:57:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915953 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="hILa3W/G"; 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 40nBPp4JkMz9s19 for ; Fri, 18 May 2018 12:07:10 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B0E9010EA; Fri, 18 May 2018 01:58:48 +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 4C075109E for ; Fri, 18 May 2018 01:58:39 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 0FA316DB for ; Fri, 18 May 2018 01:58:38 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id bi12-v6so3613873plb.12 for ; Thu, 17 May 2018 18:58:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=k8SS6rLrg1/UxR9buY/DiXW/ZoM9crVB3ENXraxhDWk=; b=hILa3W/GjE5MJLMCW00yYd7hUEXCM0uNAFW+lbcXu+mfYgpAveMct9wM721xEcCHWC 2Xpmpi2X/SomSHKfANbXd4hKi198ZQRyuBATnw+gXNLkv2qO8A7mIUSssLRrx1yAFsVP Db9OTlAEu+3TkD+L5N1Mxb0IIZNoLyS/o8aLHa3QurPk8rapquavhmGTmH62eWQcIf6r RQaM/CTAs6UKS82ydtfjbFiKvee88tw/UMZsURuHVK73iDXNaHxg4WKwOvYVJ4TeqAk9 vLcSe33hhMsKFHoPUZJWdYeVVEnNlfN7+ZSlZ7UNfSSsEPPMfw38Kshzrjq+pGu178hs 8DSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=k8SS6rLrg1/UxR9buY/DiXW/ZoM9crVB3ENXraxhDWk=; b=TdmEwHBaMDUyW9fDM/8ybCzZwTRpUhCfLv17pMzkAotDMJRksHX1H/fN0EBKuRLshg xpUe3TMU9X6+sARLvIaDXU7DPBWytVfZLgl55SSFznJ47Olz584y5zhsIsJ1nxFladFj eR8VCtgxpgTSWfv+jJwQFDLg1TP3mHCAb0y/pGMmsOny2RVJwj55QmvFvCUrAnRhfPTE ppwe+nFJxT6lS7kD0H8Z/xqJ1ISsNw2gHBYrRqQ7zT1KGO/fHi78QVd0AUQWcr7QJ921 AutSzF06fH3tksZ2wdwMTqz4P9ruzZAwtUvkEGWAiWiALnpoYm78YDheA5d7ks2GKScK 3r1w== X-Gm-Message-State: ALKqPwdRxZobozIvau1Sog6WT0p2S7+99uEkasayla/mms4EcS5taiVd fbKz02RnhZhrQUTsEfR8BK2Vxw== X-Google-Smtp-Source: AB8JxZoYZTJOqxnxUX1vBb9QkPj28T/IN5A4DPQOv3n+SD9PwQTnqSqD6rGEQ0JXvNnILDL0LZallg== X-Received: by 2002:a17:902:9a9:: with SMTP id 38-v6mr7643424pln.114.1526608718428; Thu, 17 May 2018 18:58:38 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:38 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:29 -0700 Message-Id: <1526608674-12702-17-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 16/41] compat: Add #define for gre_handle_offloads X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Fixes compile errors on some 4.x kernels. Signed-off-by: Greg Rose --- datapath/linux/compat/ip_gre.c | 1 + 1 file changed, 1 insertion(+) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index f849971..b1493e0 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -421,6 +421,7 @@ static bool is_gre_gso(struct sk_buff *skb) return skb_is_gso(skb); } +#define gre_handle_offloads rpl_gre_handle_offloads static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) { int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; From patchwork Fri May 18 01:57:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915954 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="k/vELNwk"; 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 40nBQM04GYz9s37 for ; Fri, 18 May 2018 12:07:38 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 301B810F5; Fri, 18 May 2018 01:58:50 +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 7493210B0 for ; Fri, 18 May 2018 01:58:40 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E20E9196 for ; Fri, 18 May 2018 01:58:39 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id u6-v6so3627622pls.9 for ; Thu, 17 May 2018 18:58:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CmaZO21AUFpxKJpglNW4aNaKQGz/lP0ouLyKOF1IR/w=; b=k/vELNwkZavv2xlh2GfRsuet2dACLzhh16BYzfGDLe2I/+8ABjt6CwwZlVWUulZU09 wjiVAEOQNl33N4sHFPPZoH3RCYXCGSGS0gKrtnZnLDGwXEj80B74KDabeWvnIzJQGqOf dGthUbRpsWkp0N/3ftrBajPo2qlsN++gJnTjco2SrrVgjE6p9oVRM1Z76yYUM1S1qNtq 7WwK4vXMQ1lTeFFiiSXCM9I/wtIwQStd3qCx3TOW0ohDsWCNV9IPQWc47OPRscCfKIfL FpzwbP0g1cqhg0k5poivBuv53oTTtMXREDvayZbALd9UkKWMOB2tIIVg1HTu/JZjIv2i o+Vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CmaZO21AUFpxKJpglNW4aNaKQGz/lP0ouLyKOF1IR/w=; b=L7xW53xCNusyuU5bUDJ/WF9UQ087pw2vWrsdcLtGGRr3vWRm8kyqwGyvqhMrCsi+ka /X41mMcnicuJiUAQkJkUYc+M8fGrE2WpK7e4/bMvgRdAHPGW/1Z/lyGqle0P4wXUXIe2 iAwFg4Wu/qcA/hkUsuS45NU7Cxr18P+pBdik69K0VtCsFZPpGKdcpVOqP8Tw9BxQ68kE mHuGAF8u5FB/22wmKgUZ3Hau+l+hmjbnTW7ms4tXYq4UPNiIGfk9u1++In2ynaixmIO6 7S9VcAEC0Z4oR37cRjXYpYm1JVyDexJ5ClbkXPU7lZhPUVftiY/K4EgSrXDTw5YpLt79 P+Kw== X-Gm-Message-State: ALKqPwcbI1wQxb7DecRTX+N4fFV8jH7Xkg3bCukSgRBJq7nymispCKw4 sak/lRmwW0+qo9FGb2hXj+TkRQ== X-Google-Smtp-Source: AB8JxZp4SQFa7FJUbCibIYUcaga6B6peKiTPvfpXQx6gCFPeBzqunsLMYq7srUu3qccIGzuavJNHNQ== X-Received: by 2002:a17:902:28a7:: with SMTP id f36-v6mr7494747plb.155.1526608719298; Thu, 17 May 2018 18:58:39 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:38 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:30 -0700 Message-Id: <1526608674-12702-18-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 17/41] compat: Fixups for some compile warnings and errors X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org A lot of code has been pulled in. Fix it up to make sure it compiles correctly. Signed-off-by: Greg Rose --- datapath/linux/compat/gre.c | 23 ---------------- datapath/linux/compat/include/net/gre.h | 47 ++++++++++++++++++++++++++++++++- datapath/linux/compat/ip_gre.c | 9 ++++--- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index 08a5a30..7d16aee 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -82,29 +82,6 @@ static __sum16 check_checksum(struct sk_buff *skb) return csum; } -#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags -static __be16 gre_flags_to_tnl_flags(__be16 flags) -{ - __be16 tflags = 0; - - if (flags & GRE_CSUM) - tflags |= TUNNEL_CSUM; - if (flags & GRE_ROUTING) - tflags |= TUNNEL_ROUTING; - if (flags & GRE_KEY) - tflags |= TUNNEL_KEY; - if (flags & GRE_SEQ) - tflags |= TUNNEL_SEQ; - if (flags & GRE_STRICT) - tflags |= TUNNEL_STRICT; - if (flags & GRE_REC) - tflags |= TUNNEL_REC; - if (flags & GRE_VERSION) - tflags |= TUNNEL_VERSION; - - return tflags; -} - static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, bool *csum_err) { diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index e2473f2..78422c8 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -31,7 +31,52 @@ static inline struct net_device *rpl_gretap_fb_dev_create( #include_next #define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags -static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) +static inline __be16 rpl_tnl_flags_to_gre_flags(__be16 tflags) +{ + __be16 flags = 0; + + if (tflags & TUNNEL_CSUM) + flags |= GRE_CSUM; + if (tflags & TUNNEL_ROUTING) + flags |= GRE_ROUTING; + if (tflags & TUNNEL_KEY) + flags |= GRE_KEY; + if (tflags & TUNNEL_SEQ) + flags |= GRE_SEQ; + if (tflags & TUNNEL_STRICT) + flags |= GRE_STRICT; + if (tflags & TUNNEL_REC) + flags |= GRE_REC; + if (tflags & TUNNEL_VERSION) + flags |= GRE_VERSION; + + return flags; +} + +#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags +static inline __be16 rpl_gre_flags_to_tnl_flags(__be16 flags) +{ + __be16 tflags = 0; + + if (flags & GRE_CSUM) + tflags |= TUNNEL_CSUM; + if (flags & GRE_ROUTING) + tflags |= TUNNEL_ROUTING; + if (flags & GRE_KEY) + tflags |= TUNNEL_KEY; + if (flags & GRE_SEQ) + tflags |= TUNNEL_SEQ; + if (flags & GRE_STRICT) + tflags |= TUNNEL_STRICT; + if (flags & GRE_REC) + tflags |= TUNNEL_REC; + if (flags & GRE_VERSION) + tflags |= TUNNEL_VERSION; + + return tflags; +} +#define gre_tnl_flags_to_gre_flags rpl_gre_tnl_flags_to_gre_flags +static inline __be16 rpl_gre_tnl_flags_to_gre_flags(__be16 tflags) { __be16 flags = 0; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index b1493e0..8060097 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -190,7 +190,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int gre_hdr_len) { struct net *net = dev_net(skb->dev); - struct metadata_dst tun_dst = NULL; + struct metadata_dst *tun_dst = NULL; struct erspan_base_hdr *ershdr; struct erspan_metadata *pkt_md; struct ip_tunnel_net *itn; @@ -200,16 +200,15 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, int len; itn = net_generic(net, erspan_net_id); - iph = ip_hdr(skb); len = gre_hdr_len + sizeof(*ershdr); /* Check based hdr len */ if (unlikely(!pskb_may_pull(skb, len))) - return -ENOMEM; + return PACKET_REJECT; iph = ip_hdr(skb); ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); - ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; + ver = ershdr->ver; /* The original GRE header does not have key field, * Use ERSPAN 10-bit session ID as key. @@ -1183,7 +1182,9 @@ static void ipgre_tunnel_setup(struct net_device *dev) static void ipgre_tap_setup(struct net_device *dev) { ether_setup(dev); +#ifdef HAVE_NET_DEVICE_MAX_MTU dev->max_mtu = 0; +#endif dev->netdev_ops = &gre_tap_netdev_ops; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ip_tunnel_setup(dev, gre_tap_net_id); From patchwork Fri May 18 01:57:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915963 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="ISKQWd5N"; 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 40nBVs4Fv5z9s37 for ; Fri, 18 May 2018 12:11:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0E4FC1111; Fri, 18 May 2018 01:59:04 +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 A3961F06 for ; Fri, 18 May 2018 01:58:54 +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 BDE486F3 for ; Fri, 18 May 2018 01:58:45 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id q22-v6so2956878pff.11 for ; Thu, 17 May 2018 18:58:45 -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=rEEtHeNS2s/pe+otCSyfZQuo4ReZp/0R6IwqOWIZX6Y=; b=ISKQWd5NLLf8vWkG6TMqFuChVsXIgNn8XYeiMkavzeB18awwHiBsJ21NoCq7fw4T7i 2dZDmHkVVuj+MG4+ldW6RBTsU4wEtJwBb+MjufHBk440rBXM5G8rFYuNp38m8TW6CTWI 6qQuGGh0y1ObSIEa3/3ZNXKLb7LzDqnsAnUCuppik1Pv7S0aTnl+eMDAHZei+4Hi3pvO 4gzOQJibeyWydIRU2HFb4Utlfc7FH2Xjuos2/LrjJVrM22oaoWqqog2G7iOusX8ZoEB9 PG9sXJy7jC61ZTWO0HvuU6XSnZINdJiwqdw/Q32KV3cBFm4KiXOOeeWO7WDDj5fCwhmv pQbw== 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=rEEtHeNS2s/pe+otCSyfZQuo4ReZp/0R6IwqOWIZX6Y=; b=U/dIapu4pTNuXXf8YwzZ4rFztEtyj/+JsIFre3zTgxw1yTxWcdQoP5Q4Nf1pMU+SUC Pj7OW3uO2oR4EkDDQumQ4wPANw7Ao/5TD06gnPKFKoI37yLIw4YF0p4nJd4KpIcsGmx0 79abJTu/sWJ9iCexBvS+EJwdV8iPDn8rGeY/k7NyljUxITngZ+mb5zADpq5XXB1dPUmd WUeyAnTKxLiXBb/ZTY3On6LU7W11/0iYtA1soquNqwRCS+InTO3LQzUygN+ZgnL4L3h4 SqhvJh4kE1mtN+eiGH02H6tUDiaDPNqmHFBydMZSbgRi3EaFsLNIGQfNa0Ab4yqLOwef O1Rg== X-Gm-Message-State: ALKqPwcAlzlULJNWovP4uy+BkZ5QMwFJF7Zms69dFrnJKhlblV39gBZv Qx/SnNxvpcto8IGvpJb41P9egQ== X-Google-Smtp-Source: AB8JxZpj1Rw5QfbT0m4kW1Q833aw2TZq55s40oiRBz3J3hFmABGnLxFQvJ7vEkHxV78DsYnXYyoNeg== X-Received: by 2002:a63:380e:: with SMTP id f14-v6mr5961078pga.242.1526608722666; Thu, 17 May 2018 18:58:42 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:42 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:31 -0700 Message-Id: <1526608674-12702-19-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-0.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, FREEMAIL_REPLY,RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V2 18/41] compat: Add ipv6 GRE and IPV6 Tunneling X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch backports upstream ipv6 GRE and tunneling into the OVS OOT (Out of Tree) datapath drivers. The primary reason for this is to support the ERSPAN feature. Because there is no previous history of ipv6 GRE and tunneling it is not possible to exactly reproduce the history of all the files in the patch. The two newly added files - ip6_gre.c and ip6_tunnel.c - are cut from whole cloth out of the upstream Linux 4.15 kernel and then modified as necessary with compatibility layer fixups. These two files already included parts of several other upstream commits that also touched other upstream files. As such, this patch may incorporate parts or all of the following commits: d350a82 net: erspan: create erspan metadata uapi header c69de58 net: erspan: use bitfield instead of mask and offset b423d13 net: erspan: fix use-after-free 214bb1c net: erspan: remove md NULL check afb4c97 ip6_gre: fix potential memory leak in ip6erspan_rcv 50670b6 ip_gre: fix potential memory leak in erspan_rcv a734321 ip6_gre: fix error path when ip6erspan_rcv failed dd8d5b8 ip_gre: fix error path when erspan_rcv failed 293a199 ip6_gre: fix a pontential issue in ip6erspan_rcv d91e8db5 net: erspan: reload pointer after pskb_may_pull ae3e133 net: erspan: fix wrong return value c05fad5 ip_gre: fix wrong return value of erspan_rcv 94d7d8f ip6_gre: add erspan v2 support f551c91 net: erspan: introduce erspan v2 for ip_gre 1d7e2ed net: erspan: refactor existing erspan code ef7baf5 ip6_gre: add ip6 erspan collect_md mode 5a963eb ip6_gre: Add ERSPAN native tunnel support ceaa001 openvswitch: Add erspan tunnel support. f192970 ip_gre: check packet length and mtu correctly in erspan tx c84bed4 ip_gre: erspan device should keep dst c122fda ip_gre: set tunnel hlen properly in erspan_tunnel_init 5513d08 ip_gre: check packet length and mtu correctly in erspan_xmit 935a974 ip_gre: get key from session_id correctly in erspan_rcv 1a66a83 gre: add collect_md mode to ERSPAN tunnel 84e54fe gre: introduce native tunnel support for ERSPAN In cases where the listed commits also touched other source code files then the patches are also listed separately within this patch series. Signed-off-by: Greg Rose --- datapath/linux/Modules.mk | 2 + datapath/linux/compat/include/linux/compiler.h | 4 + datapath/linux/compat/include/linux/if_ether.h | 4 + datapath/linux/compat/include/linux/netdevice.h | 7 + datapath/linux/compat/include/linux/openvswitch.h | 3 + datapath/linux/compat/include/linux/skbuff.h | 11 + datapath/linux/compat/include/net/erspan.h | 254 +- datapath/linux/compat/include/net/gre.h | 25 + datapath/linux/compat/include/net/ip6_tunnel.h | 206 +- datapath/linux/compat/include/net/ipv6.h | 29 + datapath/linux/compat/ip6_gre.c | 2578 +++++++++++++++++++++ datapath/linux/compat/ip6_tunnel.c | 2199 ++++++++++++++++++ datapath/linux/compat/ip_gre.c | 1 + datapath/vport.c | 12 + lib/dpif-netlink-rtnl.c | 12 + lib/dpif-netlink.c | 5 + ofproto/ofproto-dpif-xlate.c | 3 + 17 files changed, 5321 insertions(+), 34 deletions(-) create mode 100644 datapath/linux/compat/ip6_gre.c create mode 100644 datapath/linux/compat/ip6_tunnel.c diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index e0a90c3..104c32f 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -13,6 +13,8 @@ openvswitch_sources += \ linux/compat/ip_tunnel.c \ linux/compat/ip_tunnels_core.c \ linux/compat/ip6_output.c \ + linux/compat/ip6_gre.c \ + linux/compat/ip6_tunnel.c \ linux/compat/lisp.c \ linux/compat/netdevice.c \ linux/compat/nf_conntrack_core.c \ diff --git a/datapath/linux/compat/include/linux/compiler.h b/datapath/linux/compat/include/linux/compiler.h index dbe3ca7..65f3ba6 100644 --- a/datapath/linux/compat/include/linux/compiler.h +++ b/datapath/linux/compat/include/linux/compiler.h @@ -11,4 +11,8 @@ #define __rcu #endif +#ifndef READ_ONCE +#define READ_ONCE(x) (x) +#endif + #endif diff --git a/datapath/linux/compat/include/linux/if_ether.h b/datapath/linux/compat/include/linux/if_ether.h index aaa88db..8dff938 100644 --- a/datapath/linux/compat/include/linux/if_ether.h +++ b/datapath/linux/compat/include/linux/if_ether.h @@ -27,6 +27,10 @@ #define ETH_P_ERSPAN 0x88BE /* ERSPAN TYPE II */ #endif +#ifndef ETH_P_ERSPAN2 +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ +#endif + #define inner_eth_hdr rpl_inner_eth_hdr static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 29ef6c7..cf68ed5 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -316,4 +316,11 @@ static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol, skb->mac_len = mac_len; } #endif + +#ifndef HAVE_NETIF_KEEP_DST +static inline void netif_keep_dst(struct net_device *dev) +{ +} +#endif + #endif /* __LINUX_NETDEVICE_WRAPPER_H */ diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 84ebcaf..771220b 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -238,6 +238,9 @@ enum ovs_vport_type { OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */ OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */ OVS_VPORT_TYPE_STT = 106, /* STT tunnel */ + OVS_VPORT_TYPE_ERSPAN = 107, /* ERSPAN tunnel. */ + OVS_VPORT_TYPE_IP6ERSPAN = 108, /* ERSPAN tunnel. */ + OVS_VPORT_TYPE_IP6GRE = 109, __OVS_VPORT_TYPE_MAX }; diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h index 45778bd..63ffcaa 100644 --- a/datapath/linux/compat/include/linux/skbuff.h +++ b/datapath/linux/compat/include/linux/skbuff.h @@ -421,4 +421,15 @@ static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len) } #endif +#ifndef HAVE_SKB_GSO_IPXIP6 +#define SKB_GSO_IPXIP6 (1 << 10) +#endif + +#ifndef HAVE_SKB_SET_INNER_IPPROTO +static inline void skb_set_inner_ipproto(struct sk_buff *skb, + __u8 ipproto) +{ +} +#endif + #endif diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h index b4f13e6..813a9c5 100644 --- a/datapath/linux/compat/include/net/erspan.h +++ b/datapath/linux/compat/include/net/erspan.h @@ -1,4 +1,4 @@ -#ifndef USE_UPSTREAM_TUNNEL +#ifndef HAVE_LINUX_ERSPAN_H #ifndef __LINUX_ERSPAN_H #define __LINUX_ERSPAN_H @@ -16,7 +16,7 @@ * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The * other fields are set to zero, so only a sequence number follows. * - * ERSPAN Type II header (8 octets [42:49]) + * ERSPAN Version 1 (Type II) header (8 octets [42:49]) * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -25,11 +25,66 @@ * | Reserved | Index | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * + * + * ERSPAN Version 2 (Type III) header (12 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS |BSO|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Timestamp | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SGT |P| FT | Hw ID |D|Gra|O| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Platform Specific SubHeader (8 octets, optional) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platf ID | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ -#define ERSPAN_VERSION 0x1 +/* #include */ +/* Just insert uapi/linux/erspan.h here since + * we don't pull in uapi to compat + */ +/* ERSPAN version 2 metadata header */ +struct erspan_md2 { + __be32 timestamp; + __be16 sgt; /* security group tag */ +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 hwid_upper:2, + ft:5, + p:1; + __u8 o:1, + gra:2, + dir:1, + hwid:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 p:1, + ft:5, + hwid_upper:2; + __u8 hwid:4, + dir:1, + gra:2, + o:1; +#else +#error "Please fix " +#endif +}; + +struct erspan_metadata { + int version; + union { + __be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ + } u; +}; +#define ERSPAN_VERSION 0x1 /* ERSPAN type II */ #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff #define COS_MASK 0xe000 @@ -38,6 +93,19 @@ #define ID_MASK 0x03ff #define INDEX_MASK 0xfffff +#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/ +#define BSO_MASK EN_MASK +#define SGT_MASK 0xffff0000 +#define P_MASK 0x8000 +#define FT_MASK 0x7c00 +#define HWID_MASK 0x03f0 +#define DIR_MASK 0x0008 +#define GRA_MASK 0x0006 +#define O_MASK 0x0001 + +#define HWID_OFFSET 4 +#define DIR_OFFSET 3 + enum erspan_encap_type { ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ @@ -45,20 +113,72 @@ enum erspan_encap_type { ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ }; -struct erspan_metadata { - __be32 index; /* type II */ -}; +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 -struct erspanhdr { - __be16 ver_vlan; -#define VER_OFFSET 12 - __be16 session_id; -#define COS_OFFSET 13 -#define EN_OFFSET 11 -#define T_OFFSET 10 - struct erspan_metadata md; +struct erspan_base_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 vlan_upper:4, + ver:4; + __u8 vlan:8; + __u8 session_id_upper:2, + t:1, + en:2, + cos:3; + __u8 session_id:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 ver: 4, + vlan_upper:4; + __u8 vlan:8; + __u8 cos:3, + en:2, + t:1, + session_id_upper:2; + __u8 session_id:8; +#else +#error "Please fix " +#endif }; +static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id) +{ + ershdr->session_id = id & 0xff; + ershdr->session_id_upper = (id >> 8) & 0x3; +} + +static inline u16 get_session_id(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->session_id_upper << 8) + ershdr->session_id; +} + +static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan) +{ + ershdr->vlan = vlan & 0xff; + ershdr->vlan_upper = (vlan >> 8) & 0xf; +} + +static inline u16 get_vlan(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->vlan_upper << 8) + ershdr->vlan; +} + +static inline void set_hwid(struct erspan_md2 *md2, u8 hwid) +{ + md2->hwid = hwid & 0xf; + md2->hwid_upper = (hwid >> 4) & 0x3; +} + +static inline u8 get_hwid(const struct erspan_md2 *md2) +{ + return (md2->hwid_upper << 4) + md2->hwid; +} + +static inline int erspan_hdr_len(int version) +{ + return sizeof(struct erspan_base_hdr) + + (version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE); +} + static inline u8 tos_to_cos(u8 tos) { u8 dscp, cos; @@ -69,18 +189,19 @@ static inline u8 tos_to_cos(u8 tos) } static inline void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, + u32 id, u32 index, bool truncate, bool is_ipv4) { - struct ethhdr *eth = eth_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb->data; enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; + struct erspan_base_hdr *ershdr; struct qtag_prefix { __be16 eth_type; __be16 tci; } *qp; u16 vlan_tci = 0; u8 tos; + __be32 *idx; tos = is_ipv4 ? ip_hdr(skb)->tos : (ipv6_hdr(skb)->priority << 4) + @@ -97,17 +218,94 @@ static inline void erspan_build_header(struct sk_buff *skb, enc_type = ERSPAN_ENCAP_INFRAME; } - skb_push(skb, sizeof(*ershdr)); - ershdr = (struct erspanhdr *)skb->data; - memset(ershdr, 0, sizeof(*ershdr)); - - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION << VER_OFFSET)); - ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | - (enc_type << EN_OFFSET & EN_MASK) | - ((truncate << T_OFFSET) & T_MASK)); - ershdr->md.index = htonl(index & INDEX_MASK); + skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + + /* Build base header */ + ershdr->ver = ERSPAN_VERSION; + ershdr->cos = tos_to_cos(tos); + ershdr->en = enc_type; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + set_session_id(ershdr, id); + + /* Build metadata */ + idx = (__be32 *)(ershdr + 1); + *idx = htonl(index & INDEX_MASK); +} + +/* ERSPAN GRA: timestamp granularity + * 00b --> granularity = 100 microseconds + * 01b --> granularity = 100 nanoseconds + * 10b --> granularity = IEEE 1588 + * Here we only support 100 microseconds. + */ +static inline __be32 erspan_get_timestamp(void) +{ + u64 h_usecs; + ktime_t kt; + + kt = ktime_get_real(); + h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC); + + /* ERSPAN base header only has 32-bit, + * so it wraps around 4 days. + */ + return htonl((u32)h_usecs); +} + +static inline void erspan_build_header_v2(struct sk_buff *skb, + u32 id, u8 direction, u16 hwid, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = (struct ethhdr *)skb->data; + struct erspan_base_hdr *ershdr; + struct erspan_md2 *md2; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u8 gra = 0; /* 100 usec */ + u8 bso = 0; /* Bad/Short/Oversized */ + u8 sgt = 0; + u8 tos; + + tos = is_ipv4 ? ip_hdr(skb)->tos : + (ipv6_hdr(skb)->priority << 4) + + (ipv6_hdr(skb)->flow_lbl[0] >> 4); + + /* Unlike v1, v2 does not have En field, + * so only extract vlan tci field. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + } + + skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + + /* Build base header */ + ershdr->ver = ERSPAN_VERSION2; + ershdr->cos = tos_to_cos(tos); + ershdr->en = bso; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + set_session_id(ershdr, id); + + /* Build metadata */ + md2 = (struct erspan_md2 *)(ershdr + 1); + md2->timestamp = erspan_get_timestamp(); + md2->sgt = htons(sgt); + md2->p = 1; + md2->ft = 0; + md2->dir = direction; + md2->gra = gra; + md2->o = 0; + set_hwid(md2, hwid); } #endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 78422c8..11a95a5 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -15,6 +15,23 @@ static inline int rpl_ipgre_init(void) static inline void rpl_ipgre_fini(void) {} +static inline int rpl_ip6gre_init(void) +{ + return 0; +} + +static inline void rpl_ip6gre_fini(void) +{} + +static inline int rpl_ip6_tunnel_init(void) +{ + return 0; +} + +static inline void rpl_ip6_tunnel_cleanup(void) +{ +} + #define gre_fb_xmit dev_queue_xmit #ifdef CONFIG_INET @@ -132,6 +149,10 @@ void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, int rpl_ipgre_init(void); void rpl_ipgre_fini(void); +int rpl_ip6gre_init(void); +void rpl_ip6gre_fini(void); +int rpl_ip6_tunnel_init(void); +void rpl_ip6_tunnel_cleanup(void); #define gretap_fb_dev_create rpl_gretap_fb_dev_create struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, @@ -147,6 +168,10 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define ipgre_init rpl_ipgre_init #define ipgre_fini rpl_ipgre_fini +#define ip6gre_init rpl_ip6gre_init +#define ip6gre_fini rpl_ip6gre_fini +#define ip6_tunnel_init rpl_ip6_tunnel_init +#define ip6_tunnel_cleanup rpl_ip6_tunnel_cleanup #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); diff --git a/datapath/linux/compat/include/net/ip6_tunnel.h b/datapath/linux/compat/include/net/ip6_tunnel.h index b0917d8..e0a33a6 100644 --- a/datapath/linux/compat/include/net/ip6_tunnel.h +++ b/datapath/linux/compat/include/net/ip6_tunnel.h @@ -1,14 +1,208 @@ -#ifndef _NET_IP6_TUNNEL_WRAPER_H -#define _NET_IP6_TUNNEL_WRAPER_H +#ifndef NET_IP6_TUNNEL_WRAPPER_H +#define NET_IP6_TUNNEL_WRAPPER_H 1 + +#ifdef HAVE_IP6_TNL_PARM_ERSPAN_VER +#include_next +#else #include #include #include #include -#include_next +#include +#include +#include +#include "gso.h" + +#define IP6TUNNEL_ERR_TIMEO (30*HZ) + +/* capable of sending packets */ +#define IP6_TNL_F_CAP_XMIT 0x10000 +/* capable of receiving packets */ +#define IP6_TNL_F_CAP_RCV 0x20000 +/* determine capability on a per-packet basis */ +#define IP6_TNL_F_CAP_PER_PACKET 0x40000 + +#ifndef IP6_TNL_F_ALLOW_LOCAL_REMOTE +#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0 +#endif + +struct rpl__ip6_tnl_parm { + char name[IFNAMSIZ]; /* name of tunnel device */ + int link; /* ifindex of underlying L2 interface */ + __u8 proto; /* tunnel protocol */ + __u8 encap_limit; /* encapsulation limit for tunnel */ + __u8 hop_limit; /* hop limit for tunnel */ + bool collect_md; + __be32 flowinfo; /* traffic class and flowlabel for tunnel */ + __u32 flags; /* tunnel flags */ + struct in6_addr laddr; /* local tunnel end-point address */ + struct in6_addr raddr; /* remote tunnel end-point address */ + + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; + + __u32 fwmark; + __u32 index; /* ERSPAN type II index */ + __u8 erspan_ver; /* ERSPAN version */ + __u8 dir; /* direction */ + __u16 hwid; /* hwid */ +}; + +#define __ip6_tnl_parm rpl__ip6_tnl_parm + +/* IPv6 tunnel */ +struct rpl_ip6_tnl { + struct rpl_ip6_tnl __rcu *next; /* next tunnel in list */ + struct net_device *dev; /* virtual device associated with tunnel */ + struct net *net; /* netns for packet i/o */ + struct __ip6_tnl_parm parms; /* tunnel configuration parameters */ + struct flowi fl; /* flowi template for xmit */ + struct dst_cache dst_cache; /* cached dst */ + struct gro_cells gro_cells; + + int err_count; + unsigned long err_time; + + /* These fields used only by GRE */ + __u32 i_seqno; /* The last seen seqno */ + __u32 o_seqno; /* The last output seqno */ + int hlen; /* tun_hlen + encap_hlen */ + int tun_hlen; /* Precalculated header length */ + int encap_hlen; /* Encap header length (FOU,GUE) */ + struct ip_tunnel_encap encap; + int mlink; +}; + +#define ip6_tnl rpl_ip6_tnl + +struct rpl_ip6_tnl_encap_ops { + size_t (*encap_hlen)(struct ip_tunnel_encap *e); + int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, + u8 *protocol, struct flowi6 *fl6); +}; + +#define ip6_tnl_encap_ops rpl_ip6_tnl_encap_ops + +#ifdef CONFIG_INET + +#ifndef MAX_IPTUN_ENCAP_OPS +#define MAX_IPTUN_ENCAP_OPS 8 +#endif + +extern const struct ip6_tnl_encap_ops __rcu * + rpl_ip6tun_encaps[MAX_IPTUN_ENCAP_OPS]; + +int rpl_ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num); +#define ip6_tnl_encap_add_ops rpl_ip6_tnl_encap_add_ops +int rpl_ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num); +#define ip6_tnl_encap_del_ops rpl_ip6_tnl_encap_del_ops +int rpl_ip6_tnl_encap_setup(struct ip6_tnl *t, + struct ip_tunnel_encap *ipencap); +#define ip6_tnl_encap_setup rpl_ip6_tnl_encap_setup + +#ifndef HAVE_TUNNEL_ENCAP_TYPES +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, +}; + +#endif +static inline int ip6_encap_hlen(struct ip_tunnel_encap *e) +{ + const struct ip6_tnl_encap_ops *ops; + int hlen = -EINVAL; + + if (e->type == TUNNEL_ENCAP_NONE) + return 0; + + if (e->type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_ip6tun_encaps[e->type]); + if (likely(ops && ops->encap_hlen)) + hlen = ops->encap_hlen(e); + rcu_read_unlock(); + + return hlen; +} + +static inline int ip6_tnl_encap(struct sk_buff *skb, struct ip6_tnl *t, + u8 *protocol, struct flowi6 *fl6) +{ + const struct ip6_tnl_encap_ops *ops; + int ret = -EINVAL; + + if (t->encap.type == TUNNEL_ENCAP_NONE) + return 0; + + if (t->encap.type >= MAX_IPTUN_ENCAP_OPS) + return -EINVAL; + + rcu_read_lock(); + ops = rcu_dereference(rpl_ip6tun_encaps[t->encap.type]); + if (likely(ops && ops->build_header)) + ret = ops->build_header(skb, &t->encap, protocol, fl6); + rcu_read_unlock(); + + return ret; +} + +/* Tunnel encapsulation limit destination sub-option */ + +struct ipv6_tlv_tnl_enc_lim { + __u8 type; /* type-code for option */ + __u8 length; /* option length */ + __u8 encap_limit; /* tunnel encapsulation limit */ +} __packed; + +int rpl_ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_rcv_ctl rpl_ip6_tnl_rcv_ctl +int rpl_ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + bool log_ecn_error); +#define ip6_tnl_rcv rpl_ip6_tnl_rcv +int rpl_ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_xmit_ctl rpl_ip6_tnl_xmit_ctl +int rpl_ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, __u32 *pmtu, + __u8 proto); +#define ip6_tnl_xmit rpl_ip6_tnl_xmit +__u16 rpl_ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw); +#define ip6_tnl_parse_tlv_enc_lim rpl_ip6_tnl_parse_tlv_enc_lim +__u32 rpl_ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr, + const struct in6_addr *raddr); +#define ip6_tnl_get_cap rpl_ip6_tnl_get_cap +struct net *rpl_ip6_tnl_get_link_net(const struct net_device *dev); +#define ip6_tnl_get_link_net rpl_ip6_tnl_get_link_net +int rpl_ip6_tnl_get_iflink(const struct net_device *dev); +#define ip6_tnl_get_iflink rpl_ip6_tnl_get_iflink +int rpl_ip6_tnl_change_mtu(struct net_device *dev, int new_mtu); +#define ip6_tnl_change_mtu rpl_ip6_tnl_change_mtu + +static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, + struct net_device *dev) +{ + int pkt_len, err; + + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + pkt_len = skb->len - skb_inner_network_offset(skb); + err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); + if (unlikely(net_xmit_eval(err))) + pkt_len = -1; + iptunnel_xmit_stats(dev, pkt_len); +} +#endif -#define ip6tunnel_xmit rpl_ip6tunnel_xmit -void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, - struct net_device *dev); +#endif /* HAVE_IP6_TNL_PARM_ERSPAN_VER */ #endif diff --git a/datapath/linux/compat/include/net/ipv6.h b/datapath/linux/compat/include/net/ipv6.h index 7fc0339..6379457 100644 --- a/datapath/linux/compat/include/net/ipv6.h +++ b/datapath/linux/compat/include/net/ipv6.h @@ -39,6 +39,35 @@ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; } +#ifndef HAVE_IP6_MAKE_FLOWLABEL_FL6 +#define ip6_make_flowlabel rpl_ip6_make_flowlabel +static inline __be32 rpl_ip6_make_flowlabel(struct net *net, + struct sk_buff *skb, + __be32 flowlabel, bool autolabel, + struct flowi6 *fl6) +{ +#ifndef HAVE_NETNS_SYSCTL_IPV6_AUTO_FLOWLABELS + if (!flowlabel && autolabel) { +#else + if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) { +#endif + u32 hash; + + hash = skb_get_hash(skb); + + /* Since this is being sent on the wire obfuscate hash a bit + * to minimize possbility that any useful information to an + * attacker is leaked. Only lower 20 bits are relevant. + */ + hash ^= hash >> 12; + + flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK; + } + + return flowlabel; +} +#endif + #ifndef IPV6_TCLASS_SHIFT #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) #define IPV6_TCLASS_SHIFT 20 diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c new file mode 100644 index 0000000..23b1c83 --- /dev/null +++ b/datapath/linux/compat/ip6_gre.c @@ -0,0 +1,2578 @@ +/* + * GRE over IPv6 protocol decoder. + * + * Authors: Dmitry Kozlov (xeb@mail.ru) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#ifndef USE_UPSTREAM_TUNNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "vport-netdev.h" + +#define IP6_GRE_HASH_SIZE_SHIFT 5 +#define IP6_GRE_HASH_SIZE (1 << IP6_GRE_HASH_SIZE_SHIFT) + +static unsigned int ip6gre_net_id __read_mostly; +struct ip6gre_net { + struct ip6_tnl __rcu *tunnels[4][IP6_GRE_HASH_SIZE]; + + struct ip6_tnl __rcu *collect_md_tun; + struct net_device *fb_tunnel_dev; +}; + +static struct rtnl_link_ops ip6gre_link_ops __read_mostly; +static struct rtnl_link_ops ip6gre_tap_ops __read_mostly; +static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly; +static int ip6gre_tunnel_init(struct net_device *dev); +static void ip6gre_tunnel_setup(struct net_device *dev); +static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); +static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); + +#define gre_calc_hlen rpl_ip_gre_calc_hlen +static int rpl_ip_gre_calc_hlen(__be16 o_flags) +{ + int addend = 4; + + if (o_flags & TUNNEL_CSUM) + addend += 4; + if (o_flags & TUNNEL_KEY) + addend += 4; + if (o_flags & TUNNEL_SEQ) + addend += 4; + return addend; +} + +/* Tunnel hash table */ + +/* + 4 hash tables: + + 3: (remote,local) + 2: (remote,*) + 1: (*,local) + 0: (*,*) + + We require exact key match i.e. if a key is present in packet + it will match only tunnel with the same key; if it is not present, + it will match only keyless tunnel. + + All keysless packets, if not matched configured keyless tunnels + will match fallback tunnel. + */ + +#define HASH_KEY(key) (((__force u32)key^((__force u32)key>>4))&(IP6_GRE_HASH_SIZE - 1)) +static u32 HASH_ADDR(const struct in6_addr *addr) +{ + u32 hash = ipv6_addr_hash(addr); + + return hash_32(hash, IP6_GRE_HASH_SIZE_SHIFT); +} + +#define tunnels_r_l tunnels[3] +#define tunnels_r tunnels[2] +#define tunnels_l tunnels[1] +#define tunnels_wc tunnels[0] + +/* Given src, dst and key, find appropriate for input tunnel. */ + +static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, + const struct in6_addr *remote, const struct in6_addr *local, + __be32 key, __be16 gre_proto) +{ + struct net *net = dev_net(dev); + int link = dev->ifindex; + unsigned int h0 = HASH_ADDR(remote); + unsigned int h1 = HASH_KEY(key); + struct ip6_tnl *t, *cand = NULL; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + int dev_type = (gre_proto == htons(ETH_P_TEB) || + gre_proto == htons(ETH_P_ERSPAN)) ? + ARPHRD_ETHER : ARPHRD_IP6GRE; + int score, cand_score = 4; + + for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) { + if (!ipv6_addr_equal(local, &t->parms.laddr) || + !ipv6_addr_equal(remote, &t->parms.raddr) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) { + if (!ipv6_addr_equal(remote, &t->parms.raddr) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) { + if ((!ipv6_addr_equal(local, &t->parms.laddr) && + (!ipv6_addr_equal(local, &t->parms.raddr) || + !ipv6_addr_is_multicast(local))) || + key != t->parms.i_key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) { + if (t->parms.i_key != key || + !(t->dev->flags & IFF_UP)) + continue; + + if (t->dev->type != ARPHRD_IP6GRE && + t->dev->type != dev_type) + continue; + + score = 0; + if (t->parms.link != link) + score |= 1; + if (t->dev->type != dev_type) + score |= 2; + if (score == 0) + return t; + + if (score < cand_score) { + cand = t; + cand_score = score; + } + } + + if (cand) + return cand; + + t = rcu_dereference(ign->collect_md_tun); + if (t && t->dev->flags & IFF_UP) + return t; + + dev = ign->fb_tunnel_dev; + if (dev->flags & IFF_UP) + return netdev_priv(dev); + + return NULL; +} + +static struct ip6_tnl __rcu **__ip6gre_bucket(struct ip6gre_net *ign, + const struct __ip6_tnl_parm *p) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + unsigned int h = HASH_KEY(p->i_key); + int prio = 0; + + if (!ipv6_addr_any(local)) + prio |= 1; + if (!ipv6_addr_any(remote) && !ipv6_addr_is_multicast(remote)) { + prio |= 2; + h ^= HASH_ADDR(remote); + } + + return &ign->tunnels[prio][h]; +} + +static inline struct ip6_tnl __rcu **ip6gre_bucket(struct ip6gre_net *ign, + const struct ip6_tnl *t) +{ + return __ip6gre_bucket(ign, &t->parms); +} + +static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp = ip6gre_bucket(ign, t); + + if (t->parms.collect_md) + rcu_assign_pointer(ign->collect_md_tun, t); + + rcu_assign_pointer(t->next, rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); +} + +static void ip6gre_tunnel_unlink(struct ip6gre_net *ign, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp; + struct ip6_tnl *iter; + + if (t->parms.collect_md) + rcu_assign_pointer(ign->collect_md_tun, NULL); + + for (tp = ip6gre_bucket(ign, t); + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { + rcu_assign_pointer(*tp, t->next); + break; + } + } +} + +static struct ip6_tnl *ip6gre_tunnel_find(struct net *net, + const struct __ip6_tnl_parm *parms, + int type) +{ + const struct in6_addr *remote = &parms->raddr; + const struct in6_addr *local = &parms->laddr; + __be32 key = parms->i_key; + int link = parms->link; + struct ip6_tnl *t; + struct ip6_tnl __rcu **tp; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + for (tp = __ip6gre_bucket(ign, parms); + (t = rtnl_dereference(*tp)) != NULL; + tp = &t->next) + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr) && + key == t->parms.i_key && + link == t->parms.link && + type == t->dev->type) + break; + + return t; +} + +static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, + const struct __ip6_tnl_parm *parms, int create) +{ + struct ip6_tnl *t, *nt; + struct net_device *dev; + char name[IFNAMSIZ]; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); + if (t && create) + return NULL; + if (t || !create) + return t; + + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else + strcpy(name, "ip6gre%d"); + + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, + ip6gre_tunnel_setup); + if (!dev) + return NULL; + + dev_net_set(dev, net); + + nt = netdev_priv(dev); + nt->parms = *parms; + dev->rtnl_link_ops = &ip6gre_link_ops; + + nt->dev = dev; + nt->net = dev_net(dev); + + if (register_netdevice(dev) < 0) + goto failed_free; + + ip6gre_tnl_link_config(nt, 1); + + /* Can use a lockless transmit, unless we generate output sequences */ + if (!(nt->parms.o_flags & TUNNEL_SEQ)) + dev->features |= NETIF_F_LLTX; + + dev_hold(dev); + ip6gre_tunnel_link(ign, nt); + return nt; + +failed_free: + free_netdev(dev); + return NULL; +} + +static void ip6gre_tunnel_uninit(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); + + ip6gre_tunnel_unlink(ign, t); + dst_cache_reset(&t->dst_cache); + dev_put(dev); +} + + +static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ +#if 0 + struct net *net = dev_net(skb->dev); + const struct gre_base_hdr *greh; + const struct ipv6hdr *ipv6h; + int grehlen = sizeof(*greh); + struct ip6_tnl *t; + int key_off = 0; + __be16 flags; + __be32 key; + + if (!pskb_may_pull(skb, offset + grehlen)) + return; + greh = (const struct gre_base_hdr *)(skb->data + offset); + flags = greh->flags; + if (flags & (GRE_VERSION | GRE_ROUTING)) + return; + if (flags & GRE_CSUM) + grehlen += 4; + if (flags & GRE_KEY) { + key_off = grehlen + offset; + grehlen += 4; + } + + if (!pskb_may_pull(skb, offset + grehlen)) + return; + ipv6h = (const struct ipv6hdr *)skb->data; + greh = (const struct gre_base_hdr *)(skb->data + offset); + key = key_off ? *(__be32 *)(skb->data + key_off) : 0; + + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, + key, greh->protocol); + if (!t) + return; + + switch (type) { + struct ipv6_tlv_tnl_enc_lim *tel; + __u32 teli; + case ICMPV6_DEST_UNREACH: + net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", + t->parms.name); + if (code != ICMPV6_PORT_UNREACH) + break; + return; + case ICMPV6_TIME_EXCEED: + if (code == ICMPV6_EXC_HOPLIMIT) { + net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", + t->parms.name); + break; + } + return; + case ICMPV6_PARAMPROB: + teli = 0; + if (code == ICMPV6_HDR_FIELD) + teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); + + if (teli && teli == be32_to_cpu(info) - 2) { + tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; + if (tel->encap_limit == 0) { + net_dbg_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", + t->parms.name); + } + } else { + net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", + t->parms.name); + } + return; + case ICMPV6_PKT_TOOBIG: + ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + return; + case NDISC_REDIRECT: + ip6_redirect(skb, net, skb->dev->ifindex, 0, + sock_net_uid(net, NULL)); + return; + } + + if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) + t->err_count++; + else + t->err_count = 1; + t->err_time = jiffies; +#endif +} + +static struct dst_ops md_dst_ops = { + .family = AF_UNSPEC, +}; + +#ifndef DST_METADATA +#define DST_METADATA 0x0080 +#endif + +static void rpl__metadata_dst_init(struct metadata_dst *md_dst, + enum metadata_type type, u8 optslen) + +{ + struct dst_entry *dst; + + dst = &md_dst->dst; + dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE, + DST_METADATA | DST_NOCOUNT); + +#if 0 + /* unused in OVS */ + dst->input = dst_md_discard; + dst->output = dst_md_discard_out; +#endif + memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst)); + md_dst->type = type; +} + +static struct metadata_dst *erspan_rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, + gfp_t flags) +{ + struct metadata_dst *md_dst; + + md_dst = kmalloc(sizeof(*md_dst) + optslen, flags); + if (!md_dst) + return NULL; + + rpl__metadata_dst_init(md_dst, type, optslen); + + return md_dst; +} +static inline struct metadata_dst *rpl_tun_rx_dst(int md_size) +{ + struct metadata_dst *tun_dst; + + tun_dst = erspan_rpl_metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC); + if (!tun_dst) + return NULL; + + tun_dst->u.tun_info.options_len = 0; + tun_dst->u.tun_info.mode = 0; + return tun_dst; +} +static inline +struct metadata_dst *rpl__ipv6_tun_set_dst(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u8 tos, __u8 ttl, + __be16 tp_dst, + __be32 label, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + struct metadata_dst *tun_dst; + struct ip_tunnel_info *info; + + tun_dst = rpl_tun_rx_dst(md_size); + if (!tun_dst) + return NULL; + + info = &tun_dst->u.tun_info; + info->mode = IP_TUNNEL_INFO_IPV6; + info->key.tun_flags = flags; + info->key.tun_id = tunnel_id; + info->key.tp_src = 0; + info->key.tp_dst = tp_dst; + + info->key.u.ipv6.src = *saddr; + info->key.u.ipv6.dst = *daddr; + + info->key.tos = tos; + info->key.ttl = ttl; + info->key.label = label; + + return tun_dst; +} + +static inline struct metadata_dst *rpl_ipv6_tun_rx_dst(struct sk_buff *skb, + __be16 flags, + __be64 tunnel_id, + int md_size) +{ + const struct ipv6hdr *ip6h = ipv6_hdr(skb); + + return rpl__ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr, + ipv6_get_dsfield(ip6h), ip6h->hop_limit, + 0, ip6_flowlabel(ip6h), flags, tunnel_id, + md_size); +} + +static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +{ + const struct ipv6hdr *ipv6h; + struct ip6_tnl *tunnel; + + ipv6h = ipv6_hdr(skb); + tunnel = ip6gre_tunnel_lookup(skb->dev, + &ipv6h->saddr, &ipv6h->daddr, tpi->key, + tpi->proto); + if (tunnel) { + struct metadata_dst *tun_dst = NULL; + if (tunnel->parms.collect_md) { + __be64 tun_id; + __be16 flags; + + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ipv6_tun_rx_dst(skb, flags, tun_id, 0); + if (!tun_dst) + return PACKET_REJECT; + + } + + skb_reset_mac_header(skb); + ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + kfree(tun_dst); + return PACKET_RCVD; + } + + return PACKET_RCVD; +} + +static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, + struct tnl_ptk_info *tpi) +{ + struct erspan_base_hdr *ershdr; + struct erspan_metadata *pkt_md; + const struct ipv6hdr *ipv6h; + struct erspan_md2 *md2; + struct ip6_tnl *tunnel; + u8 ver; + + if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) + return PACKET_REJECT; + + ipv6h = ipv6_hdr(skb); + ershdr = (struct erspan_base_hdr *)skb->data; + ver = ershdr->ver; + tpi->key = cpu_to_be32(get_session_id(ershdr)); + + tunnel = ip6gre_tunnel_lookup(skb->dev, + &ipv6h->saddr, &ipv6h->daddr, 0, + tpi->proto); + if (tunnel) { + struct metadata_dst *tun_dst = NULL; + int len = erspan_hdr_len(ver); + + if (unlikely(!pskb_may_pull(skb, len))) + return PACKET_REJECT; + + ershdr = (struct erspan_base_hdr *)skb->data; + pkt_md = (struct erspan_metadata *)(ershdr + 1); + + if (__iptunnel_pull_header(skb, len, + htons(ETH_P_TEB), + false, false) < 0) + return PACKET_REJECT; + + if (tunnel->parms.collect_md) { + struct ip_tunnel_info *info; + struct erspan_metadata *md; + __be64 tun_id; + __be16 flags; + + tpi->flags |= TUNNEL_KEY; + flags = tpi->flags; + tun_id = key32_to_tunnel_id(tpi->key); + + tun_dst = rpl_ipv6_tun_rx_dst(skb, flags, tun_id, + sizeof(*md)); + if (!tun_dst) + return PACKET_REJECT; + + info = &tun_dst->u.tun_info; + md = ip_tunnel_info_opts(info); + md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); + info->key.tun_flags |= TUNNEL_ERSPAN_OPT; + info->options_len = sizeof(*md); + } + + ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, false); + kfree(tun_dst); + return PACKET_RCVD; + } + + kfree(skb); + return PACKET_RCVD; +} + +static int gre_rcv(struct sk_buff *skb) +{ + struct tnl_ptk_info tpi; + bool csum_err = false; + int hdr_len; + + hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IPV6), 0); + if (hdr_len < 0) + goto drop; + + if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) + goto drop; + + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { + if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD) + return 0; + goto out; + } + + if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD) + return 0; + +out: + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); +drop: + kfree_skb(skb); + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#include "gso.h" +/* gre_handle_offloads() has different return type on older kernsl. */ +static void gre_nop_fix(struct sk_buff *skb) { } + +static void gre_csum_fix(struct sk_buff *skb) +{ + struct gre_base_hdr *greh; + __be32 *options; + int gre_offset = skb_transport_offset(skb); + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + options = ((__be32 *)greh + 1); + + *options = 0; + *(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset, + skb->len - gre_offset, 0)); +} + +#define gre_handle_offloads rpl_gre_handle_offloads +static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; + gso_fix_segment_t fix_segment; + + if (gre_csum) + fix_segment = gre_csum_fix; + else + fix_segment = gre_nop_fix; + + return ovs_iptunnel_handle_offloads(skb, type, fix_segment); +} +#else +static int gre_handle_offloads(struct sk_buff *skb, bool csum) +{ + return iptunnel_handle_offloads(skb, + csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); + +#endif + +static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, __u8 *dsfield, + int *encap_limit) +{ + const struct iphdr *iph = ip_hdr(skb); + struct ip6_tnl *t = netdev_priv(dev); + + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + *encap_limit = t->parms.encap_limit; + + memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6)); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + *dsfield = ipv4_get_dsfield(iph); + else + *dsfield = ip6_tclass(t->parms.flowinfo); + +#ifndef IP6_TNL_F_USE_ORIG_FWMARK + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6->flowi6_mark = skb->mark; + else + fl6->flowi6_mark = t->parms.fwmark; + + fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); +#endif +} + +static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, __u8 *dsfield, + int *encap_limit) +{ + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + struct ip6_tnl *t = netdev_priv(dev); + __u16 offset; + + offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); + /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ + + if (offset > 0) { + struct ipv6_tlv_tnl_enc_lim *tel; + + tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; + if (tel->encap_limit == 0) { + icmpv6_send(skb, ICMPV6_PARAMPROB, + ICMPV6_HDR_FIELD, offset + 2); + return -1; + } + *encap_limit = tel->encap_limit - 1; + } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { + *encap_limit = t->parms.encap_limit; + } + + memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6)); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + *dsfield = ipv6_get_dsfield(ipv6h); + else + *dsfield = ip6_tclass(t->parms.flowinfo); + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) + fl6->flowlabel |= ip6_flowlabel(ipv6h); + +#ifndef IP6_TNL_F_USE_ORIG_FWMARK + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6->flowi6_mark = skb->mark; + else + fl6->flowi6_mark = t->parms.fwmark; + + fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); +#endif + + return 0; +} + +static netdev_tx_t __gre6_xmit(struct sk_buff *skb, + struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, + __u32 *pmtu, __be16 proto) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + struct tnl_ptk_info tpi; + __be16 protocol; + + if (dev->type == ARPHRD_ETHER) + IPCB(skb)->flags = 0; + + if (dev->header_ops && dev->type == ARPHRD_IP6GRE) + fl6->daddr = ((struct ipv6hdr *)skb->data)->daddr; + else + fl6->daddr = tunnel->parms.raddr; + + if (tunnel->parms.o_flags & TUNNEL_SEQ) + tunnel->o_seqno++; + + /* Push GRE header. */ + protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto; + + if (tunnel->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + __be16 flags; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || + !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -EINVAL; + + key = &tun_info->key; + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_proto = IPPROTO_GRE; + fl6->daddr = key->u.ipv6.dst; + fl6->flowlabel = key->label; +// FIX ME! +// fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + dsfield = key->tos; + flags = key->tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); + tunnel->tun_hlen = gre_calc_hlen(flags); + + tpi.flags = flags; + tpi.proto = protocol; + tpi.key = tunnel_id_to_key32(key->tun_id); + tpi.seq = htonl(tunnel->o_seqno++); + tpi.hdr_len = tunnel->tun_hlen; + + gre_build_header(skb, &tpi, 8); + } else { + tpi.flags = tunnel->parms.o_flags; + tpi.proto = protocol; + tpi.key = tunnel->parms.o_key; + tpi.seq = htonl(tunnel->o_seqno++); + tpi.hdr_len = tunnel->tun_hlen; + + gre_build_header(skb, &tpi, 8); + } + + return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, + NEXTHDR_GRE); +} + +static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield = 0; + __u32 mtu; + int err; + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + + if (!t->parms.collect_md) + prepare_ip6gre_xmit_ipv4(skb, dev, &fl6, + &dsfield, &encap_limit); + + err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); + if (err) + return -1; + + err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + skb->protocol); + if (err != 0) { + /* XXX: send ICMP error even if DF is not set. */ + if (err == -EMSGSIZE) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + return -1; + } + + return 0; +} + +static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield = 0; + __u32 mtu; + int err; + + if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr)) + return -1; + + if (!t->parms.collect_md && + prepare_ip6gre_xmit_ipv6(skb, dev, &fl6, &dsfield, &encap_limit)) + return -1; + + if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM))) + return -1; + + err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, + &mtu, skb->protocol); + if (err != 0) { + if (err == -EMSGSIZE) + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -1; + } + + return 0; +} + +/** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device + * @hdr: IPv6 header from the incoming packet + * + * Description: + * Avoid trivial tunneling loop by checking that tunnel exit-point + * doesn't match source of incoming packet. + * + * Return: + * 1 if conflict, + * 0 else + **/ + +static inline bool ip6gre_tnl_addr_conflict(const struct ip6_tnl *t, + const struct ipv6hdr *hdr) +{ + return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); +} + +static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int encap_limit = -1; + struct flowi6 fl6; + __u32 mtu; + int err; + + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + encap_limit = t->parms.encap_limit; + + if (!t->parms.collect_md) + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + + err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); + if (err) + return err; + + err = __gre6_xmit(skb, dev, 0, &fl6, encap_limit, &mtu, skb->protocol); + + return err; +} + +static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net_device_stats *stats = &t->dev->stats; + int ret; + + if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) + goto tx_err; + + switch (skb->protocol) { + case htons(ETH_P_IP): + ret = ip6gre_xmit_ipv4(skb, dev); + break; + case htons(ETH_P_IPV6): + ret = ip6gre_xmit_ipv6(skb, dev); + break; + default: + ret = ip6gre_xmit_other(skb, dev); + break; + } + + if (ret < 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static netdev_tx_t __ip6gre_tunnel_xmit(struct sk_buff *skb) +{ + return ip6gre_tunnel_xmit(skb, skb->dev); +} + +static bool erspan_skb_would_panic(struct sk_buff *skb, int erspan_md_size) +{ + /* check if there is enough headroom in packet, if not + * drop it. Checking for 8 bytes of gre header space + + * erspan base hdr and erspan type specific header. + */ + if (skb_headroom(skb) < (8 + sizeof(struct erspan_base_hdr) + + erspan_md_size)) + return true; + + return false; +} + +static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct dst_entry *dst = skb_dst(skb); + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + struct net_device_stats *stats; + struct erspan_metadata *md; + struct tnl_ptk_info tpi; + bool truncate = false; + int encap_limit = -1; + __u8 dsfield = false; + struct flowi6 fl6; + int err = -EINVAL; + __be32 tun_id; + __u32 mtu; + + + /* OVS doesn't support native mode ip6 tunnel traffic so + * take an early exit in that case. */ + if (!t->parms.collect_md) + goto tx_err; + + if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr)) + goto tx_err; + + if (gre_handle_offloads(skb, false)) + goto tx_err; + + if (skb->len > dev->mtu + dev->hard_header_len) { + pskb_trim(skb, dev->mtu + dev->hard_header_len); + truncate = true; + } + + t->parms.o_flags &= ~TUNNEL_KEY; + IPCB(skb)->flags = 0; + + tun_info = ovs_skb_tunnel_info(skb); + if (unlikely(!tun_info || + !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -EINVAL; + + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_GRE; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + // fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + dsfield = key->tos; + md = ip_tunnel_info_opts(tun_info); + if (!md) + goto tx_err; + + if (erspan_skb_would_panic(skb, + md->version == 1 ? + ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE)) + goto tx_err; + + tun_id = tunnel_id_to_key32(key->tun_id); + if (md->version == 1) { + erspan_build_header(skb, + ntohl(tun_id), + ntohl(md->u.index), truncate, + false); + tpi.hdr_len = ERSPAN_V1_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN); + } else if (md->version == 2) { + erspan_build_header_v2(skb, + ntohl(tun_id), + md->u.md2.dir, + get_hwid(&md->u.md2), + truncate, false); + tpi.hdr_len = ERSPAN_V2_MDSIZE; + tpi.proto = htons(ETH_P_ERSPAN2); + } + + tpi.flags = TUNNEL_SEQ; + tpi.key = 0; + tpi.seq = htonl(t->o_seqno++); + + /* Push GRE header. */ + gre_build_header(skb, &tpi, 8); + + /* TooBig packet may have updated dst->dev's mtu */ + if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) + dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + NEXTHDR_GRE); + if (err != 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats = &t->dev->stats; + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static netdev_tx_t __ip6erspan_tunnel_xmit(struct sk_buff *skb) +{ + return ip6erspan_tunnel_xmit(skb, skb->dev); +} + +static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) +{ + struct net_device *dev = t->dev; + struct __ip6_tnl_parm *p = &t->parms; + struct flowi6 *fl6 = &t->fl.u.ip6; + int t_hlen; + + if (dev->type != ARPHRD_ETHER) { + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + } + + /* Set up flowi template */ + fl6->saddr = p->laddr; + fl6->daddr = p->raddr; + fl6->flowi6_oif = p->link; + fl6->flowlabel = 0; + fl6->flowi6_proto = IPPROTO_GRE; + + if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) + fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; + if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) + fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; + + p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV|IP6_TNL_F_CAP_PER_PACKET); + p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr); + + if (p->flags&IP6_TNL_F_CAP_XMIT && + p->flags&IP6_TNL_F_CAP_RCV && dev->type != ARPHRD_ETHER) + dev->flags |= IFF_POINTOPOINT; + else + dev->flags &= ~IFF_POINTOPOINT; + + t->tun_hlen = gre_calc_hlen(t->parms.o_flags); + + t->hlen = t->encap_hlen + t->tun_hlen; + + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); + + struct rt6_info *rt = rt6_lookup(t->net, + &p->raddr, &p->laddr, + p->link, strict); + + if (!rt) + return; + + if (rt->dst.dev) { + dev->hard_header_len = rt->dst.dev->hard_header_len + + t_hlen; + + if (set_mtu) { + dev->mtu = rt->dst.dev->mtu - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + + if (dev->mtu < IPV6_MIN_MTU) + dev->mtu = IPV6_MIN_MTU; + } + } + ip6_rt_put(rt); + } +} + +static int ip6gre_tnl_change(struct ip6_tnl *t, + const struct __ip6_tnl_parm *p, int set_mtu) +{ + t->parms.laddr = p->laddr; + t->parms.raddr = p->raddr; + t->parms.flags = p->flags; + t->parms.hop_limit = p->hop_limit; + t->parms.encap_limit = p->encap_limit; + t->parms.flowinfo = p->flowinfo; + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.i_key = p->i_key; + t->parms.o_key = p->o_key; + t->parms.i_flags = p->i_flags; + t->parms.o_flags = p->o_flags; + t->parms.fwmark = p->fwmark; + dst_cache_reset(&t->dst_cache); + ip6gre_tnl_link_config(t, set_mtu); + return 0; +} + +static void ip6gre_tnl_parm_from_user(struct __ip6_tnl_parm *p, + const struct ip6_tnl_parm2 *u) +{ + p->laddr = u->laddr; + p->raddr = u->raddr; + p->flags = u->flags; + p->hop_limit = u->hop_limit; + p->encap_limit = u->encap_limit; + p->flowinfo = u->flowinfo; + p->link = u->link; + p->i_key = u->i_key; + p->o_key = u->o_key; + p->i_flags = gre_flags_to_tnl_flags(u->i_flags); + p->o_flags = gre_flags_to_tnl_flags(u->o_flags); + memcpy(p->name, u->name, sizeof(u->name)); +} + +static void ip6gre_tnl_parm_to_user(struct ip6_tnl_parm2 *u, + const struct __ip6_tnl_parm *p) +{ + u->proto = IPPROTO_GRE; + u->laddr = p->laddr; + u->raddr = p->raddr; + u->flags = p->flags; + u->hop_limit = p->hop_limit; + u->encap_limit = p->encap_limit; + u->flowinfo = p->flowinfo; + u->link = p->link; + u->i_key = p->i_key; + u->o_key = p->o_key; + u->i_flags = gre_tnl_flags_to_gre_flags(p->i_flags); + u->o_flags = gre_tnl_flags_to_gre_flags(p->o_flags); + memcpy(u->name, p->name, sizeof(u->name)); +} + +static int ip6gre_tunnel_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) +{ + int err = 0; + struct ip6_tnl_parm2 p; + struct __ip6_tnl_parm p1; + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + memset(&p1, 0, sizeof(p1)); + + switch (cmd) { + case SIOCGETTUNNEL: + if (dev == ign->fb_tunnel_dev) { + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { + err = -EFAULT; + break; + } + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, 0); + if (!t) + t = netdev_priv(dev); + } + memset(&p, 0, sizeof(p)); + ip6gre_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + break; + + case SIOCADDTUNNEL: + case SIOCCHGTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + goto done; + + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + goto done; + + err = -EINVAL; + if ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)) + goto done; + + if (!(p.i_flags&GRE_KEY)) + p.i_key = 0; + if (!(p.o_flags&GRE_KEY)) + p.o_key = 0; + + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, cmd == SIOCADDTUNNEL); + + if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { + if (t) { + if (t->dev != dev) { + err = -EEXIST; + break; + } + } else { + t = netdev_priv(dev); + + ip6gre_tunnel_unlink(ign, t); + synchronize_net(); + ip6gre_tnl_change(t, &p1, 1); + ip6gre_tunnel_link(ign, t); + netdev_state_change(dev); + } + } + + if (t) { + err = 0; + + memset(&p, 0, sizeof(p)); + ip6gre_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + } else + err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); + break; + + case SIOCDELTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + goto done; + + if (dev == ign->fb_tunnel_dev) { + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + goto done; + err = -ENOENT; + ip6gre_tnl_parm_from_user(&p1, &p); + t = ip6gre_tunnel_locate(net, &p1, 0); + if (!t) + goto done; + err = -EPERM; + if (t == netdev_priv(ign->fb_tunnel_dev)) + goto done; + dev = t->dev; + } + unregister_netdevice(dev); + err = 0; + break; + + default: + err = -EINVAL; + } + +done: + return err; +} + +static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h; + __be16 *p; + + ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); + ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, + t->fl.u.ip6.flowlabel, + true, &t->fl.u.ip6)); + ipv6h->hop_limit = t->parms.hop_limit; + ipv6h->nexthdr = NEXTHDR_GRE; + ipv6h->saddr = t->parms.laddr; + ipv6h->daddr = t->parms.raddr; + + p = (__be16 *)(ipv6h + 1); + p[0] = t->parms.o_flags; + p[1] = htons(type); + + /* + * Set the source hardware address. + */ + + if (saddr) + memcpy(&ipv6h->saddr, saddr, sizeof(struct in6_addr)); + if (daddr) + memcpy(&ipv6h->daddr, daddr, sizeof(struct in6_addr)); + if (!ipv6_addr_any(&ipv6h->daddr)) + return t->hlen; + + return -t->hlen; +} + +static const struct header_ops ip6gre_header_ops = { + .create = ip6gre_header, +}; + +static const struct net_device_ops ip6gre_netdev_ops = { + .ndo_init = ip6gre_tunnel_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6gre_tunnel_xmit, + .ndo_do_ioctl = ip6gre_tunnel_ioctl, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +#ifdef HAVE_NEEDS_FREE_NETDEV +static void ip6gre_dev_free(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +} + +#endif +static void ip6gre_tunnel_setup(struct net_device *dev) +{ + dev->netdev_ops = &ip6gre_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->type = ARPHRD_IP6GRE; + + dev->flags |= IFF_NOARP; + dev->addr_len = sizeof(struct in6_addr); + netif_keep_dst(dev); + /* This perm addr will be used as interface identifier by IPv6 */ + dev->addr_assign_type = NET_ADDR_RANDOM; + eth_random_addr(dev->perm_addr); +} + +#define GRE6_FEATURES (NETIF_F_SG | \ + NETIF_F_FRAGLIST | \ + NETIF_F_HIGHDMA | \ + NETIF_F_HW_CSUM) + +static void ip6gre_tnl_init_features(struct net_device *dev) +{ + struct ip6_tnl *nt = netdev_priv(dev); + + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + + if (!(nt->parms.o_flags & TUNNEL_SEQ)) { + /* TCP offload with GRE SEQ is not supported, nor + * can we support 2 levels of outer headers requiring + * an update. + */ + if (!(nt->parms.o_flags & TUNNEL_CSUM) || + nt->encap.type == TUNNEL_ENCAP_NONE) { + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; + } + + /* Can use a lockless transmit, unless we generate + * output sequences + */ + dev->features |= NETIF_F_LLTX; + } +} + +static int ip6gre_tunnel_init_common(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int ret; + int t_hlen; + + tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (ret) { + free_percpu(dev->tstats); + dev->tstats = NULL; + return ret; + } + + tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; + t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); + + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + if (tunnel->parms.collect_md) { + dev->features |= NETIF_F_NETNS_LOCAL; + netif_keep_dst(dev); + } + ip6gre_tnl_init_features(dev); + + return 0; +} + +static int ip6gre_tunnel_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int ret; + + ret = ip6gre_tunnel_init_common(dev); + if (ret) + return ret; + + tunnel = netdev_priv(dev); + + if (tunnel->parms.collect_md) + return 0; + + memcpy(dev->dev_addr, &tunnel->parms.laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &tunnel->parms.raddr, sizeof(struct in6_addr)); + + if (ipv6_addr_any(&tunnel->parms.raddr)) + dev->header_ops = &ip6gre_header_ops; + + return 0; +} + +static void ip6gre_fb_tunnel_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + tunnel->hlen = sizeof(struct ipv6hdr) + 4; + + dev_hold(dev); +} + +static struct inet6_protocol ip6gre_protocol __read_mostly = { + .handler = gre_rcv, + .err_handler = ip6gre_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) +{ + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct net_device *dev, *aux; + int prio; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == &ip6gre_link_ops || + dev->rtnl_link_ops == &ip6gre_tap_ops || + dev->rtnl_link_ops == &ip6erspan_tap_ops) + unregister_netdevice_queue(dev, head); + + for (prio = 0; prio < 4; prio++) { + int h; + for (h = 0; h < IP6_GRE_HASH_SIZE; h++) { + struct ip6_tnl *t; + + t = rtnl_dereference(ign->tunnels[prio][h]); + + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, + head); + t = rtnl_dereference(t->next); + } + } + } +} + +static int __net_init ip6gre_init_net(struct net *net) +{ + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + int err; + + ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", + NET_NAME_UNKNOWN, + ip6gre_tunnel_setup); + if (!ign->fb_tunnel_dev) { + err = -ENOMEM; + goto err_alloc_dev; + } + dev_net_set(ign->fb_tunnel_dev, net); + /* FB netdevice is special: we have one, and only one per netns. + * Allowing to move it to another netns is clearly unsafe. + */ + ign->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; + + + ip6gre_fb_tunnel_init(ign->fb_tunnel_dev); + ign->fb_tunnel_dev->rtnl_link_ops = &ip6gre_link_ops; + + err = register_netdev(ign->fb_tunnel_dev); + if (err) + goto err_reg_dev; + + rcu_assign_pointer(ign->tunnels_wc[0], + netdev_priv(ign->fb_tunnel_dev)); + return 0; + +err_reg_dev: + free_netdev(ign->fb_tunnel_dev); +err_alloc_dev: + return err; +} + +static void __net_exit ip6gre_exit_batch_net(struct list_head *net_list) +{ + struct net *net; + LIST_HEAD(list); + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) + ip6gre_destroy_tunnels(net, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); +} + +enum { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) + IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) + IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) + IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) + IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) + IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, +#endif + +}; + +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) + +static struct pernet_operations ip6gre_net_ops = { + .init = ip6gre_init_net, + .exit_batch = ip6gre_exit_batch_net, + .id = &ip6gre_net_id, + .size = sizeof(struct ip6gre_net), +}; +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + __be16 flags; + + if (!data) + return 0; + + flags = 0; + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (flags & (GRE_VERSION|GRE_ROUTING)) + return -EINVAL; + + return 0; +} +#define ip6gre_tunnel_validate rpl_ip6gre_tunnel_validate + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct in6_addr daddr; + + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + + if (!data) + goto out; + + if (data[IFLA_GRE_REMOTE]) { + daddr = nla_get_in6_addr(data[IFLA_GRE_REMOTE]); + if (ipv6_addr_any(&daddr)) + return -EINVAL; + } + +out: +#ifdef HAVE_IP6GRE_EXTACK + return ip6gre_tunnel_validate(tb, data, extack); +#else + return ip6gre_tunnel_validate(tb, data); +#endif +} +#define ip6gre_tap_validate rpl_ip6gre_tap_validate + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6erspan_tap_validate(struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6erspan_tap_validate(struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + __be16 flags = 0; + int ret, ver = 0; + + if (!data) + return 0; + +#ifdef HAVE_IP6GRE_EXTACK + ret = ip6gre_tap_validate(tb, data, extack); +#else + ret = ip6gre_tap_validate(tb, data); +#endif + if (ret) + return ret; + + /* ERSPAN should only have GRE sequence and key flag */ + if (data[IFLA_GRE_OFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); + if (data[IFLA_GRE_IFLAGS]) + flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); + if (!data[IFLA_GRE_COLLECT_METADATA] && + flags != (GRE_SEQ | GRE_KEY)) + return -EINVAL; + + /* ERSPAN Session ID only has 10-bit. Since we reuse + * 32-bit key field as ID, check it's range. + */ + if (data[IFLA_GRE_IKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_OKEY] && + (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) + return -EINVAL; + + if (data[IFLA_GRE_ERSPAN_VER]) { + ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); + if (ver != 1 && ver != 2) + return -EINVAL; + } + + if (ver == 1) { + if (data[IFLA_GRE_ERSPAN_INDEX]) { + u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + + if (index & ~INDEX_MASK) + return -EINVAL; + } + } else if (ver == 2) { + if (data[IFLA_GRE_ERSPAN_DIR]) { + u16 dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); + + if (dir & ~(DIR_MASK >> DIR_OFFSET)) + return -EINVAL; + } + + if (data[IFLA_GRE_ERSPAN_HWID]) { + u16 hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); + + if (hwid & ~(HWID_MASK >> HWID_OFFSET)) + return -EINVAL; + } + } + + return 0; +} +#define ip6erspan_tap_validate rpl_ip6erspan_tap_validate + +static void ip6gre_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) +{ +#if 0 + /* Do not use in case of OVS - our vport needs to set a parm + * directly and this erases it + */ + memset(parms, 0, sizeof(*parms)); + +#endif + if (!data) + return; + + if (data[IFLA_GRE_LINK]) + parms->link = nla_get_u32(data[IFLA_GRE_LINK]); + + if (data[IFLA_GRE_IFLAGS]) + parms->i_flags = gre_flags_to_tnl_flags( + nla_get_be16(data[IFLA_GRE_IFLAGS])); + + if (data[IFLA_GRE_OFLAGS]) + parms->o_flags = gre_flags_to_tnl_flags( + nla_get_be16(data[IFLA_GRE_OFLAGS])); + + if (data[IFLA_GRE_IKEY]) + parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); + + if (data[IFLA_GRE_OKEY]) + parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); + + if (data[IFLA_GRE_LOCAL]) + parms->laddr = nla_get_in6_addr(data[IFLA_GRE_LOCAL]); + + if (data[IFLA_GRE_REMOTE]) + parms->raddr = nla_get_in6_addr(data[IFLA_GRE_REMOTE]); + + if (data[IFLA_GRE_TTL]) + parms->hop_limit = nla_get_u8(data[IFLA_GRE_TTL]); + + if (data[IFLA_GRE_ENCAP_LIMIT]) + parms->encap_limit = nla_get_u8(data[IFLA_GRE_ENCAP_LIMIT]); + + if (data[IFLA_GRE_FLOWINFO]) + parms->flowinfo = nla_get_be32(data[IFLA_GRE_FLOWINFO]); + + if (data[IFLA_GRE_FLAGS]) + parms->flags = nla_get_u32(data[IFLA_GRE_FLAGS]); + + if (data[IFLA_GRE_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); + + if (data[IFLA_GRE_COLLECT_METADATA]) + parms->collect_md = true; + + if (data[IFLA_GRE_ERSPAN_VER]) + parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); + + if (parms->erspan_ver == 1) { + if (data[IFLA_GRE_ERSPAN_INDEX]) + parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + } else if (parms->erspan_ver == 2) { + if (data[IFLA_GRE_ERSPAN_DIR]) + parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); + if (data[IFLA_GRE_ERSPAN_HWID]) + parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); + } +} + +static int ip6gre_tap_init(struct net_device *dev) +{ + int ret; + + ret = ip6gre_tunnel_init_common(dev); + if (ret) + return ret; + + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + return 0; +} + +static const struct net_device_ops ip6gre_tap_netdev_ops = { + .ndo_init = ip6gre_tap_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6gre_tunnel_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = rpl_ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +static int ip6erspan_tap_init(struct net_device *dev) +{ + struct ip6_tnl *tunnel; + int t_hlen; + int ret; + + tunnel = netdev_priv(dev); + + tunnel->dev = dev; + tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); + if (ret) { + free_percpu(dev->tstats); + dev->tstats = NULL; + return ret; + } + + tunnel->tun_hlen = 8; + tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + + erspan_hdr_len(tunnel->parms.erspan_ver); + t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); + + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (dev->type == ARPHRD_ETHER) + dev->mtu -= ETH_HLEN; + if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + tunnel = netdev_priv(dev); + ip6gre_tnl_link_config(tunnel, 1); + + return 0; +} + +static const struct net_device_ops ip6erspan_netdev_ops = { + .ndo_init = ip6erspan_tap_init, + .ndo_uninit = ip6gre_tunnel_uninit, + .ndo_start_xmit = ip6erspan_tunnel_xmit, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats64 = ip_tunnel_get_stats64, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +static void ip6gre_tap_setup(struct net_device *dev) +{ + + ether_setup(dev); +#ifdef HAVE_NET_DEVICE_MAX_MTU + dev->max_mtu = 0; +#endif + dev->netdev_ops = &ip6gre_tap_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); +} + +static bool ip6gre_netlink_encap_parms(struct nlattr *data[], + struct ip_tunnel_encap *ipencap) +{ + bool ret = false; + + memset(ipencap, 0, sizeof(*ipencap)); + + if (!data) + return ret; + + if (data[IFLA_GRE_ENCAP_TYPE]) { + ret = true; + ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); + } + + if (data[IFLA_GRE_ENCAP_FLAGS]) { + ret = true; + ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); + } + + if (data[IFLA_GRE_ENCAP_SPORT]) { + ret = true; + ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); + } + + if (data[IFLA_GRE_ENCAP_DPORT]) { + ret = true; + ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); + } + + return ret; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct ip6_tnl *nt; + struct net *net = dev_net(dev); + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct ip_tunnel_encap ipencap; + int err; + + nt = netdev_priv(dev); + + if (ip6gre_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(nt, &ipencap); + + if (err < 0) + return err; + } + + ip6gre_netlink_parms(data, &nt->parms); + + if (nt->parms.collect_md) { + if (rtnl_dereference(ign->collect_md_tun)) + return -EEXIST; + } else { + if (ip6gre_tunnel_find(net, &nt->parms, dev->type)) + return -EEXIST; + } + + if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) + eth_hw_addr_random(dev); + + nt->dev = dev; + nt->net = dev_net(dev); + + err = register_netdevice(dev); + if (err) + goto out; + + ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); + + if (tb[IFLA_MTU]) + ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU])); + + dev_hold(dev); + ip6gre_tunnel_link(ign, nt); + +out: + return err; +} +#define ip6gre_newlink rpl_ip6gre_newlink + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + struct ip6_tnl *t, *nt = netdev_priv(dev); + struct net *net = nt->net; + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct __ip6_tnl_parm p; + struct ip_tunnel_encap ipencap; + + if (dev == ign->fb_tunnel_dev) + return -EINVAL; + + if (ip6gre_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(nt, &ipencap); + + if (err < 0) + return err; + } + + ip6gre_netlink_parms(data, &p); + + t = ip6gre_tunnel_locate(net, &p, 0); + + if (t) { + if (t->dev != dev) + return -EEXIST; + } else { + t = nt; + } + + ip6gre_tunnel_unlink(ign, t); + ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); + ip6gre_tunnel_link(ign, t); + return 0; +} +#define ip6gre_changelink rpl_ip6gre_changelink + +static void ip6gre_dellink(struct net_device *dev, struct list_head *head) +{ + struct net *net = dev_net(dev); + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + if (dev != ign->fb_tunnel_dev) + unregister_netdevice_queue(dev, head); +} + +static size_t ip6gre_get_size(const struct net_device *dev) +{ + return + /* IFLA_GRE_LINK */ + nla_total_size(4) + + /* IFLA_GRE_IFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_OFLAGS */ + nla_total_size(2) + + /* IFLA_GRE_IKEY */ + nla_total_size(4) + + /* IFLA_GRE_OKEY */ + nla_total_size(4) + + /* IFLA_GRE_LOCAL */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_GRE_REMOTE */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_GRE_TTL */ + nla_total_size(1) + + /* IFLA_GRE_ENCAP_LIMIT */ + nla_total_size(1) + + /* IFLA_GRE_FLOWINFO */ + nla_total_size(4) + + /* IFLA_GRE_FLAGS */ + nla_total_size(4) + + /* IFLA_GRE_ENCAP_TYPE */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_FLAGS */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_SPORT */ + nla_total_size(2) + + /* IFLA_GRE_ENCAP_DPORT */ + nla_total_size(2) + + /* IFLA_GRE_COLLECT_METADATA */ + nla_total_size(0) + + /* IFLA_GRE_FWMARK */ + nla_total_size(4) + + /* IFLA_GRE_ERSPAN_INDEX */ + nla_total_size(4) + + 0; +} + +static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm *p = &t->parms; + + if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || + nla_put_be16(skb, IFLA_GRE_IFLAGS, + gre_tnl_flags_to_gre_flags(p->i_flags)) || + nla_put_be16(skb, IFLA_GRE_OFLAGS, + gre_tnl_flags_to_gre_flags(p->o_flags)) || + nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || + nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || + nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) || + nla_put_in6_addr(skb, IFLA_GRE_REMOTE, &p->raddr) || + nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) || + nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || + nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) || + nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) || + nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) || + nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) + goto nla_put_failure; + + if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, + t->encap.type) || + nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, + t->encap.sport) || + nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, + t->encap.dport) || + nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, + t->encap.flags)) + goto nla_put_failure; + + if (p->collect_md) { + if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) + goto nla_put_failure; + } + + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver)) + goto nla_put_failure; + + if (p->erspan_ver == 1) { + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index)) + goto nla_put_failure; + } else if (p->erspan_ver == 2) { + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir)) + goto nla_put_failure; + if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid)) + goto nla_put_failure; + } + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static const struct nla_policy ip6gre_policy[RPL_IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) }, + [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) }, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, + [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, + [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, +}; + +static void ip6erspan_tap_setup(struct net_device *dev) +{ + ether_setup(dev); + + dev->netdev_ops = &ip6erspan_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; +#endif + + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); +} + +static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { + .kind = "ip6gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6gre_tunnel_setup, + .validate = ip6gre_tunnel_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { + .kind = "ip6gre", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6gre_tap_setup, + .validate = ip6gre_tap_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = { + .kind = "ip6erspan", + .maxtype = RPL_IFLA_GRE_MAX, + .policy = ip6gre_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6erspan_tap_setup, + .validate = ip6erspan_tap_validate, + .newlink = ip6gre_newlink, + .changelink = ip6gre_changelink, + .get_size = ip6gre_get_size, + .fill_info = ip6gre_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +struct net_device *ip6erspan_fb_dev_create(struct net *net, const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip6_tnl *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &ip6erspan_tap_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->parms.collect_md = true; + + err = ip6gre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = ip6_tnl_change_mtu(dev, 64000); + if (err) + goto out; + + return dev; +out: + ip6gre_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_erspan6_vport_ops; + +static struct vport *erspan6_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_erspan6_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = ip6erspan_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *erspan6_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = erspan6_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +#ifndef OVS_VPORT_TYPE_IP6ERSPAN +/* Just until integration */ +#define OVS_VPORT_TYPE_IP6ERSPAN 108 +#endif +static struct vport_ops ovs_erspan6_vport_ops = { + .type = OVS_VPORT_TYPE_IP6ERSPAN, + .create = erspan6_create, + .send = __ip6erspan_tunnel_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + +struct net_device *ip6gre_fb_dev_create(struct net *net, const char *name, + u8 name_assign_type) +{ + struct nlattr *tb[IFLA_MAX + 1]; + struct net_device *dev; + LIST_HEAD(list_kill); + struct ip6_tnl *t; + int err; + + memset(&tb, 0, sizeof(tb)); + + dev = rtnl_create_link(net, (char *)name, name_assign_type, + &ip6gre_tap_ops, tb); + if (IS_ERR(dev)) + return dev; + + t = netdev_priv(dev); + t->parms.collect_md = true; + + err = ip6gre_newlink(net, dev, tb, NULL); + if (err < 0) { + free_netdev(dev); + return ERR_PTR(err); + } + + /* openvswitch users expect packet sizes to be unrestricted, + * so set the largest MTU we can. + */ + err = ip6_tnl_change_mtu(dev, 64000); + if (err) + goto out; + + return dev; +out: + ip6gre_dellink(dev, &list_kill); + unregister_netdevice_many(&list_kill); + return ERR_PTR(err); +} + +static struct vport_ops ovs_ip6gre_vport_ops; + +static struct vport *ip6gre_tnl_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct net_device *dev; + struct vport *vport; + int err; + + vport = ovs_vport_alloc(0, &ovs_ip6gre_vport_ops, parms); + if (IS_ERR(vport)) + return vport; + + rtnl_lock(); + dev = ip6gre_fb_dev_create(net, parms->name, NET_NAME_USER); + if (IS_ERR(dev)) { + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_CAST(dev); + } + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + rtnl_delete_link(dev); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); + } + + rtnl_unlock(); + return vport; +} + +static struct vport *ip6gre_create(const struct vport_parms *parms) +{ + struct vport *vport; + + vport = ip6gre_tnl_create(parms); + if (IS_ERR(vport)) + return vport; + + return ovs_netdev_link(vport, parms->name); +} + +static struct vport_ops ovs_ip6gre_vport_ops = { + .type = OVS_VPORT_TYPE_IP6GRE, + .create = ip6gre_create, + .send = __ip6gre_tunnel_xmit, +#ifndef USE_UPSTREAM_TUNNEL + .fill_metadata_dst = gre_fill_metadata_dst, +#endif + .destroy = ovs_netdev_tunnel_destroy, +}; + + +/* + * And now the modules code and kernel interface. + */ + +int rpl_ip6gre_init(void) +{ + int err; + + err = register_pernet_device(&ip6gre_net_ops); + if (err < 0) + return err; + + err = inet6_add_protocol(&ip6gre_protocol, IPPROTO_GRE); + if (err < 0) { + pr_info("%s: can't add protocol\n", __func__); + goto add_proto_failed; + } + + pr_info("GRE over IPv6 tunneling driver\n"); + ovs_vport_ops_register(&ovs_ip6gre_vport_ops); + ovs_vport_ops_register(&ovs_erspan6_vport_ops); + return 0; +out: + return err; + +add_proto_failed: + unregister_pernet_device(&ip6gre_net_ops); + goto out; +} + +void rpl_ip6gre_fini(void) +{ + ovs_vport_ops_unregister(&ovs_erspan6_vport_ops); + ovs_vport_ops_unregister(&ovs_ip6gre_vport_ops); + inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE); + unregister_pernet_device(&ip6gre_net_ops); +} +#endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/ip6_tunnel.c b/datapath/linux/compat/ip6_tunnel.c new file mode 100644 index 0000000..f9720a3 --- /dev/null +++ b/datapath/linux/compat/ip6_tunnel.c @@ -0,0 +1,2199 @@ +/* + * IPv6 tunneling device + * Linux INET6 implementation + * + * Authors: + * Ville Nuorvala + * Yasuyuki Kozakai + * + * Based on: + * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c + * + * RFC 2473 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#ifndef USE_UPSTREAM_TUNNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gso.h" +#include + +#include "vport-netdev.h" + +#define IP6_TUNNEL_HASH_SIZE_SHIFT 5 +#define IP6_TUNNEL_HASH_SIZE (1 << IP6_TUNNEL_HASH_SIZE_SHIFT) + +enum { +#ifndef HAVE_IFLA_IPTUN_ENCAP_TYPE + IFLA_IPTUN_ENCAP_TYPE = IFLA_IPTUN_6RD_RELAY_PREFIXLEN + 1, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT, +#endif +#ifndef HAVE_IFLA_IPTUN_COLLECT_METADTA + IFLA_IPTUN_COLLECT_METADATA = IFLA_IPTUN_ENCAP_DPORT + 1, + IFLA_IPTUN_FWMARK, +#endif + RPL__IFLA_IPTUN_MAX = IFLA_IPTUN_FWMARK + 1, +}; + +#define RPL_IFLA_IPTUN_MAX RPL__IFLA_IPTUN_MAX + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +/* Undef the one from ip_tunnels.h - we need a different one here */ +/* At least I think... */ +#undef iptunnel_handle_offloads +/* gre_handle_offloads() has different return type on older kernsl. */ +static void gre_nop_fix(struct sk_buff *skb) { } + +static void gre_csum_fix(struct sk_buff *skb) +{ + struct gre_base_hdr *greh; + __be32 *options; + int gre_offset = skb_transport_offset(skb); + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + options = ((__be32 *)greh + 1); + + *options = 0; + *(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset, + skb->len - gre_offset, 0)); +} + +#define iptunnel_handle_offloads rpl__iptunnel_handle_offloads +static int rpl__iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; + gso_fix_segment_t fix_segment; + + if (gre_csum) + fix_segment = gre_csum_fix; + else + fix_segment = gre_nop_fix; + + return ovs_iptunnel_handle_offloads(skb, type, fix_segment); +} + +#endif +static bool log_ecn_error = true; + +static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) +{ + u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); + + return hash_32(hash, IP6_TUNNEL_HASH_SIZE_SHIFT); +} + +static int ip6_tnl_dev_init(struct net_device *dev); +static void ip6_tnl_dev_setup(struct net_device *dev); +static struct rtnl_link_ops ip6_link_ops __read_mostly; + +static unsigned int ip6_tnl_net_id __read_mostly; +struct ip6_tnl_net { + /* the IPv6 tunnel fallback device */ + struct net_device *fb_tnl_dev; + /* lists for storing tunnels in use */ + struct ip6_tnl __rcu *tnls_r_l[IP6_TUNNEL_HASH_SIZE]; + struct ip6_tnl __rcu *tnls_wc[1]; + struct ip6_tnl __rcu **tnls[2]; + struct ip6_tnl __rcu *collect_md_tun; +}; + +static struct net_device_stats *ip6_get_stats(struct net_device *dev) +{ + struct pcpu_sw_netstats tmp, sum = { 0 }; + int i; + + for_each_possible_cpu(i) { + unsigned int start; + const struct pcpu_sw_netstats *tstats = + per_cpu_ptr(dev->tstats, i); + + do { + start = u64_stats_fetch_begin_irq(&tstats->syncp); + tmp.rx_packets = tstats->rx_packets; + tmp.rx_bytes = tstats->rx_bytes; + tmp.tx_packets = tstats->tx_packets; + tmp.tx_bytes = tstats->tx_bytes; + } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); + + sum.rx_packets += tmp.rx_packets; + sum.rx_bytes += tmp.rx_bytes; + sum.tx_packets += tmp.tx_packets; + sum.tx_bytes += tmp.tx_bytes; + } + dev->stats.rx_packets = sum.rx_packets; + dev->stats.rx_bytes = sum.rx_bytes; + dev->stats.tx_packets = sum.tx_packets; + dev->stats.tx_bytes = sum.tx_bytes; + return &dev->stats; +} + +/** + * ip6_tnl_lookup - fetch tunnel matching the end-point addresses + * @remote: the address of the tunnel exit-point + * @local: the address of the tunnel entry-point + * + * Return: + * tunnel matching given end-points if found, + * else fallback tunnel if its device is up, + * else %NULL + **/ + +#define for_each_ip6_tunnel_rcu(start) \ + for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) + +static struct ip6_tnl * +ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local) +{ + unsigned int hash = HASH(remote, local); + struct ip6_tnl *t; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct in6_addr any; + + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + memset(&any, 0, sizeof(any)); + hash = HASH(&any, local); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_any(&t->parms.raddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + hash = HASH(remote, &any); + for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) { + if (ipv6_addr_equal(remote, &t->parms.raddr) && + ipv6_addr_any(&t->parms.laddr) && + (t->dev->flags & IFF_UP)) + return t; + } + + t = rcu_dereference(ip6n->collect_md_tun); + if (t && t->dev->flags & IFF_UP) + return t; + + t = rcu_dereference(ip6n->tnls_wc[0]); + if (t && (t->dev->flags & IFF_UP)) + return t; + + return NULL; +} + +/** + * ip6_tnl_bucket - get head of list matching given tunnel parameters + * @p: parameters containing tunnel end-points + * + * Description: + * ip6_tnl_bucket() returns the head of the list matching the + * &struct in6_addr entries laddr and raddr in @p. + * + * Return: head of IPv6 tunnel list + **/ + +static struct ip6_tnl __rcu ** +ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + unsigned int h = 0; + int prio = 0; + + if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) { + prio = 1; + h = HASH(remote, local); + } + return &ip6n->tnls[prio][h]; +} + +/** + * ip6_tnl_link - add tunnel to hash table + * @t: tunnel to be added + **/ + +static void +ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); + + if (t->parms.collect_md) + rcu_assign_pointer(ip6n->collect_md_tun, t); + rcu_assign_pointer(t->next , rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); +} + +/** + * ip6_tnl_unlink - remove tunnel from hash table + * @t: tunnel to be removed + **/ + +static void +ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) +{ + struct ip6_tnl __rcu **tp; + struct ip6_tnl *iter; + + if (t->parms.collect_md) + rcu_assign_pointer(ip6n->collect_md_tun, NULL); + + for (tp = ip6_tnl_bucket(ip6n, &t->parms); + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { + rcu_assign_pointer(*tp, t->next); + break; + } + } +} + +#ifdef HAVE_NEEDS_FREE_NETDEV +static void ip6_dev_free(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + gro_cells_destroy(&t->gro_cells); + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +} + +#endif +static int ip6_tnl_create2(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + int err; + + t = netdev_priv(dev); + + dev->rtnl_link_ops = &ip6_link_ops; + err = register_netdevice(dev); + if (err < 0) + goto out; + + strcpy(t->parms.name, dev->name); + + dev_hold(dev); + ip6_tnl_link(ip6n, t); + return 0; + +out: + return err; +} + +/** + * ip6_tnl_create - create a new tunnel + * @p: tunnel parameters + * @pt: pointer to new tunnel + * + * Description: + * Create tunnel matching given parameters. + * + * Return: + * created tunnel or error pointer + **/ + +static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) +{ + struct net_device *dev; + struct ip6_tnl *t; + char name[IFNAMSIZ]; + int err = -ENOMEM; + + if (p->name[0]) + strlcpy(name, p->name, IFNAMSIZ); + else + sprintf(name, "ip6tnl%%d"); + + dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, + ip6_tnl_dev_setup); + if (!dev) + goto failed; + + dev_net_set(dev, net); + + t = netdev_priv(dev); + t->parms = *p; + t->net = dev_net(dev); + err = ip6_tnl_create2(dev); + if (err < 0) + goto failed_free; + + return t; + +failed_free: + free_netdev(dev); +failed: + return ERR_PTR(err); +} + +/** + * ip6_tnl_locate - find or create tunnel matching given parameters + * @p: tunnel parameters + * @create: != 0 if allowed to create new tunnel if no match found + * + * Description: + * ip6_tnl_locate() first tries to locate an existing tunnel + * based on @parms. If this is unsuccessful, but @create is set a new + * tunnel device is created and registered for use. + * + * Return: + * matching tunnel or error pointer + **/ + +static struct ip6_tnl *ip6_tnl_locate(struct net *net, + struct __ip6_tnl_parm *p, int create) +{ + const struct in6_addr *remote = &p->raddr; + const struct in6_addr *local = &p->laddr; + struct ip6_tnl __rcu **tp; + struct ip6_tnl *t; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + for (tp = ip6_tnl_bucket(ip6n, p); + (t = rtnl_dereference(*tp)) != NULL; + tp = &t->next) { + if (ipv6_addr_equal(local, &t->parms.laddr) && + ipv6_addr_equal(remote, &t->parms.raddr)) { + if (create) + return ERR_PTR(-EEXIST); + + return t; + } + } + if (!create) + return ERR_PTR(-ENODEV); + return ip6_tnl_create(net, p); +} + +/** + * ip6_tnl_dev_uninit - tunnel device uninitializer + * @dev: the device to be destroyed + * + * Description: + * ip6_tnl_dev_uninit() removes tunnel from its list + **/ + +static void +ip6_tnl_dev_uninit(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + if (dev == ip6n->fb_tnl_dev) + RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); + else + ip6_tnl_unlink(ip6n, t); + dst_cache_reset(&t->dst_cache); + dev_put(dev); +} + +/** + * parse_tvl_tnl_enc_lim - handle encapsulation limit option + * @skb: received socket buffer + * + * Return: + * 0 if none was found, + * else index to encapsulation limit + **/ + +__u16 rpl_ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) +{ + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; + unsigned int nhoff = raw - skb->data; + unsigned int off = nhoff + sizeof(*ipv6h); + u8 next, nexthdr = ipv6h->nexthdr; + + while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { + struct ipv6_opt_hdr *hdr; + u16 optlen; + + if (!pskb_may_pull(skb, off + sizeof(*hdr))) + break; + + hdr = (struct ipv6_opt_hdr *)(skb->data + off); + if (nexthdr == NEXTHDR_FRAGMENT) { + struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; + if (frag_hdr->frag_off) + break; + optlen = 8; + } else if (nexthdr == NEXTHDR_AUTH) { + optlen = (hdr->hdrlen + 2) << 2; + } else { + optlen = ipv6_optlen(hdr); + } + /* cache hdr->nexthdr, since pskb_may_pull() might + * invalidate hdr + */ + next = hdr->nexthdr; + if (nexthdr == NEXTHDR_DEST) { + u16 i = 2; + + /* Remember : hdr is no longer valid at this point. */ + if (!pskb_may_pull(skb, off + optlen)) + break; + + while (1) { + struct ipv6_tlv_tnl_enc_lim *tel; + + /* No more room for encapsulation limit */ + if (i + sizeof(*tel) > optlen) + break; + + tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i); + /* return index of option if found and valid */ + if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT && + tel->length == 1) + return i + off - nhoff; + /* else jump to next option */ + if (tel->type) + i += tel->length + 2; + else + i++; + } + } + nexthdr = next; + off += optlen; + } + return 0; +} + +static int +ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return PACKET_REJECT; +} + +static int +ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return PACKET_REJECT; +} + +static int ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb) +{ + __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; + + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); + + return IP6_ECN_decapsulate(ipv6h, skb); +} + +static int ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb) +{ + if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) + ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); + + return IP6_ECN_decapsulate(ipv6h, skb); +} + +__u32 rpl_ip6_tnl_get_cap(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ltype = ipv6_addr_type(laddr); + int rtype = ipv6_addr_type(raddr); + __u32 flags = 0; + + if (ltype == IPV6_ADDR_ANY || rtype == IPV6_ADDR_ANY) { + flags = IP6_TNL_F_CAP_PER_PACKET; + } else if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && + !((ltype|rtype) & IPV6_ADDR_LOOPBACK) && + (!((ltype|rtype) & IPV6_ADDR_LINKLOCAL) || p->link)) { + if (ltype&IPV6_ADDR_UNICAST) + flags |= IP6_TNL_F_CAP_XMIT; + if (rtype&IPV6_ADDR_UNICAST) + flags |= IP6_TNL_F_CAP_RCV; + } + return flags; +} + +/* called with rcu_read_lock() */ +int rpl_ip6_tnl_rcv_ctl(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ret = 0; + struct net *net = t->net; + + if ((p->flags & IP6_TNL_F_CAP_RCV) || + ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && + (rpl_ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_RCV))) { + struct net_device *ldev = NULL; + + if (p->link) + ldev = dev_get_by_index_rcu(net, p->link); + + if ((ipv6_addr_is_multicast(laddr) || + likely(ipv6_chk_addr(net, laddr, ldev, 0))) && + ((p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) || + likely(!ipv6_chk_addr(net, raddr, NULL, 0)))) + ret = 1; + } + return ret; +} + +static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb), + bool log_ecn_err) +{ + struct pcpu_sw_netstats *tstats; + + if ((!(tpi->flags & TUNNEL_CSUM) && + (tunnel->parms.i_flags & TUNNEL_CSUM)) || + ((tpi->flags & TUNNEL_CSUM) && + !(tunnel->parms.i_flags & TUNNEL_CSUM))) { + tunnel->dev->stats.rx_crc_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + + if (tunnel->parms.i_flags & TUNNEL_SEQ) { + if (!(tpi->flags & TUNNEL_SEQ) || + (tunnel->i_seqno && + (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) { + tunnel->dev->stats.rx_fifo_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + tunnel->i_seqno = ntohl(tpi->seq) + 1; + } + +#if 0 + /* Warning: All skb pointers will be invalidated! */ + if (tunnel->dev->type == ARPHRD_ETHER) { + if (!pskb_may_pull(skb, ETH_HLEN)) { + tunnel->dev->stats.rx_length_errors++; + tunnel->dev->stats.rx_errors++; + goto drop; + } + + ipv6h = ipv6_hdr(skb); + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + } else { + skb->dev = tunnel->dev; + } + + skb_reset_network_header(skb); + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + + __skb_tunnel_rx(skb, tunnel->dev, tunnel->net); + + err = dscp_ecn_decapsulate(tunnel, ipv6h, skb); + if (unlikely(err)) { + if (log_ecn_err) + net_info_ratelimited("non-ECT from %pI6 with DS=%#x\n", + &ipv6h->saddr, + ipv6_get_dsfield(ipv6h)); + if (err > 1) { + ++tunnel->dev->stats.rx_frame_errors; + ++tunnel->dev->stats.rx_errors; + goto drop; + } + } + +#endif + tstats = this_cpu_ptr(tunnel->dev->tstats); + u64_stats_update_begin(&tstats->syncp); + tstats->rx_packets++; + tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); + + skb_reset_mac_header(skb); + skb_scrub_packet(skb, false); + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + ovs_skb_dst_set(skb, (struct dst_entry *)tun_dst); + netdev_port_receive(skb, &tun_dst->u.tun_info); + return 0; + +drop: + /* In OVS case caller will free tun_dst and skb */ +#if 0 + if (tun_dst) + dst_release((struct dst_entry *)tun_dst); + kfree_skb(skb); +#endif + return 0; +} + +int rpl_ip6_tnl_rcv(struct ip6_tnl *t, struct sk_buff *skb, + const struct tnl_ptk_info *tpi, + struct metadata_dst *tun_dst, + bool log_ecn_err) +{ + return __ip6_tnl_rcv(t, skb, tpi, tun_dst, ip6ip6_dscp_ecn_decapsulate, + log_ecn_err); +} + +static const struct tnl_ptk_info tpi_v6 = { + /* no tunnel info required for ipxip6. */ + .proto = htons(ETH_P_IPV6), +}; + +static const struct tnl_ptk_info tpi_v4 = { + /* no tunnel info required for ipxip6. */ + .proto = htons(ETH_P_IP), +}; + +static int ipxip6_rcv(struct sk_buff *skb, u8 ipproto, + const struct tnl_ptk_info *tpi, + int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, + const struct ipv6hdr *ipv6h, + struct sk_buff *skb)) +{ + struct ip6_tnl *t; + const struct ipv6hdr *ipv6h = ipv6_hdr(skb); + struct metadata_dst *tun_dst = NULL; + int ret = -1; + + rcu_read_lock(); + t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, &ipv6h->daddr); + + if (t) { + u8 tproto = READ_ONCE(t->parms.proto); + + if (tproto != ipproto && tproto != 0) + goto drop; + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto drop; + if (!rpl_ip6_tnl_rcv_ctl(t, &ipv6h->daddr, &ipv6h->saddr)) + goto drop; + if (iptunnel_pull_header(skb, 0, tpi->proto, false)) + goto drop; + if (t->parms.collect_md) { + ovs_ipv6_tun_rx_dst(tun_dst, skb, 0, 0, 0); + if (!tun_dst) + goto drop; + } + ret = __ip6_tnl_rcv(t, skb, tpi, tun_dst, dscp_ecn_decapsulate, + log_ecn_error); + } + + rcu_read_unlock(); + + return ret; + +drop: + rcu_read_unlock(); + kfree_skb(skb); + return 0; +} + +static int ip4ip6_rcv(struct sk_buff *skb) +{ + return ipxip6_rcv(skb, IPPROTO_IPIP, &tpi_v4, + ip4ip6_dscp_ecn_decapsulate); +} + +static int ip6ip6_rcv(struct sk_buff *skb) +{ + return ipxip6_rcv(skb, IPPROTO_IPV6, &tpi_v6, + ip6ip6_dscp_ecn_decapsulate); +} + +struct ipv6_tel_txoption { + struct ipv6_txoptions ops; + __u8 dst_opt[8]; +}; + +static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) +{ + memset(opt, 0, sizeof(struct ipv6_tel_txoption)); + + opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT; + opt->dst_opt[3] = 1; + opt->dst_opt[4] = encap_limit; + opt->dst_opt[5] = IPV6_TLV_PADN; + opt->dst_opt[6] = 1; + + opt->ops.dst1opt = (struct ipv6_opt_hdr *) opt->dst_opt; + opt->ops.opt_nflen = 8; +} + +/** + * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own + * @t: the outgoing tunnel device + * @hdr: IPv6 header from the incoming packet + * + * Description: + * Avoid trivial tunneling loop by checking that tunnel exit-point + * doesn't match source of incoming packet. + * + * Return: + * 1 if conflict, + * 0 else + **/ + +static inline bool +ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) +{ + return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); +} + +int rpl_ip6_tnl_xmit_ctl(struct ip6_tnl *t, + const struct in6_addr *laddr, + const struct in6_addr *raddr) +{ + struct __ip6_tnl_parm *p = &t->parms; + int ret = 0; + struct net *net = t->net; + + if (t->parms.collect_md) + return 1; + + if ((p->flags & IP6_TNL_F_CAP_XMIT) || + ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && + (rpl_ip6_tnl_get_cap(t, laddr, raddr) & IP6_TNL_F_CAP_XMIT))) { + struct net_device *ldev = NULL; + + rcu_read_lock(); + if (p->link) + ldev = dev_get_by_index_rcu(net, p->link); + + if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0))) + pr_warn("%s xmit: Local address not yet configured!\n", + p->name); + else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) && + !ipv6_addr_is_multicast(raddr) && + unlikely(ipv6_chk_addr(net, raddr, NULL, 0))) + pr_warn("%s xmit: Routing loop! Remote address found on this node!\n", + p->name); + else + ret = 1; + rcu_read_unlock(); + } + return ret; +} + +static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, + u8 type, struct ipv6_opt_hdr *opt) +{ + struct ipv6_opt_hdr *h = + (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt)); + + memcpy(h, opt, ipv6_optlen(opt)); + h->nexthdr = *proto; + *proto = type; +} + +void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, + u8 *proto) +{ + if (opt->dst1opt) + ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt); +} + +/** + * ip6_tnl_xmit - encapsulate packet and send + * @skb: the outgoing socket buffer + * @dev: the outgoing tunnel device + * @dsfield: dscp code for outer header + * @fl6: flow of tunneled packet + * @encap_limit: encapsulation limit + * @pmtu: Path MTU is stored if packet is too big + * @proto: next header value + * + * Description: + * Build new header and do some sanity checks on the packet before sending + * it. + * + * Return: + * 0 on success + * -1 fail + * %-EMSGSIZE message too big. return mtu in this case. + **/ + +int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield, + struct flowi6 *fl6, int encap_limit, __u32 *pmtu, + __u8 proto) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct net_device_stats *stats = &t->dev->stats; + struct ipv6hdr *ipv6h; + struct ipv6_tel_txoption opt; + struct dst_entry *dst = NULL, *ndst = NULL; + struct net_device *tdev; + int mtu; + unsigned int eth_hlen = t->dev->type == ARPHRD_ETHER ? ETH_HLEN : 0; + unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen; + unsigned int max_headroom = psh_hlen; + bool use_cache = false; + u8 hop_limit; + int err = -1; + + if (t->parms.collect_md) { + hop_limit = skb_tunnel_info(skb)->key.ttl; + goto route_lookup; + } else { + hop_limit = t->parms.hop_limit; + } + + /* NBMA tunnel */ + if (ipv6_addr_any(&t->parms.raddr)) { + if (skb->protocol == htons(ETH_P_IPV6)) { + struct in6_addr *addr6; + struct neighbour *neigh; + int addr_type; + + if (!skb_dst(skb)) + goto tx_err_link_failure; + + neigh = dst_neigh_lookup(skb_dst(skb), + &ipv6_hdr(skb)->daddr); + if (!neigh) + goto tx_err_link_failure; + + addr6 = (struct in6_addr *)&neigh->primary_key; + addr_type = ipv6_addr_type(addr6); + + if (addr_type == IPV6_ADDR_ANY) + addr6 = &ipv6_hdr(skb)->daddr; + + memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr)); + neigh_release(neigh); + } + } else if (t->parms.proto != 0 && !(t->parms.flags & + (IP6_TNL_F_USE_ORIG_TCLASS | + IP6_TNL_F_USE_ORIG_FWMARK))) { + /* enable the cache only if neither the outer protocol nor the + * routing decision depends on the current inner header value + */ + use_cache = true; + } + + if (use_cache) + dst = dst_cache_get(&t->dst_cache); + + if (!rpl_ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) + goto tx_err_link_failure; + + if (!dst) { +route_lookup: + /* add dsfield to flowlabel for route lookup */ + fl6->flowlabel = ip6_make_flowinfo(dsfield, fl6->flowlabel); + + dst = ip6_route_output(net, NULL, fl6); + + if (dst->error) + goto tx_err_link_failure; + dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0); + if (IS_ERR(dst)) { + err = PTR_ERR(dst); + dst = NULL; + goto tx_err_link_failure; + } + if (t->parms.collect_md && + ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev, + &fl6->daddr, 0, &fl6->saddr)) + goto tx_err_link_failure; + ndst = dst; + } + + tdev = dst->dev; + + if (tdev == dev) { + stats->collisions++; + net_warn_ratelimited("%s: Local routing loop detected!\n", + t->parms.name); + goto tx_err_dst_release; + } + mtu = dst_mtu(dst) - eth_hlen - psh_hlen - t->tun_hlen; + if (encap_limit >= 0) { + max_headroom += 8; + mtu -= 8; + } + if (skb->protocol == htons(ETH_P_IPV6)) { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + } else if (mtu < 576) { + mtu = 576; + } + +// FIX ME +// skb_dst_update_pmtu(skb, mtu); + if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) { + *pmtu = mtu; + err = -EMSGSIZE; + goto tx_err_dst_release; + } + + if (t->err_count > 0) { + if (time_before(jiffies, + t->err_time + IP6TUNNEL_ERR_TIMEO)) { + t->err_count--; + + dst_link_failure(skb); + } else { + t->err_count = 0; + } + } + + skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); + + /* + * Okay, now see if we can stuff it in the buffer as-is. + */ + max_headroom += LL_RESERVED_SPACE(tdev); + + if (skb_headroom(skb) < max_headroom || skb_shared(skb) || + (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { + struct sk_buff *new_skb; + + new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) + goto tx_err_dst_release; + + if (skb->sk) + skb_set_owner_w(new_skb, skb->sk); + consume_skb(skb); + skb = new_skb; + } + + if (t->parms.collect_md) { + if (t->encap.type != TUNNEL_ENCAP_NONE) + goto tx_err_dst_release; + } else { + if (use_cache && ndst) + dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr); + } + skb_dst_set(skb, dst); + + if (encap_limit >= 0) { + init_tel_txopt(&opt, encap_limit); + ipv6_push_frag_opts(skb, &opt.ops, &proto); + } + hop_limit = hop_limit ? : ip6_dst_hoplimit(dst); + + /* Calculate max headroom for all the headers and adjust + * needed_headroom if necessary. + */ + max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr) + + dst->header_len + t->hlen; + if (max_headroom > dev->needed_headroom) + dev->needed_headroom = max_headroom; + + err = ip6_tnl_encap(skb, t, &proto, fl6); + if (err) + return err; + + skb_push(skb, sizeof(struct ipv6hdr)); + skb_reset_network_header(skb); + ipv6h = ipv6_hdr(skb); + ip6_flow_hdr(ipv6h, dsfield, + ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6)); + ipv6h->hop_limit = hop_limit; + ipv6h->nexthdr = proto; + ipv6h->saddr = fl6->saddr; + ipv6h->daddr = fl6->daddr; + ip6tunnel_xmit(NULL, skb, dev); + return 0; +tx_err_link_failure: + stats->tx_carrier_errors++; + dst_link_failure(skb); +tx_err_dst_release: + dst_release(dst); + return err; +} +EXPORT_SYMBOL(ip6_tnl_xmit); + +static inline int +ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + const struct iphdr *iph = ip_hdr(skb); + int encap_limit = -1; + struct flowi6 fl6; + __u8 dsfield; + __u32 mtu; + u8 tproto; + int err; + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + + tproto = READ_ONCE(t->parms.proto); + if (tproto != IPPROTO_IPIP && tproto != 0) + return -1; + + if (t->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -1; + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPIP; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + dsfield = key->tos; + } else { + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPIP; + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + dsfield = ipv4_get_dsfield(iph); + else + dsfield = ip6_tclass(t->parms.flowinfo); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6.flowi6_mark = skb->mark; + else + fl6.flowi6_mark = t->parms.fwmark; + } + +// FIX ME +// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + + dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph)); + + skb_set_inner_ipproto(skb, IPPROTO_IPIP); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + IPPROTO_IPIP); + if (err != 0) { + /* XXX: send ICMP error even if DF is not set. */ + if (err == -EMSGSIZE) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + return -1; + } + + return 0; +} + +static inline int +ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + int encap_limit = -1; + __u16 offset; + struct flowi6 fl6; + __u8 dsfield; + __u32 mtu; + u8 tproto; + int err; + + tproto = READ_ONCE(t->parms.proto); + if ((tproto != IPPROTO_IPV6 && tproto != 0) || + ip6_tnl_addr_conflict(t, ipv6h)) + return -1; + + if (t->parms.collect_md) { + struct ip_tunnel_info *tun_info; + const struct ip_tunnel_key *key; + + tun_info = skb_tunnel_info(skb); + if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) + return -1; + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPV6; + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + dsfield = key->tos; + } else { + offset = rpl_ip6_tnl_parse_tlv_enc_lim(skb, + skb_network_header(skb)); + /* + * ip6_tnl_parse_tlv_enc_lim() might + * have reallocated skb->head + */ + ipv6h = ipv6_hdr(skb); + if (offset > 0) { + struct ipv6_tlv_tnl_enc_lim *tel; + + tel = (void *)&skb_network_header(skb)[offset]; + if (tel->encap_limit == 0) { + icmpv6_send(skb, ICMPV6_PARAMPROB, + ICMPV6_HDR_FIELD, offset + 2); + return -1; + } + encap_limit = tel->encap_limit - 1; + } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { + encap_limit = t->parms.encap_limit; + } + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_IPV6; + + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) + dsfield = ipv6_get_dsfield(ipv6h); + else + dsfield = ip6_tclass(t->parms.flowinfo); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) + fl6.flowlabel |= ip6_flowlabel(ipv6h); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) + fl6.flowi6_mark = skb->mark; + else + fl6.flowi6_mark = t->parms.fwmark; + } + +// FIX ME +// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); + + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) + return -1; + + dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); + + skb_set_inner_ipproto(skb, IPPROTO_IPV6); + + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, + IPPROTO_IPV6); + if (err != 0) { + if (err == -EMSGSIZE) + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -1; + } + + return 0; +} + +static netdev_tx_t +ip6_tnl_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net_device_stats *stats = &t->dev->stats; + int ret; + + switch (skb->protocol) { + case htons(ETH_P_IP): + ret = ip4ip6_tnl_xmit(skb, dev); + break; + case htons(ETH_P_IPV6): + ret = ip6ip6_tnl_xmit(skb, dev); + break; + default: + goto tx_err; + } + + if (ret < 0) + goto tx_err; + + return NETDEV_TX_OK; + +tx_err: + stats->tx_errors++; + stats->tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static void ip6_tnl_link_config(struct ip6_tnl *t) +{ + struct net_device *dev = t->dev; + struct __ip6_tnl_parm *p = &t->parms; + struct flowi6 *fl6 = &t->fl.u.ip6; + int t_hlen; + + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + + /* Set up flowi template */ + fl6->saddr = p->laddr; + fl6->daddr = p->raddr; + fl6->flowi6_oif = p->link; + fl6->flowlabel = 0; + + if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) + fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; + if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) + fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; + + p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV|IP6_TNL_F_CAP_PER_PACKET); + p->flags |= rpl_ip6_tnl_get_cap(t, &p->laddr, &p->raddr); + + if (p->flags&IP6_TNL_F_CAP_XMIT && p->flags&IP6_TNL_F_CAP_RCV) + dev->flags |= IFF_POINTOPOINT; + else + dev->flags &= ~IFF_POINTOPOINT; + + t->tun_hlen = 0; + t->hlen = t->encap_hlen + t->tun_hlen; + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); + + struct rt6_info *rt = rt6_lookup(t->net, + &p->raddr, &p->laddr, + p->link, strict); + + if (!rt) + return; + + if (rt->dst.dev) { + dev->hard_header_len = rt->dst.dev->hard_header_len + + t_hlen; + + dev->mtu = rt->dst.dev->mtu - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + + if (dev->mtu < IPV6_MIN_MTU) + dev->mtu = IPV6_MIN_MTU; + } + ip6_rt_put(rt); + } +} + +/** + * ip6_tnl_change - update the tunnel parameters + * @t: tunnel to be changed + * @p: tunnel configuration parameters + * + * Description: + * ip6_tnl_change() updates the tunnel parameters + **/ + +static int +ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) +{ + t->parms.laddr = p->laddr; + t->parms.raddr = p->raddr; + t->parms.flags = p->flags; + t->parms.hop_limit = p->hop_limit; + t->parms.encap_limit = p->encap_limit; + t->parms.flowinfo = p->flowinfo; + t->parms.link = p->link; + t->parms.proto = p->proto; + t->parms.fwmark = p->fwmark; + dst_cache_reset(&t->dst_cache); + ip6_tnl_link_config(t); + return 0; +} + +static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +{ + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + int err; + + ip6_tnl_unlink(ip6n, t); + synchronize_net(); + err = ip6_tnl_change(t, p); + ip6_tnl_link(ip6n, t); + netdev_state_change(t->dev); + return err; +} + +static int ip6_tnl0_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +{ + /* for default tnl0 device allow to change only the proto */ + t->parms.proto = p->proto; + netdev_state_change(t->dev); + return 0; +} + +static void +ip6_tnl_parm_from_user(struct __ip6_tnl_parm *p, const struct ip6_tnl_parm *u) +{ + p->laddr = u->laddr; + p->raddr = u->raddr; + p->flags = u->flags; + p->hop_limit = u->hop_limit; + p->encap_limit = u->encap_limit; + p->flowinfo = u->flowinfo; + p->link = u->link; + p->proto = u->proto; + memcpy(p->name, u->name, sizeof(u->name)); +} + +static void +ip6_tnl_parm_to_user(struct ip6_tnl_parm *u, const struct __ip6_tnl_parm *p) +{ + u->laddr = p->laddr; + u->raddr = p->raddr; + u->flags = p->flags; + u->hop_limit = p->hop_limit; + u->encap_limit = p->encap_limit; + u->flowinfo = p->flowinfo; + u->link = p->link; + u->proto = p->proto; + memcpy(u->name, p->name, sizeof(u->name)); +} + +/** + * ip6_tnl_ioctl - configure ipv6 tunnels from userspace + * @dev: virtual device associated with tunnel + * @ifr: parameters passed from userspace + * @cmd: command to be performed + * + * Description: + * ip6_tnl_ioctl() is used for managing IPv6 tunnels + * from userspace. + * + * The possible commands are the following: + * %SIOCGETTUNNEL: get tunnel parameters for device + * %SIOCADDTUNNEL: add tunnel matching given tunnel parameters + * %SIOCCHGTUNNEL: change tunnel parameters to those given + * %SIOCDELTUNNEL: delete tunnel + * + * The fallback device "ip6tnl0", created during module + * initialization, can be used for creating other tunnel devices. + * + * Return: + * 0 on success, + * %-EFAULT if unable to copy data to or from userspace, + * %-EPERM if current process hasn't %CAP_NET_ADMIN set + * %-EINVAL if passed tunnel parameters are invalid, + * %-EEXIST if changing a tunnel's parameters would cause a conflict + * %-ENODEV if attempting to change or delete a nonexisting device + **/ + +static int +ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + int err = 0; + struct ip6_tnl_parm p; + struct __ip6_tnl_parm p1; + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + memset(&p1, 0, sizeof(p1)); + + switch (cmd) { + case SIOCGETTUNNEL: + if (dev == ip6n->fb_tnl_dev) { + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { + err = -EFAULT; + break; + } + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, 0); + if (IS_ERR(t)) + t = netdev_priv(dev); + } else { + memset(&p, 0, sizeof(p)); + } + ip6_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) { + err = -EFAULT; + } + break; + case SIOCADDTUNNEL: + case SIOCCHGTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + break; + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + break; + err = -EINVAL; + if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && + p.proto != 0) + break; + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, cmd == SIOCADDTUNNEL); + if (cmd == SIOCCHGTUNNEL) { + if (!IS_ERR(t)) { + if (t->dev != dev) { + err = -EEXIST; + break; + } + } else + t = netdev_priv(dev); + if (dev == ip6n->fb_tnl_dev) + err = ip6_tnl0_update(t, &p1); + else + err = ip6_tnl_update(t, &p1); + } + if (!IS_ERR(t)) { + err = 0; + ip6_tnl_parm_to_user(&p, &t->parms); + if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) + err = -EFAULT; + + } else { + err = PTR_ERR(t); + } + break; + case SIOCDELTUNNEL: + err = -EPERM; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + break; + + if (dev == ip6n->fb_tnl_dev) { + err = -EFAULT; + if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) + break; + err = -ENOENT; + ip6_tnl_parm_from_user(&p1, &p); + t = ip6_tnl_locate(net, &p1, 0); + if (IS_ERR(t)) + break; + err = -EPERM; + if (t->dev == ip6n->fb_tnl_dev) + break; + dev = t->dev; + } + err = 0; + unregister_netdevice(dev); + break; + default: + err = -EINVAL; + } + return err; +} + +/** + * ip6_tnl_change_mtu - change mtu manually for tunnel device + * @dev: virtual device associated with tunnel + * @new_mtu: the new mtu + * + * Return: + * 0 on success, + * %-EINVAL if mtu too small + **/ + +int rpl_ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) +{ + struct ip6_tnl *tnl = netdev_priv(dev); + + if (tnl->parms.proto == IPPROTO_IPV6) { + if (new_mtu < IPV6_MIN_MTU) + return -EINVAL; + } else { + if (new_mtu < ETH_MIN_MTU) + return -EINVAL; + } + if (new_mtu > 0xFFF8 - dev->hard_header_len) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +#ifdef HAVE_NDO_GET_IFLINK +int rpl_ip6_tnl_get_iflink(const struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + + return t->parms.link; +} + +#endif +const struct ip6_tnl_encap_ops __rcu * + rpl_ip6tun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly; + +int rpl_ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num) +{ + if (num >= MAX_IPTUN_ENCAP_OPS) + return -ERANGE; + + return !cmpxchg((const struct ip6_tnl_encap_ops **) + &rpl_ip6tun_encaps[num], + NULL, ops) ? 0 : -1; +} + +int rpl_ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops, + unsigned int num) +{ + int ret; + + if (num >= MAX_IPTUN_ENCAP_OPS) + return -ERANGE; + + ret = (cmpxchg((const struct ip6_tnl_encap_ops **) + &rpl_ip6tun_encaps[num], + ops, NULL) == ops) ? 0 : -1; + + synchronize_net(); + + return ret; +} + +int rpl_ip6_tnl_encap_setup(struct ip6_tnl *t, + struct ip_tunnel_encap *ipencap) +{ + int hlen; + + memset(&t->encap, 0, sizeof(t->encap)); + + hlen = ip6_encap_hlen(ipencap); + if (hlen < 0) + return hlen; + + t->encap.type = ipencap->type; + t->encap.sport = ipencap->sport; + t->encap.dport = ipencap->dport; + t->encap.flags = ipencap->flags; + + t->encap_hlen = hlen; + t->hlen = t->encap_hlen + t->tun_hlen; + + return 0; +} + +static const struct net_device_ops ip6_tnl_netdev_ops = { + .ndo_init = ip6_tnl_dev_init, + .ndo_uninit = ip6_tnl_dev_uninit, + .ndo_start_xmit = ip6_tnl_start_xmit, + .ndo_do_ioctl = ip6_tnl_ioctl, + .ndo_change_mtu = ip6_tnl_change_mtu, + .ndo_get_stats = ip6_get_stats, +#ifdef HAVE_NDO_GET_IFLINK + .ndo_get_iflink = ip6_tnl_get_iflink, +#endif +}; + +#define IPXIPX_FEATURES (NETIF_F_SG | \ + NETIF_F_FRAGLIST | \ + NETIF_F_HIGHDMA | \ + NETIF_F_GSO_SOFTWARE | \ + NETIF_F_HW_CSUM) + +/** + * ip6_tnl_dev_setup - setup virtual tunnel device + * @dev: virtual device associated with tunnel + * + * Description: + * Initialize function pointers and device parameters + **/ + +static void ip6_tnl_dev_setup(struct net_device *dev) +{ + dev->netdev_ops = &ip6_tnl_netdev_ops; +#ifndef HAVE_NEEDS_FREE_NETDEV + dev->destructor = free_netdev; +#else + dev->needs_free_netdev = true; + dev->priv_destructor = ip6_dev_free; +#endif + + dev->type = ARPHRD_TUNNEL6; + dev->flags |= IFF_NOARP; + dev->addr_len = sizeof(struct in6_addr); + dev->features |= NETIF_F_LLTX; + netif_keep_dst(dev); + + dev->features |= IPXIPX_FEATURES; + dev->hw_features |= IPXIPX_FEATURES; + + /* This perm addr will be used as interface identifier by IPv6 */ + dev->addr_assign_type = NET_ADDR_RANDOM; + eth_random_addr(dev->perm_addr); +} + + +/** + * ip6_tnl_dev_init_gen - general initializer for all tunnel devices + * @dev: virtual device associated with tunnel + **/ + +static inline int +ip6_tnl_dev_init_gen(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int ret; + int t_hlen; + + t->dev = dev; + t->net = dev_net(dev); + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; + + ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); + if (ret) + goto free_stats; + + ret = gro_cells_init(&t->gro_cells, dev); + if (ret) + goto destroy_dst; + + t->tun_hlen = 0; + t->hlen = t->encap_hlen + t->tun_hlen; + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + dev->type = ARPHRD_TUNNEL6; + dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; +#ifdef HAVE_NET_DEVICE_MAX_MTU + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = 0xFFF8 - dev->hard_header_len; +#endif + + return 0; + +destroy_dst: + dst_cache_destroy(&t->dst_cache); +free_stats: + free_percpu(dev->tstats); + dev->tstats = NULL; + + return ret; +} + +/** + * ip6_tnl_dev_init - initializer for all non fallback tunnel devices + * @dev: virtual device associated with tunnel + **/ + +static int ip6_tnl_dev_init(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + int err = ip6_tnl_dev_init_gen(dev); + + if (err) + return err; + ip6_tnl_link_config(t); + if (t->parms.collect_md) { + dev->features |= NETIF_F_NETNS_LOCAL; + netif_keep_dst(dev); + } + return 0; +} + +/** + * ip6_fb_tnl_dev_init - initializer for fallback tunnel device + * @dev: fallback device + * + * Return: 0 + **/ + +static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + u8 proto; + + if (!data || !data[IFLA_IPTUN_PROTO]) + return 0; + + proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); + if (proto != IPPROTO_IPV6 && + proto != IPPROTO_IPIP && + proto != 0) + return -EINVAL; + + return 0; +} +#define ip6_tnl_validate rpl_ip6_tnl_validate + +static void ip6_tnl_netlink_parms(struct nlattr *data[], + struct __ip6_tnl_parm *parms) +{ + memset(parms, 0, sizeof(*parms)); + + if (!data) + return; + + if (data[IFLA_IPTUN_LINK]) + parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]); + + if (data[IFLA_IPTUN_LOCAL]) + parms->laddr = nla_get_in6_addr(data[IFLA_IPTUN_LOCAL]); + + if (data[IFLA_IPTUN_REMOTE]) + parms->raddr = nla_get_in6_addr(data[IFLA_IPTUN_REMOTE]); + + if (data[IFLA_IPTUN_TTL]) + parms->hop_limit = nla_get_u8(data[IFLA_IPTUN_TTL]); + + if (data[IFLA_IPTUN_ENCAP_LIMIT]) + parms->encap_limit = nla_get_u8(data[IFLA_IPTUN_ENCAP_LIMIT]); + + if (data[IFLA_IPTUN_FLOWINFO]) + parms->flowinfo = nla_get_be32(data[IFLA_IPTUN_FLOWINFO]); + + if (data[IFLA_IPTUN_FLAGS]) + parms->flags = nla_get_u32(data[IFLA_IPTUN_FLAGS]); + + if (data[IFLA_IPTUN_PROTO]) + parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); + + if (data[IFLA_IPTUN_COLLECT_METADATA]) + parms->collect_md = true; + + if (data[IFLA_IPTUN_FWMARK]) + parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); +} + +static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], + struct ip_tunnel_encap *ipencap) +{ + bool ret = false; + + memset(ipencap, 0, sizeof(*ipencap)); + + if (!data) + return ret; + + if (data[IFLA_IPTUN_ENCAP_TYPE]) { + ret = true; + ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]); + } + + if (data[IFLA_IPTUN_ENCAP_FLAGS]) { + ret = true; + ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]); + } + + if (data[IFLA_IPTUN_ENCAP_SPORT]) { + ret = true; + ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]); + } + + if (data[IFLA_IPTUN_ENCAP_DPORT]) { + ret = true; + ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]); + } + + return ret; +} + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +#endif +{ + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip_tunnel_encap ipencap; + struct ip6_tnl *nt, *t; + int err; + + nt = netdev_priv(dev); + + if (ip6_tnl_netlink_encap_parms(data, &ipencap)) { + err = ip6_tnl_encap_setup(nt, &ipencap); + if (err < 0) + return err; + } + + ip6_tnl_netlink_parms(data, &nt->parms); + + if (nt->parms.collect_md) { + if (rtnl_dereference(ip6n->collect_md_tun)) + return -EEXIST; + } else { + t = ip6_tnl_locate(net, &nt->parms, 0); + if (!IS_ERR(t)) + return -EEXIST; + } + + err = ip6_tnl_create2(dev); + if (!err && tb[IFLA_MTU]) + ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU])); + + return err; +} +#define ip6_tnl_newlink rpl_ip6_tnl_newlink + +#ifdef HAVE_IP6GRE_EXTACK +static int rpl_ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +#else +static int rpl_ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) +#endif +{ + struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm p; + struct net *net = t->net; + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip_tunnel_encap ipencap; + + if (dev == ip6n->fb_tnl_dev) + return -EINVAL; + + if (ip6_tnl_netlink_encap_parms(data, &ipencap)) { + int err = ip6_tnl_encap_setup(t, &ipencap); + + if (err < 0) + return err; + } + ip6_tnl_netlink_parms(data, &p); + if (p.collect_md) + return -EINVAL; + + t = ip6_tnl_locate(net, &p, 0); + if (!IS_ERR(t)) { + if (t->dev != dev) + return -EEXIST; + } else + t = netdev_priv(dev); + + return ip6_tnl_update(t, &p); +} +#define ip6_tnl_changelink rpl_ip6_tnl_changelink + +static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head) +{ + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + + if (dev != ip6n->fb_tnl_dev) + unregister_netdevice_queue(dev, head); +} + +static size_t ip6_tnl_get_size(const struct net_device *dev) +{ + return + /* IFLA_IPTUN_LINK */ + nla_total_size(4) + + /* IFLA_IPTUN_LOCAL */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_IPTUN_REMOTE */ + nla_total_size(sizeof(struct in6_addr)) + + /* IFLA_IPTUN_TTL */ + nla_total_size(1) + + /* IFLA_IPTUN_ENCAP_LIMIT */ + nla_total_size(1) + + /* IFLA_IPTUN_FLOWINFO */ + nla_total_size(4) + + /* IFLA_IPTUN_FLAGS */ + nla_total_size(4) + + /* IFLA_IPTUN_PROTO */ + nla_total_size(1) + + /* IFLA_IPTUN_ENCAP_TYPE */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_FLAGS */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_SPORT */ + nla_total_size(2) + + /* IFLA_IPTUN_ENCAP_DPORT */ + nla_total_size(2) + + /* IFLA_IPTUN_COLLECT_METADATA */ + nla_total_size(0) + + /* IFLA_IPTUN_FWMARK */ + nla_total_size(4) + + 0; +} + +static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + struct __ip6_tnl_parm *parm = &tunnel->parms; + + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || + nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || + nla_put_in6_addr(skb, IFLA_IPTUN_REMOTE, &parm->raddr) || + nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) || + nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || + nla_put_u32(skb, IFLA_IPTUN_FWMARK, parm->fwmark)) + goto nla_put_failure; + + if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || + nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || + nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS, tunnel->encap.flags)) + goto nla_put_failure; + + if (parm->collect_md) + if (nla_put_flag(skb, IFLA_IPTUN_COLLECT_METADATA)) + goto nla_put_failure; + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +#ifdef HAVE_GET_LINK_NET +struct net *rpl_ip6_tnl_get_link_net(const struct net_device *dev) +{ + struct ip6_tnl *tunnel = netdev_priv(dev); + + return tunnel->net; +} + +#endif +static const struct nla_policy ip6_tnl_policy[RPL_IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .len = sizeof(struct in6_addr) }, + [IFLA_IPTUN_REMOTE] = { .len = sizeof(struct in6_addr) }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, + [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, + [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, +}; + +static struct rtnl_link_ops ip6_link_ops __read_mostly = { + .kind = "ip6tnl", + .maxtype = RPL_IFLA_IPTUN_MAX, + .policy = ip6_tnl_policy, + .priv_size = sizeof(struct ip6_tnl), + .setup = ip6_tnl_dev_setup, + .validate = ip6_tnl_validate, + .newlink = ip6_tnl_newlink, + .changelink = ip6_tnl_changelink, + .dellink = ip6_tnl_dellink, + .get_size = ip6_tnl_get_size, + .fill_info = ip6_tnl_fill_info, +#ifdef HAVE_GET_LINK_NET + .get_link_net = ip6_tnl_get_link_net, +#endif +}; + +static struct xfrm6_tunnel ip4ip6_handler __read_mostly = { + .handler = ip4ip6_rcv, + .err_handler = ip4ip6_err, + .priority = 1, +}; + +static struct xfrm6_tunnel ip6ip6_handler __read_mostly = { + .handler = ip6ip6_rcv, + .err_handler = ip6ip6_err, + .priority = 1, +}; + +static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head *list) +{ + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct net_device *dev, *aux; + int h; + struct ip6_tnl *t; + + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == &ip6_link_ops) + unregister_netdevice_queue(dev, list); + + for (h = 0; h < IP6_TUNNEL_HASH_SIZE; h++) { + t = rtnl_dereference(ip6n->tnls_r_l[h]); + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, list); + t = rtnl_dereference(t->next); + } + } +} + +static int __net_init ip6_tnl_init_net(struct net *net) +{ + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip6_tnl *t = NULL; + int err; + + ip6n->tnls[0] = ip6n->tnls_wc; + ip6n->tnls[1] = ip6n->tnls_r_l; + + err = -ENOMEM; + ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", + NET_NAME_UNKNOWN, ip6_tnl_dev_setup); + + if (!ip6n->fb_tnl_dev) + goto err_alloc_dev; + dev_net_set(ip6n->fb_tnl_dev, net); + ip6n->fb_tnl_dev->rtnl_link_ops = &ip6_link_ops; + /* FB netdevice is special: we have one, and only one per netns. + * Allowing to move it to another netns is clearly unsafe. + */ + ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL; + + err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; + + err = register_netdev(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; + + t = netdev_priv(ip6n->fb_tnl_dev); + + strcpy(t->parms.name, ip6n->fb_tnl_dev->name); + return 0; + +err_register: + free_netdev(ip6n->fb_tnl_dev); +err_alloc_dev: + return err; +} + +static void __net_exit ip6_tnl_exit_batch_net(struct list_head *net_list) +{ + struct net *net; + LIST_HEAD(list); + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) + ip6_tnl_destroy_tunnels(net, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); +} + +static struct pernet_operations ip6_tnl_net_ops = { + .init = ip6_tnl_init_net, + .exit_batch = ip6_tnl_exit_batch_net, + .id = &ip6_tnl_net_id, + .size = sizeof(struct ip6_tnl_net), +}; + +/** + * ip6_tunnel_init - register protocol and reserve needed resources + * + * Return: 0 on success + **/ + +int rpl_ip6_tunnel_init(void) +{ + int err; + +#if 0 + if (!ipv6_mod_enabled()) + return -EOPNOTSUPP; +#endif + err = register_pernet_device(&ip6_tnl_net_ops); + if (err < 0) + goto out_pernet; + + err = xfrm6_tunnel_register(&ip4ip6_handler, AF_INET); + if (err < 0) { + pr_err("%s: can't register ip4ip6\n", __func__); + goto out_ip4ip6; + } + + err = xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6); + if (err < 0) { + pr_err("%s: can't register ip6ip6\n", __func__); + goto out_ip6ip6; + } + err = rtnl_link_register(&ip6_link_ops); + if (err < 0) + goto rtnl_link_failed; + + return 0; + +rtnl_link_failed: + xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); +out_ip6ip6: + xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); +out_ip4ip6: + unregister_pernet_device(&ip6_tnl_net_ops); +out_pernet: + return err; +} + +/** + * ip6_tunnel_cleanup - free resources and unregister protocol + **/ + +void rpl_ip6_tunnel_cleanup(void) +{ + rtnl_link_unregister(&ip6_link_ops); + if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET)) + pr_info("%s: can't deregister ip4ip6\n", __func__); + + if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) + pr_info("%s: can't deregister ip6ip6\n", __func__); + + unregister_pernet_device(&ip6_tnl_net_ops); +} + +#endif /* USE_UPSTREAM_TUNNEL */ diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 8060097..0b0a17f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -196,6 +196,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; const struct iphdr *iph; + struct erspan_md2 *md2; int ver; int len; diff --git a/datapath/vport.c b/datapath/vport.c index 711c29f..f4131be 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -67,6 +67,12 @@ int ovs_vport_init(void) err = ipgre_init(); if (err) goto err_gre; + err = ip6gre_init(); + if (err) + goto err_ip6gre; + err = ip6_tunnel_init(); + if (err) + goto err_ip6_tunnel; err = geneve_init_module(); if (err) goto err_geneve; @@ -84,6 +90,10 @@ err_stt: err_vxlan: geneve_cleanup_module(); err_geneve: + ip6_tunnel_cleanup(); +err_ip6_tunnel: + ip6gre_fini(); +err_ip6gre: ipgre_fini(); err_gre: lisp_cleanup_module(); @@ -102,6 +112,8 @@ void ovs_vport_exit(void) ovs_stt_cleanup_module(); vxlan_cleanup_module(); geneve_cleanup_module(); + ip6_tunnel_cleanup(); + ip6gre_fini(); ipgre_fini(); lisp_cleanup_module(); kfree(dev_table); diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 40c4569..63d3454 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -90,6 +90,9 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_VXLAN: return "vxlan"; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L3) { return "gre"; } else if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L2) { @@ -262,6 +265,9 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -316,6 +322,9 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, nl_msg_put_be16(&request, IFLA_VXLAN_PORT, tnl_cfg->dst_port); break; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: nl_msg_put_flag(&request, IFLA_GRE_COLLECT_METADATA); break; case OVS_VPORT_TYPE_GENEVE: @@ -438,6 +447,9 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index bb9e95d..e8ffd6f 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -787,6 +787,11 @@ get_vport_type(const struct dpif_netlink_vport *vport) case OVS_VPORT_TYPE_STT: return "stt"; + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: + return ""; + case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: break; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 3cb7b5e..a3635e7 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3348,6 +3348,9 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac, switch (tnl_type) { case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: nw_proto = IPPROTO_GRE; break; case OVS_VPORT_TYPE_VXLAN: From patchwork Fri May 18 01:57:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915955 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="DhcAljdB"; 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 40nBQr2Ktvz9s19 for ; Fri, 18 May 2018 12:08:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4B27A10F3; Fri, 18 May 2018 01:58:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 566B31086 for ; Fri, 18 May 2018 01:58:44 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f66.google.com (mail-pl0-f66.google.com [209.85.160.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 1A3CE6F3 for ; Fri, 18 May 2018 01:58:44 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id az12-v6so3624922plb.8 for ; Thu, 17 May 2018 18:58:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vF+h5j49m4OeaAysg9XaOt8MSByqeN2+208QyR24qw8=; b=DhcAljdBQfDNkJpasMq7PJA3ffatYUyyOiC2AISDKJxOqyCFO0HFs00YUn2OnWGiRD E+K1JKPQPHG+J8bLXF+msS6xSR5K+iWqt8g0G2V53mQeNlYXJ/D639eQKPsH6I1peA4e ey98pUrNxx6xE6R8S3ppswDs6viPTIBTcEi1q5peQ0n1SNDpmuSmP+zrPYLaIB7WyhVg 5I0KO2KXp/A8ZgqGhuDx0Z6WDFoyg8InFrjyRwMA6K/ZUyiONjw/4u8J8q3yrkiCGPIv OVeZ2DSr1WIl7PEnmi6uB5oHzDLX9igo0/vlH1a6GuGfLPCrRjRNFxH3f2W95pkVtwq1 PtMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vF+h5j49m4OeaAysg9XaOt8MSByqeN2+208QyR24qw8=; b=BFoHSpznz4t9u5HSsq3BVbKlpDLeln9dK6jt5GxqwGD5c7DrbkLJ6cly8jv3jT48Gd f+Pb+fv2Xk2IHv8nlM267A5nQYI5H0erVp9uv5CaZBLEEI5ohUHe0XRKllfqXa2/r4GW 5Vptgcua1Fr5i9T2T3119THsuKBriLW9XmmptHVk6WOSMWUzaqz3y0NJ2lCKNAG1GRVu moY6nUwuoHOE1TGH5dRPJ+7jLvh3DwvlIg5WCO/65LwvWpiKdhN0CO1/xoPA/rIUERNt hxQMPoaCBLmtl/5YnQUc5PfVFVLCIoR+AHZwkYNBaezzaVn0WxPco5dss0fT98Lt8VIh St8A== X-Gm-Message-State: ALKqPwdX3RaT9A+te6CVQCYLt3t2yZ8XUy9J0DluneV0WGZNMajJi/Fr JIjNVl2DZPCsy7lsONTMty+G3g== X-Google-Smtp-Source: AB8JxZpNFck7aPH+WmJEsYDei2/yt7HJdRpQSQGUyhpNq5eOiIUYWPBFtHvQUjISuOdWJx99DiyoVQ== X-Received: by 2002:a17:902:848b:: with SMTP id c11-v6mr7529253plo.132.1526608723460; Thu, 17 May 2018 18:58:43 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:43 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:32 -0700 Message-Id: <1526608674-12702-20-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 19/41] datapath: Add dellink op to ip6gre and ip6erspan tap ops X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Fix an oversight in the ip6gre_tap_ops and ip6erspan_tap_ops in which the .dellink field was not initialized leading to bugs when trying to remove and re-add those type of ports. Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 23b1c83..1e2f46a 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -2324,6 +2324,7 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { .validate = ip6gre_tap_validate, .newlink = ip6gre_newlink, .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, #ifdef HAVE_GET_LINK_NET @@ -2340,6 +2341,7 @@ static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = { .validate = ip6erspan_tap_validate, .newlink = ip6gre_newlink, .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, #ifdef HAVE_GET_LINK_NET From patchwork Fri May 18 01:57:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915956 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="QNsVmd5h"; 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 40nBRP0Gllz9s19 for ; Fri, 18 May 2018 12:08:32 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 2E6091102; Fri, 18 May 2018 01:58:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 34A58F14 for ; Fri, 18 May 2018 01:58:45 +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 F08B56DB for ; Fri, 18 May 2018 01:58:44 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id w4-v6so2605421pgq.8 for ; Thu, 17 May 2018 18:58:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+K8Uz9GTAqOj4X8qwVF/G8F4McIsqoE82ebcV+AyN0E=; b=QNsVmd5htdlHcRUSNo63M6zxaruvNkoBIPjqOQ382lAkKbZM+IfVd4jB5Pi1lGNQdA 53fOnfPhw5L9Q6EtD1Pim5+S4mrSrX4j+HWuyRpUj8D4UZf1SvMkgaFT0/DjMPRkqlk+ 8XIdN9FNKUsLuwDMIpeD8N5wUI+XaUgDYCqiwkRlKmA6miyyHqO4GmUhiZK8HgoP1rsC btdag5mlPPSelTuntTkr3LOXJnsjzFS5jFbhw4Ui6yC9aRy6Hx5zC/WgTchK0/OSNLw5 XQEQ71ucYAo2UJIf0KA7AoMoaJyMMQct9ySUoMXRrDtBol91j+P5wxV8j+K7SKnoYgZQ QWvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+K8Uz9GTAqOj4X8qwVF/G8F4McIsqoE82ebcV+AyN0E=; b=dSh0b9KQENVje+qCWtUtjLv3APlipct5wkskuSZ7P1SFdSyXBosScbU57xi8cJ/cNh 0ZLadYPsElFIYcuCaBJu6lRjha+rpYXKrszDckymE9vfgaf7wJ2Q5mi/K3i2HLa2pQMm 57EbUhj7tMGRiDjFtIdxhBtITWLgK2oKv0omH58mA6j18sYLAHqGQ8mWScKKbCZ/W6Eh g26R9KLL7lVlGw444jwbzKflI3/dZjXwB7aJ3l2Jrq9dSEo8wbeAD4ViUHxTcNcvejaw wZFNCyqblTT1EQBRUbw+laFgwre6hXDuJnSfad77spzl2ggeJqPguwcaALtpQVV7qvhS PpGQ== X-Gm-Message-State: ALKqPwcOTmMyKQf2oKQErQxRNk71I/PojMIXPyxb06daBvsaClYI/h2+ uCsug+SZ4U58mvKZTStAmuAwAQ== X-Google-Smtp-Source: AB8JxZp7UCjsnyI1mx6R2TztrbBmyY3Dn8Ft5ZgdewEyqZPqtOr2rAJN8glXDf6AitrwFffnuU3KhA== X-Received: by 2002:a62:3f4e:: with SMTP id m75-v6mr7298560pfa.176.1526608724289; Thu, 17 May 2018 18:58:44 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:43 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:33 -0700 Message-Id: <1526608674-12702-21-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 20/41] datapath: Use correct tunnel receive for ip6gre X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org During backports of ip6 gre I used ovs_ip_tunnel_rcv() for the ip6gre_rcv() function but that is wrong because it processes ipv4 tunnels. Use the correct backported ip6 tunnel receive in ip6 tunnel.c ip6_tnl_rcv(). Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 1e2f46a..085d04f 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -603,8 +603,7 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) } - skb_reset_mac_header(skb); - ovs_ip_tunnel_rcv(tunnel->dev, skb, tun_dst); + ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, false); kfree(tun_dst); return PACKET_RCVD; } From patchwork Fri May 18 01:57:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915957 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="hLg/fCAk"; 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 40nBS16Q6dz9s19 for ; Fri, 18 May 2018 12:09:05 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8385A1113; Fri, 18 May 2018 01:58:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id F2ACB10CC for ; Fri, 18 May 2018 01:58:46 +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 DFFD36F9 for ; Fri, 18 May 2018 01:58:45 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id l2-v6so2604081pgc.7 for ; Thu, 17 May 2018 18:58:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QONi4bMB9a+QOmH5das6ahnsp7WJmQxwZ/R4O8w54oY=; b=hLg/fCAklm1wqLPXvktuTctcltyvUZEVRJ6pKiWrhYHsd1tbms/hJ68TUFW7DfJWub c8WBboT/W/e9RZqMkrxZrO9ZuMdTigVVXoBbLNyQu7zkBTszdpkkp2+3YWYLH9gIO9Nn arjDjgXt4wS40YvjnHkskVrc7qVrhqza/yLZQx8Pc8MObko8Y+3mVipxwncLSCw4Rz5Z 156iH//DZSKHgMZy5W/NNbGXDIYJBVRG+G8lhSM3mA4Mjs3TYz7ogHS1k7DavWxbfauD X/dLhCc+dxj+Qhn6VCXTk+dC7QKwaaeLAsQlyE1t03cPr19mxCRZrXU1vxX7HhgsX2sf ivAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QONi4bMB9a+QOmH5das6ahnsp7WJmQxwZ/R4O8w54oY=; b=rwryUQjKMP+C9s/o5qTevQfmy7eV5nJlrTrY1jWoEGWJ+2F5Ci2byYcoxf7qmuL9xq NmDPvTtSrLr59gix9BCdhRnDdMj6b3toHcaqSJLLdgH4g6WpF/ssRzbJdhlGPo/rMV2X O50i2JFwf71PiHDMz/ftyIxsmqdaYKdea2FmUbnM2gmxaWOJS9nSIFLTjUQzRNXyEdoS qzpb82cPPD9ox2KJq9AAZ008vr64RCnfRsuPDHn59WVlAFDT8u0M0mSlJY6zPtd0+skO dnecpGmrnXMuAgvw8JjizOWzTZv1QJFSeZT+0Cu05b9iMeBakFIjScRJ7O5jki1wyWGc Ujrw== X-Gm-Message-State: ALKqPwcRIc9vX/rdcB73KymRPUtKA59msC7nBgv/UYLE1OcjwnfBUy4v 1tToO9Tc/d98mw1ELDBd8hO3LQ== X-Google-Smtp-Source: AB8JxZqH+ziKMGXpoh+RvafkD7RxRq4AXVQlg/8BKrPdz1ToFYY+JkJUqccov5uBdStlKFdUOlOiGg== X-Received: by 2002:a62:fe0e:: with SMTP id z14-v6mr7446523pfh.73.1526608725168; Thu, 17 May 2018 18:58:45 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:44 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:34 -0700 Message-Id: <1526608674-12702-22-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 21/41] datapath: erspan: introduce erspan v2 for ip_gre X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit f551c91de262ba36b20c3ac19538afb4f4507441 Author: William Tu Date: Wed Dec 13 16:38:56 2017 -0800 net: erspan: introduce erspan v2 for ip_gre The patch adds support for erspan version 2. Not all features are supported in this patch. The SGT (security group tag), GRA (timestamp granularity), FT (frame type) are set to fixed value. Only hardware ID and direction are configurable. Optional subheader is also not supported. Signed-off-by: William Tu Signed-off-by: David S. Miller Includes some compatability layer adjustments and portions of this commit were introduced earlier while pulling in ipv6 erspan. Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/include/net/ip_tunnels.h | 10 +++--- datapath/linux/compat/ip_gre.c | 44 ++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index ea3fb8d..9b2621e 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -257,7 +257,7 @@ struct rpl_ip_tunnel_dst { }; #define ip_tunnel rpl_ip_tunnel -struct ip_tunnel { +struct rpl_ip_tunnel { struct ip_tunnel __rcu *next; struct hlist_node hash_node; struct net_device *dev; @@ -301,7 +301,7 @@ struct ip_tunnel { }; #define ip_tunnel_net rpl_ip_tunnel_net -struct ip_tunnel_net { +struct rpl_ip_tunnel_net { struct net_device *fb_tunnel_dev; struct hlist_head tunnels[IP_TNL_HASH_SIZE]; struct ip_tunnel __rcu *collect_md_tun; @@ -368,8 +368,8 @@ struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *tot); #define ip_tunnel_get_dsfield rpl_ip_tunnel_get_dsfield -static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, - const struct sk_buff *skb) +static inline u8 rpl_ip_tunnel_get_dsfield(const struct iphdr *iph, + const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) return iph->tos; @@ -380,7 +380,7 @@ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, } #define ip_tunnel_ecn_encap rpl_ip_tunnel_ecn_encap -static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, +static inline u8 rpl_ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, const struct sk_buff *skb) { u8 inner = ip_tunnel_get_dsfield(iph, skb); diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 0b0a17f..9bc3277 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -364,7 +364,8 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi) if (hdr_len < 0) goto drop; - if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { + if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || + tpi.proto == htons(ETH_P_ERSPAN2))) { if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) return 0; goto drop; @@ -819,9 +820,14 @@ enum { #if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) + IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, +#endif }; -#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_INDEX + 1) +#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) static int erspan_validate(struct nlattr *tb[], struct nlattr *data[]) { @@ -966,8 +972,14 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, } /* Push ERSPAN header */ - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, - truncate, true); + if (tunnel->erspan_ver == 1) + erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + truncate, true); + else + erspan_build_header_v2(skb, tunnel->parms.o_key, + tunnel->dir, tunnel->hwid, + truncate, true); + tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); return NETDEV_TX_OK; @@ -1011,7 +1023,7 @@ static int erspan_tunnel_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->parms.iph.protocol = IPPROTO_GRE; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + - sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; + erspan_hdr_len(tunnel->erspan_ver); t_hlen = tunnel->hlen + sizeof(struct iphdr); dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; @@ -1248,6 +1260,12 @@ static size_t ipgre_get_size(const struct net_device *dev) nla_total_size(0) + /* IFLA_GRE_ERSPAN_INDEX */ nla_total_size(4) + + /* IFLA_GRE_ERSPAN_VER */ + nla_total_size(1) + + /* IFLA_GRE_ERSPAN_DIR */ + nla_total_size(1) + + /* IFLA_GRE_ERSPAN_HWID */ + nla_total_size(2) + 0; } @@ -1269,9 +1287,18 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) !!(p->iph.frag_off & htons(IP_DF)))) goto nla_put_failure; - if (t->index) - if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver)) + goto nla_put_failure; + + if (t->erspan_ver == 1) { + if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) + goto nla_put_failure; + } else if (t->erspan_ver == 2) { + if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir)) + goto nla_put_failure; + if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid)) goto nla_put_failure; + } return 0; @@ -1291,6 +1318,9 @@ static const struct nla_policy ipgre_policy[RPL_IFLA_GRE_MAX + 1] = { [IFLA_GRE_TOS] = { .type = NLA_U8 }, [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, + [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, + [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, }; static struct rtnl_link_ops ipgre_link_ops __read_mostly = { From patchwork Fri May 18 01:57:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915958 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="ragQr1OO"; 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 40nBSf0zgXz9s19 for ; Fri, 18 May 2018 12:09:38 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8848A1131; Fri, 18 May 2018 01:58:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 84BF2FC5 for ; Fri, 18 May 2018 01:58:47 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f67.google.com (mail-pl0-f67.google.com [209.85.160.67]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 1B3DD6F9 for ; Fri, 18 May 2018 01:58:47 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id az12-v6so3624977plb.8 for ; Thu, 17 May 2018 18:58:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Ql5zHckoutwzkwrh+yOq+iYve1l5vcpvoK6Htq7JVWA=; b=ragQr1OOihMEQVn8MPXbJMMSZiKdU1h0OFFhaW8CGA9x5y4YIKc3OlEixDbQQdUA8B SlY5ZYgPiglSuXajUkEWGmyDfQKO+LX9j6mjmIN74Q3u/fLTNNDOMy11KNvAn8JXddR6 nXutEwMYt+1EjeGgnITDHnvl9cR4KcIIYdEtVacOgiXHwOm41OGqLTc3yLQ1mTK4WEme 0npJxSM6LoGr43FNLjO9NU1RDdtsfagPa07sSM4BPxszpPiaGI5PotbCDp3I+ccV+2Mg cj/Q4PFDoXu0lVicvtuukvzVV8Rg18gmjMj2r+u7zwQP8aZYXb0jg+8j4RJhcIEQBhd+ wRWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Ql5zHckoutwzkwrh+yOq+iYve1l5vcpvoK6Htq7JVWA=; b=SxFumRvoOFEvMWi4EOXdJF1CHkU5d+D6W11hxT15XXgEQxDeUYmyQrgpBOY/F1jFZ5 9P06uVDW1t5rq1uhgN0XMDo4i5RTfBjO04jHRvnI5utABWegH1yGqCnRN6hR+UgZru5k L37np4voy954biYbNB7H4ZqwXZZ+rwhRUSt+JT7yhobUGL3O1d7RSgkCGiZfIRGdeTGr tGscxzR+45pYyKrfCTbSGXKSfLi4Wnp3s9WfNWfYLyc6C5K2bro/Jj0b1HLxpXhXSnAb O+r9YWVd1/n64or4pOUxiqK/hdOD2f4oyHGXZ82p2w+MDvk44KNCmbjzaojmeEF3VY0w 5RuA== X-Gm-Message-State: ALKqPwfl99hBsfv+5Tx2EyD8tqFosofxdIZpmJgOI8M7Bi7KJAdLU5MJ C7QSgCqAynwHW2qODv2gJbF0rw== X-Google-Smtp-Source: AB8JxZqUt0Qtb4sz5J18Mv1FLubg7qph2ayr34qGaVrI10D72YhojaWq/4A2x7N/Pk7GohWnCFBqBw== X-Received: by 2002:a17:902:8f97:: with SMTP id z23-v6mr7612404plo.329.1526608726414; Thu, 17 May 2018 18:58:46 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:46 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:35 -0700 Message-Id: <1526608674-12702-23-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 22/41] compat: erspan: use bitfield instead of mask and offset X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit c69de58ba84f480879de64571d9dae5102d10ed6 Author: William Tu Date: Thu Jan 25 13:20:09 2018 -0800 net: erspan: use bitfield instead of mask and offset Originally the erspan fields are defined as a group into a __be16 field, and use mask and offset to access each field. This is more costly due to calling ntohs/htons. The patch changes it to use bitfields. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Folds in the ip_gre portions of this commit. Other portions of this commit are included in a previous patch where it is called out. Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip_gre.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 9bc3277..958965f 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -973,10 +973,11 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, /* Push ERSPAN header */ if (tunnel->erspan_ver == 1) - erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, + erspan_build_header(skb, ntohl(tunnel->parms.o_key), + tunnel->index, truncate, true); else - erspan_build_header_v2(skb, tunnel->parms.o_key, + erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), tunnel->dir, tunnel->hwid, truncate, true); From patchwork Fri May 18 01:57:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915960 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="KPWZcngW"; 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 40nBTD0Hlhz9s37 for ; Fri, 18 May 2018 12:10:08 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7528110E1; Fri, 18 May 2018 01:58: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 162F810A3 for ; Fri, 18 May 2018 01:58:49 +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 2A5CA6DB for ; Fri, 18 May 2018 01:58:48 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id v7-v6so2630614pgs.0 for ; Thu, 17 May 2018 18:58:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AN3kBEMJAPx+b3R3KzG8xQfJhvNeYLRnhie23KlFAbU=; b=KPWZcngWBw7oaJZD1fvAlKmNaWU7gvTSsofb/1BhhGaO79W/qGONc7m/U8UMlDUY2T UxO2CkIf0H5mqBwBPTG+wNLAAjwID3iXvQfJyaTSKfK+g/wpIeIBrJ33uDZ9H4MddcQP nbVFkSaSMRZMMa4rFGvMdl7oPXSkl3wS11hUKhvyg5JIZ+tQ4eHKdbv+M+LnbXP4ixuw VYnHx4iw+2v8PRnPNOBSI+PxNdq9FQUs+Ly+Z/fqIdKMz0Bpa1im2bsJ604Z7bK9hvnB /jSH6aV1yAW5GL2VGRy6UzUSvEiOKi+4OJP0oCw7Ae54+EBniXxQp5L3i7F+MN4JPkyw PtWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AN3kBEMJAPx+b3R3KzG8xQfJhvNeYLRnhie23KlFAbU=; b=ZXB8rNJnJhgFoiFEJQ4T9GFoY8LUmWsJbAlCINoRsGRoOJ1Nw+n6GyBisQrZkNWgf/ q/xw0qHM+rwRbudj/yp1dyxulb1k/DaLwFwHVKt2PzNDWAKxdUydHfRx6fy9OPupHgnz gt5Rp+zFgzARZ5dWJmtPa3zPBSVfzwa3XmvjiMo9M09LHjqEIoNP3aE/udQowTqwN5h0 gUuY7n+jzVxEs0AohJnX4Y1ZjliADHnuv8RAO5YS4RP3i/ewsmyslr8JKj9Vtl+JLM06 2XmNiUbti0qHTm0gsjaDQFI8xBWbNM/SV4cMpJK4dqsNa/Bu12tvDuRhdy2FZao7ccJj DwlQ== X-Gm-Message-State: ALKqPwebIx1CO9C2+SFIjUVhPV3e4q6M0GU1wGXcCE/sfkx4+Yz7LmbU zG+lzsXHDFCi0J3ao4fz1xPjxQ== X-Google-Smtp-Source: AB8JxZpsNS6UfJvKGWdXHhV3oJLNO5Sdd74JwJ/hbjV2YSaVl+53lqtiCl5Gb1Pu1TJ3ucYfjqXL8w== X-Received: by 2002:a62:f24a:: with SMTP id y10-v6mr7406683pfl.75.1526608727395; Thu, 17 May 2018 18:58:47 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:46 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:36 -0700 Message-Id: <1526608674-12702-24-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 23/41] datapath: add erspan version I and II support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit fc1372f89ffe1f58b589643b75f679e452350703 Author: William Tu Date: Thu Jan 25 13:20:11 2018 -0800 openvswitch: add erspan version I and II support The patch adds support for openvswitch to configure erspan v1 and v2. The OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS attr is added to uapi as a binary blob to support all ERSPAN v1 and v2's fields. Note that Previous commit "openvswitch: Add erspan tunnel support." was reverted since it does not design properly. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/flow_netlink.c | 52 ++++++++++++++++++++++- datapath/linux/compat/include/linux/openvswitch.h | 1 + lib/odp-util.c | 2 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index e2ccf91..1b7bad8 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "datapath.h" #include "conntrack.h" @@ -330,7 +331,8 @@ size_t ovs_tun_key_attr_size(void) + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ + nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */ - /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS is mutually exclusive with + /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and + * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it. */ + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */ @@ -401,6 +403,7 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] .next = ovs_vxlan_ext_key_lens }, [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, + [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, }; static const struct ovs_len_tbl @@ -632,6 +635,33 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr, return 0; } +static int erspan_tun_opt_from_nlattr(const struct nlattr *a, + struct sw_flow_match *match, bool is_mask, + bool log) +{ + unsigned long opt_key_offset; + + BUILD_BUG_ON(sizeof(struct erspan_metadata) > + sizeof(match->key->tun_opts)); + + if (nla_len(a) > sizeof(match->key->tun_opts)) { + OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).", + nla_len(a), sizeof(match->key->tun_opts)); + return -EINVAL; + } + + if (!is_mask) + SW_FLOW_KEY_PUT(match, tun_opts_len, + sizeof(struct erspan_metadata), false); + else + SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true); + + opt_key_offset = TUN_METADATA_OFFSET(nla_len(a)); + SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a), + nla_len(a), is_mask); + return 0; +} + static int ip_tun_from_nlattr(const struct nlattr *attr, struct sw_flow_match *match, bool is_mask, bool log) @@ -739,6 +769,20 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, break; case OVS_TUNNEL_KEY_ATTR_PAD: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + if (opts_type) { + OVS_NLERR(log, "Multiple metadata blocks provided"); + return -EINVAL; + } + + err = erspan_tun_opt_from_nlattr(a, match, is_mask, + log); + if (err) + return err; + + tun_flags |= TUNNEL_ERSPAN_OPT; + opts_type = type; + break; default: OVS_NLERR(log, "Unknown IP tunnel attribute %d", type); @@ -863,6 +907,10 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, else if (output->tun_flags & TUNNEL_VXLAN_OPT && vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len)) return -EMSGSIZE; + else if (output->tun_flags & TUNNEL_ERSPAN_OPT && + nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, + swkey_tun_opts_len, tun_opts)) + return -EMSGSIZE; } return 0; @@ -2490,6 +2538,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, break; case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + break; } } diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 771220b..6f4fa01 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -398,6 +398,7 @@ enum ovs_tunnel_key_attr { OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ OVS_TUNNEL_KEY_ATTR_PAD, + OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */ __OVS_TUNNEL_KEY_ATTR_MAX }; diff --git a/lib/odp-util.c b/lib/odp-util.c index 70188b6..752836a 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -3489,6 +3489,8 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr, break; case OVS_TUNNEL_KEY_ATTR_PAD: break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + break; case __OVS_TUNNEL_KEY_ATTR_MAX: default: format_unknown_key(ds, a, ma); From patchwork Fri May 18 01:57:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915961 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="QlM2Qtsw"; 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 40nBTl6DX3z9s19 for ; Fri, 18 May 2018 12:10:35 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 91537113C; Fri, 18 May 2018 01:59:00 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 96B3D10E8 for ; Fri, 18 May 2018 01:58:49 +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 DF2596FA for ; Fri, 18 May 2018 01:58:48 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id a14-v6so2966358pfi.1 for ; Thu, 17 May 2018 18:58:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=180UToHz+/5upm/xU7/kHY7oDrdiwqCL4sXyx3n4SVo=; b=QlM2QtswDhYmpBhvA/YrNnCX78kev9WRMWxFc2/1eMp5KtYLD5q8S7YYLtrodGRHxy qqxiRqFzbjiHQNWc46KgGsGLxTY/GiaZs7TqO+e/LdX84ldiCyyxHxavk9RGKzbdnpWB tzXw+E//ZG7YrcsJksK4MiJ1T+5dys8hdZfu12amEhfympAtD9yHwi18Bj2M2udLmBg2 Gd+nXLedYV0Ch1FOWPmiuiMznB1YS3+zHvhSyu73b5Z9EW6cB9vxJH85GHM4+pPLKBCB uoYpbgE4t89U0YAAOmf/q/sGUAXY3K4DtwuDpAQcRQMW1fMcAg5MNF3gp9RULYauvwr/ +qig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=180UToHz+/5upm/xU7/kHY7oDrdiwqCL4sXyx3n4SVo=; b=RznKJcWhziSz1KVMhXay/U4jnHdGS/WlhE7PM3ldTNwtdC1GxwBFFluUaHcpBh9TGp R6D84VW0z+TpHAshruYy79iObhnLDYOXx2yzVmWwFm9dAs6k4svHc4SC32sdbTIZt6zd wXsDC4OezcsxCfccFgVfgob0JraOPFoBtw8jh0D+0Nzkx8QI1NcXFgotqje1J60It5DJ G3QwXBpxT9t/oCp/ODPCN4PNX82KZ4iPrL1jxjokIyr0yf+d02yShIFXt2P2Ej0ihTob nS1KonCY0QpUM1WN6NyZ0VFPRim5CLqWePrUc7oJUZv1WTPiDOS5aByTqL7e3bTeIuAO 9WwA== X-Gm-Message-State: ALKqPwdcHDo0dDcpU2M06pRlyLHGN60vECGXLUwqUCpIgpIeImiK83xS ngbWdd/BS6EygdzVqmoXHCd0Gg== X-Google-Smtp-Source: AB8JxZrFgMqwZUHEAp/jpe+l6pa6KQVV/sMQ54ivLUom5fMVtwOtCaKyGn3ltudlQFlvampWNcs7hw== X-Received: by 2002:a62:c987:: with SMTP id l7-v6mr7247045pfk.221.1526608728274; Thu, 17 May 2018 18:58:48 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:47 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:37 -0700 Message-Id: <1526608674-12702-25-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 24/41] netdev-native-tnl: refactor the tunnel push header. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu The patch adds additional 'struct netdev *' to the native tunnel's push_header() interface. This is used for later GRE sequence number support. Signed-off-by: William Tu --- lib/netdev-native-tnl.c | 6 ++++-- lib/netdev-native-tnl.h | 6 ++++-- lib/netdev-provider.h | 3 ++- lib/netdev.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index c3e698d..5eb3d22 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -215,7 +215,8 @@ udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl, void -netdev_tnl_push_udp_header(struct dp_packet *packet, +netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED, + struct dp_packet *packet, const struct ovs_action_push_tnl *data) { struct udp_header *udp; @@ -435,7 +436,8 @@ err: } void -netdev_gre_push_header(struct dp_packet *packet, +netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, + struct dp_packet *packet, const struct ovs_action_push_tnl *data) { struct gre_base_hdr *greh; diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index a912ce9..5012b2d 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -34,13 +34,15 @@ netdev_gre_build_header(const struct netdev *netdev, const struct netdev_tnl_build_header_params *params); void -netdev_gre_push_header(struct dp_packet *packet, +netdev_gre_push_header(const struct netdev *netdev, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); struct dp_packet * netdev_gre_pop_header(struct dp_packet *packet); void -netdev_tnl_push_udp_header(struct dp_packet *packet, +netdev_tnl_push_udp_header(const struct netdev *netdev, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); int netdev_geneve_build_header(const struct netdev *netdev, diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 6e8ae4f..5503b79 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -314,7 +314,8 @@ struct netdev_class { * flow. Push header is called for packet to build header specific to * a packet on actual transmit. It uses partial header build by * build_header() which is passed as data. */ - void (*push_header)(struct dp_packet *packet, + void (*push_header)(const struct netdev *, + struct dp_packet *packet, const struct ovs_action_push_tnl *data); /* Pop tunnel header from packet, build tunnel metadata and resize packet diff --git a/lib/netdev.c b/lib/netdev.c index a1ac1b5..dec35de 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -858,7 +858,7 @@ netdev_push_header(const struct netdev *netdev, { struct dp_packet *packet; DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - netdev->netdev_class->push_header(packet, data); + netdev->netdev_class->push_header(netdev, packet, data); pkt_metadata_init(&packet->md, data->out_port); } From patchwork Fri May 18 01:57:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915962 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="gFB5qh+p"; 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 40nBVJ0m8Zz9s19 for ; Fri, 18 May 2018 12:11:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 931391138; Fri, 18 May 2018 01:59: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 1C76910F2 for ; Fri, 18 May 2018 01:58:52 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f51.google.com (mail-pl0-f51.google.com [209.85.160.51]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8ACAF6F8 for ; Fri, 18 May 2018 01:58:51 +0000 (UTC) Received: by mail-pl0-f51.google.com with SMTP id az12-v6so3625062plb.8 for ; Thu, 17 May 2018 18:58:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4GQY7z5NyC1wygOl0cT8Us2f2XQ6o5sdFTQJM17wRSU=; b=gFB5qh+pj7QwtmKzcnjjQZXI6vkwWlKH6pZNqvJ+uBCZHkglUXbsjBqzR2YkSO9mb9 TgI+7uSZhf/Z+38XA/wDjkLDi+jcQ2SKKqzu5hnLNIebNudXkGwFnO/1lKc09QmiD13y jvhqSC+WktkFRRHF1y3BEetIIs5Ie4jha549qihgYlQW6M89lpw2+E1rWQxlB1ewEE// FXiaFaU11OjF1nalhsA8BRilSFjmICJKChY3EWGJokJCv+VU4NgtbSA7Iq4Q8bWHajkG /tQQ0cpOOcXwelsJxih1Sb9RoLdaum7UW0kBGGK3TNOXdNyvYBkzIF//NIrXdeLYVnow yuTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4GQY7z5NyC1wygOl0cT8Us2f2XQ6o5sdFTQJM17wRSU=; b=YFqHTqXBBFL7j8t6sXDeY+VOUivcBicggfhA97wuWSXh3VzNMLBLzKbn8ckS59Zauo 5VDAmbbELc3ngFzOVFz3MgAuS/sYKJOg8JdIUxw83I1K8+tWcaoYyhVNRScYvP0Uslq+ iV3hn/XU7ICRQy/TaDBaX/0mdf4Q6a31mKq2osFJK4ADDzHqSO2CDCgQsjnNKfUaM/O1 qpvZH0hTunMUPYM1XXBkQEYyQngGYzMk/g3NtQ9pxFcRX4NTGoWVgfeu3r6IRXBZO+EO tx6sHaZpaJNu5knW2Lp7I7lIlx2da9SlLIaMgAmsso90gWNfCddi5PuIx20SYT01nakB 4Pqw== X-Gm-Message-State: ALKqPweWqMIgQyl4IeppGnrNhhEndgv4iSvn9/WtKoo6Ft6rAiytPJAa WCBZ8YOpWNyuiDEm58JCYNd9Hg== X-Google-Smtp-Source: AB8JxZqXp5dn80slySoNZp0kRvE0DMZbJPuiMYm3ttbg1ghbTbGTbqZE6Lae18dVuQKzYQ5wNYBIrg== X-Received: by 2002:a17:902:7409:: with SMTP id g9-v6mr7472170pll.255.1526608729320; Thu, 17 May 2018 18:58:49 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:48 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:38 -0700 Message-Id: <1526608674-12702-26-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 25/41] userspace: add gre sequence number support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu The patch adds support for gre sequence number. Default is disable. When enable with 'options:seq=true', the outgoing gre packet will have its sequence number incremented by one. Signed-off-by: William Tu --- lib/netdev-native-tnl.c | 19 ++++++++++++++++++- lib/netdev-vport.c | 11 ++++++++++- lib/netdev.h | 3 +++ tests/tunnel-push-pop.at | 8 ++++---- vswitchd/vswitch.xml | 7 +++++++ 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 5eb3d22..876718a 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -436,10 +436,12 @@ err: } void -netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, +netdev_gre_push_header(const struct netdev *netdev, struct dp_packet *packet, const struct ovs_action_push_tnl *data) { + struct netdev_vport *dev = netdev_vport_cast(netdev); + struct netdev_tunnel_config *tnl_cfg; struct gre_base_hdr *greh; int ip_tot_size; @@ -449,6 +451,15 @@ netdev_gre_push_header(const struct netdev *netdev OVS_UNUSED, ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1); *csum_opt = csum(greh, ip_tot_size); } + + if (greh->flags & htons(GRE_SEQ)) { + /* Last 4 byte is GRE seqno */ + int seq_ofs = gre_header_len(greh->flags) - 4; + ovs_16aligned_be32 *seq_opt = + ALIGNED_CAST(ovs_16aligned_be32 *, (char *)greh + seq_ofs); + tnl_cfg = &dev->tnl_cfg; + put_16aligned_be32(seq_opt, htonl(tnl_cfg->seqno++)); + } } int @@ -491,6 +502,12 @@ netdev_gre_build_header(const struct netdev *netdev, options++; } + if (tnl_cfg->set_seq) { + greh->flags |= htons(GRE_SEQ); + /* seqno is updated at push header */ + options++; + } + ovs_mutex_unlock(&dev->mutex); hlen = (uint8_t *) options - (uint8_t *) greh; diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 52aa12d..cc50aa5 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -428,7 +428,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) const char *name = netdev_get_name(dev_); const char *type = netdev_get_type(dev_); struct ds errors = DS_EMPTY_INITIALIZER; - bool needs_dst_port, has_csum; + bool needs_dst_port, has_csum, has_seq; uint16_t dst_proto = 0, src_proto = 0; struct netdev_tunnel_config tnl_cfg; struct smap_node *node; @@ -436,6 +436,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) has_csum = strstr(type, "gre") || strstr(type, "geneve") || strstr(type, "stt") || strstr(type, "vxlan"); + has_seq = strstr(type, "gre"); memset(&tnl_cfg, 0, sizeof tnl_cfg); /* Add a default destination port for tunnel ports if none specified. */ @@ -506,6 +507,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) if (!strcmp(node->value, "true")) { tnl_cfg.csum = true; } + } else if (!strcmp(node->key, "seq") && has_seq) { + if (!strcmp(node->value, "true")) { + tnl_cfg.set_seq = true; + } } else if (!strcmp(node->key, "df_default")) { if (!strcmp(node->value, "false")) { tnl_cfg.dont_fragment = false; @@ -709,6 +714,10 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) smap_add(args, "csum", "true"); } + if (tnl_cfg.set_seq) { + smap_add(args, "seq", "true"); + } + enum tunnel_layers layers = tunnel_supported_layers(type, &tnl_cfg); if (tnl_cfg.pt_mode != default_pt_mode(layers)) { smap_add(args, "packet_type", diff --git a/lib/netdev.h b/lib/netdev.h index bd6f45a..e331cac 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -127,6 +127,9 @@ struct netdev_tunnel_config { bool csum; bool dont_fragment; enum netdev_pt_mode pt_mode; + + bool set_seq; + uint32_t seqno; }; void netdev_run(void); diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 10f98c6..4bd412e 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -358,7 +358,7 @@ AT_SETUP([tunnel_push_pop - underlay bridge match]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=gre \ - options:remote_ip=1.1.2.92 options:key=456 ofport_request=3], [0]) + options:remote_ip=1.1.2.92 options:key=456 options:seq=true ofport_request=3], [0]) AT_CHECK([ovs-appctl dpif/show], [0], [dnl dummy@ovs-dummy: hit:0 missed:0 @@ -367,7 +367,7 @@ dummy@ovs-dummy: hit:0 missed:0 p0 1/1: (dummy) int-br: int-br 65534/2: (dummy-internal) - t1 3/3: (gre: key=456, remote_ip=1.1.2.92) + t1 3/3: (gre: key=456, remote_ip=1.1.2.92, seq=true) ]) AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK @@ -390,14 +390,14 @@ AT_CHECK([ovs-ofctl add-flow int-br action=3]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4789)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], - [Datapath actions: clone(tnl_push(tnl_port(3),header(size=42,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x2000,proto=0x6558),key=0x1c8)),out_port(100)),1) + [Datapath actions: tnl_push(tnl_port(3),header(size=46,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x3000,proto=0x6558),key=0x1c8,seq=0x0)),out_port(100)) ]) dnl Verify outer L2 and L3 header flow fields can be matched in the underlay bridge AT_CHECK([ovs-appctl netdev-dummy/receive int-br '50540000000a5054000000091234']) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl) n_packets=1, n_bytes=42, priority=1,arp actions=NORMAL - n_packets=1, n_bytes=56, priority=99,ip,dl_src=aa:55:aa:55:00:00,dl_dst=f8:bc:12:44:34:b6,nw_src=1.1.2.88,nw_dst=1.1.2.92,nw_proto=47,nw_tos=0 actions=NORMAL + n_packets=1, n_bytes=60, priority=99,ip,dl_src=aa:55:aa:55:00:00,dl_dst=f8:bc:12:44:34:b6,nw_src=1.1.2.88,nw_dst=1.1.2.92,nw_proto=47,nw_tos=0 actions=NORMAL NXST_FLOW reply: ]) diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 7ab90d5..acc1b03 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -2596,6 +2596,13 @@ + +

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

+
From patchwork Fri May 18 01:57: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: 915969 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="EirGDa9u"; 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 40nBZ85NnFz9s28 for ; Fri, 18 May 2018 12:14:24 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C2A2F1163; Fri, 18 May 2018 01:59:12 +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 2984310E4 for ; Fri, 18 May 2018 01:58:57 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f50.google.com (mail-pg0-f50.google.com [74.125.83.50]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 82C1D6DB for ; Fri, 18 May 2018 01:58:53 +0000 (UTC) Received: by mail-pg0-f50.google.com with SMTP id a13-v6so2608739pgu.4 for ; Thu, 17 May 2018 18:58:53 -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=yAQLiU9QIrY8gNOZWojpX45odyKmSnsf2gcUVw+0Nn0=; b=EirGDa9uLpo9tX6CEa/xAxKC/tyVlFLJtmaMPnjBVNsq0eZUu57glHdlvm04ZNmeh/ W6MaqCkbP6eHWIHoWx80epSyNond7oLzDXDMpS4exu+fzKMuc9LUs6LOUDEljqxiNr3C upsz/GA5aPaF1N+WSvxzEQoEz0WQtiptlZV7E8LnENHF52gqRpHES66sZcpT8hlf9G4L mIsCt0XIo7DrONXMiO5J8pzX9lHd+QZBDx3GcfJTXW1QKBaejq/umBGAGDI3+M0TQZU+ hiw0Ldl+TlXKJxDyUemVJGBSSIuDVE2kLB7s0Bn8Bs5ZjCeibVoEcMkVmze0v/+Q0iO1 3AGQ== 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=yAQLiU9QIrY8gNOZWojpX45odyKmSnsf2gcUVw+0Nn0=; b=QwO/uJtvwACKW8Vdl1amsO0fUd1BYMj/3Uc8uVlw+GSo/joTtJQq0AAwdHS070AIP0 wxnY2Qd8/TQr0QP/ouYAbzFRuuO6+JkbOyuimOiUIsBCp2Hi70jl3fxMKSw/RLTW5JOC S9NILLnOrZtZK+HlK2BTvjr77jUUE8QWaXdFXW4Jx9EjZuStib7NQDYKnlN4it47wNBN 1yubDbE9utfb22C2ijPhxjihwg6MyMyPSLgdEtq1P6QuyJyTw2s6J1hh/nvJYdKiNg93 yNHhYF7BJUCj8pchjwAIpYpHqlxkvOJLfCnYlu27PI1bpgXgbrDT6HFvO9scd+25H60n X0Og== X-Gm-Message-State: ALKqPwenaQVaqX+KIHax4TOWMw13RNtZpVN1pvhjxAGoctnGhbXEGmtr wYhzAYrJjNDxo4FNjugmBDA7DQ== X-Google-Smtp-Source: AB8JxZqp8VOtaLGoXNnDEgI5UjMq7zL+tXuukbBCx4PuZj+Q5TdTBP67zHCETnGFJLvvDM6dZJy6yA== X-Received: by 2002:a62:a315:: with SMTP id s21-v6mr7443292pfe.168.1526608731395; Thu, 17 May 2018 18:58:51 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:50 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:39 -0700 Message-Id: <1526608674-12702-27-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 26/41] userspace: add erspan tunnel support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu ERSPAN is a tunneling protocol based on GRE tunnel. The patch add erspan tunnel support for ovs-vswitchd with userspace datapath. Configuring erspan tunnel is similar to gre tunnel, but with additional erspan's parameters. Matching a flow on erspan's metadata is also supported, see ovs-fields for more details. Cc: Ben Pfaff Signed-off-by: William Tu Signed-off-by: Greg Rose --- V2 - Additional changes from Ben Pfaff folded in as per his suggestion. --- include/openvswitch/flow.h | 4 +- include/openvswitch/match.h | 12 +++ include/openvswitch/meta-flow.h | 56 ++++++++++++++ include/openvswitch/packets.h | 6 +- lib/dpif-netlink.c | 4 + lib/flow.c | 32 ++++++-- lib/flow.h | 2 +- lib/match.c | 69 ++++++++++++++++- lib/meta-flow.c | 77 +++++++++++++++++++ lib/meta-flow.xml | 89 +++++++++++++++++++++ lib/netdev-native-tnl.c | 166 ++++++++++++++++++++++++++++++++++++++++ lib/netdev-native-tnl.h | 12 +++ lib/netdev-vport.c | 54 +++++++++++++ lib/netdev.h | 4 + lib/nx-match.c | 13 +++- lib/odp-util.c | 80 ++++++++++++++++++- lib/odp-util.h | 2 +- lib/ofp-match.c | 2 +- lib/packets.h | 126 ++++++++++++++++++++++++++++++ lib/tnl-ports.c | 3 +- ofproto/ofproto-dpif-rid.h | 2 +- ofproto/ofproto-dpif-xlate.c | 2 +- ofproto/tunnel.c | 13 ++++ tests/ofproto.at | 6 +- tests/tunnel-push-pop-ipv6.at | 118 ++++++++++++++++++++++++++++ tests/tunnel-push-pop.at | 137 +++++++++++++++++++++++++++++++++ tests/tunnel.at | 12 +++ vswitchd/vswitch.xml | 34 ++++++++ 28 files changed, 1115 insertions(+), 22 deletions(-) diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h index cd61fff..5d2cf09 100644 --- a/include/openvswitch/flow.h +++ b/include/openvswitch/flow.h @@ -27,7 +27,7 @@ extern "C" { /* This sequence number should be incremented whenever anything involving flows * or the wildcarding of flows changes. This will cause build assertion * failures in places which likely need to be updated. */ -#define FLOW_WC_SEQ 40 +#define FLOW_WC_SEQ 41 /* Number of Open vSwitch extension 32-bit registers. */ #define FLOW_N_REGS 16 @@ -166,7 +166,7 @@ BUILD_ASSERT_DECL(sizeof(struct ovs_key_nsh) % sizeof(uint64_t) == 0); /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t) == sizeof(struct flow_tnl) + sizeof(struct ovs_key_nsh) + 300 - && FLOW_WC_SEQ == 40); + && FLOW_WC_SEQ == 41); /* Incremental points at which flow classification may be performed in * segments. diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h index 49333ae..49e463a 100644 --- a/include/openvswitch/match.h +++ b/include/openvswitch/match.h @@ -109,6 +109,18 @@ void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id); void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask); void match_set_tun_gbp_flags(struct match *match, uint8_t flags); +void match_set_tun_erspan_ver(struct match *match, uint8_t ver); +void match_set_tun_erspan_ver_masked(struct match *match, uint8_t ver, + uint8_t mask); +void match_set_tun_erspan_idx(struct match *match, uint32_t idx); +void match_set_tun_erspan_idx_masked(struct match *match, uint32_t idx, + uint32_t mask); +void match_set_tun_erspan_dir(struct match *match, uint8_t dir); +void match_set_tun_erspan_dir_masked(struct match *match, uint8_t dir, + uint8_t mask); +void match_set_tun_erspan_hwid(struct match *match, uint8_t hwid); +void match_set_tun_erspan_hwid_masked(struct match *match, uint8_t hwid, + uint8_t mask); void match_set_in_port(struct match *, ofp_port_t ofp_port); void match_set_pkt_mark(struct match *, uint32_t pkt_mark); void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask); diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 98c9e1c..64470b5 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -450,6 +450,62 @@ enum OVS_PACKED_ENUM mf_field_id { */ MFF_TUN_GBP_FLAGS, + /* "tun_erspan_idx". + * + * ERSPAN index (direction/port number) + * + * Type: be32 (low 20 bits). + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_IDX(11) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_IDX, + + /* "tun_erspan_ver". + * + * ERSPAN version (v1 / v2) + * + * Type: u8 (low 4 bits). + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_VER(12) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_VER, + + /* "tun_erspan_dir". + * + * ERSPAN mirrored traffic's direction + * + * Type: u8 (low 1 bits). + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_DIR(13) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_DIR, + + /* "tun_erspan_hwid". + * + * ERSPAN Hardware ID + * + * Type: u8 (low 6 bits). + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_HWID(14) since OF1.5 and v2.10. + */ + MFF_TUN_ERSPAN_HWID, + #if TUN_METADATA_NUM_OPTS == 64 /* "tun_metadata". * diff --git a/include/openvswitch/packets.h b/include/openvswitch/packets.h index fef756b..925844e 100644 --- a/include/openvswitch/packets.h +++ b/include/openvswitch/packets.h @@ -39,7 +39,11 @@ struct flow_tnl { ovs_be16 tp_dst; ovs_be16 gbp_id; uint8_t gbp_flags; - uint8_t pad1[5]; /* Pad to 64 bits. */ + uint8_t erspan_ver; + uint32_t erspan_idx; + uint8_t erspan_dir; + uint8_t erspan_hwid; + uint8_t pad1[6]; /* Pad to 64 bits. */ struct tun_metadata metadata; }; diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index e8ffd6f..a8b3ec6 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -819,6 +819,10 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_VXLAN; } else if (!strcmp(type, "lisp")) { return OVS_VPORT_TYPE_LISP; + } else if (!strcmp(type, "erspan")) { + return OVS_VPORT_TYPE_ERSPAN; + } else if (!strcmp(type, "ip6erspan")) { + return OVS_VPORT_TYPE_IP6ERSPAN; } else { return OVS_VPORT_TYPE_UNSPEC; } diff --git a/lib/flow.c b/lib/flow.c index 09b66b8..136f060 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -126,7 +126,7 @@ struct mf_ctx { * away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are * defined as macros. */ -#if (FLOW_WC_SEQ != 40) +#if (FLOW_WC_SEQ != 41) #define MINIFLOW_ASSERT(X) ovs_assert(X) BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime " "assertions enabled. Consider updating FLOW_WC_SEQ after " @@ -1014,7 +1014,7 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) { int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); match_init_catchall(flow_metadata); if (flow->tunnel.tun_id != htonll(0)) { @@ -1042,6 +1042,18 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) if (flow->tunnel.gbp_flags) { match_set_tun_gbp_flags(flow_metadata, flow->tunnel.gbp_flags); } + if (flow->tunnel.erspan_ver) { + match_set_tun_erspan_ver(flow_metadata, flow->tunnel.erspan_ver); + } + if (flow->tunnel.erspan_idx) { + match_set_tun_erspan_idx(flow_metadata, flow->tunnel.erspan_idx); + } + if (flow->tunnel.erspan_dir) { + match_set_tun_erspan_dir(flow_metadata, flow->tunnel.erspan_dir); + } + if (flow->tunnel.erspan_hwid) { + match_set_tun_erspan_hwid(flow_metadata, flow->tunnel.erspan_hwid); + } tun_metadata_get_fmd(&flow->tunnel, flow_metadata); if (flow->metadata != htonll(0)) { match_set_metadata(flow_metadata, flow->metadata); @@ -1581,7 +1593,7 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc, memset(&wc->masks, 0x0, sizeof wc->masks); /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); if (flow_tnl_dst_is_set(&flow->tunnel)) { if (flow->tunnel.flags & FLOW_TNL_F_KEY) { @@ -1598,6 +1610,10 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc, WC_MASK_FIELD(wc, tunnel.tp_dst); WC_MASK_FIELD(wc, tunnel.gbp_id); WC_MASK_FIELD(wc, tunnel.gbp_flags); + WC_MASK_FIELD(wc, tunnel.erspan_ver); + WC_MASK_FIELD(wc, tunnel.erspan_idx); + WC_MASK_FIELD(wc, tunnel.erspan_dir); + WC_MASK_FIELD(wc, tunnel.erspan_hwid); if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) { if (flow->tunnel.metadata.present.map) { @@ -1728,7 +1744,7 @@ void flow_wc_map(const struct flow *flow, struct flowmap *map) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); flowmap_init(map); @@ -1829,7 +1845,7 @@ void flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata); memset(&wc->masks.regs, 0, sizeof wc->masks.regs); @@ -1973,7 +1989,7 @@ flow_wildcards_set_xxreg_mask(struct flow_wildcards *wc, int idx, uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); uint32_t hash = basis; if (flow) { @@ -2020,7 +2036,7 @@ ASSERT_SEQUENTIAL(ipv6_src, ipv6_dst); uint32_t flow_hash_5tuple(const struct flow *flow, uint32_t basis) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); uint32_t hash = basis; if (flow) { @@ -2609,7 +2625,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type, if (clear_flow_L3) { /* Clear all L3 and L4 fields and dp_hash. */ - BUILD_ASSERT(FLOW_WC_SEQ == 40); + BUILD_ASSERT(FLOW_WC_SEQ == 41); memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0, sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT); flow->dp_hash = 0; diff --git a/lib/flow.h b/lib/flow.h index af82931..7a9e7d0 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -959,7 +959,7 @@ static inline void pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); md->recirc_id = flow->recirc_id; md->dp_hash = flow->dp_hash; diff --git a/lib/match.c b/lib/match.c index 2e9a803..bf7e636 100644 --- a/lib/match.c +++ b/lib/match.c @@ -320,6 +320,61 @@ match_set_tun_gbp_flags(struct match *match, uint8_t flags) } void +match_set_tun_erspan_ver_masked(struct match *match, uint8_t ver, uint8_t mask) +{ + match->wc.masks.tunnel.erspan_ver = ver; + match->flow.tunnel.erspan_ver = ver & mask; +} + +void +match_set_tun_erspan_ver(struct match *match, uint8_t ver) +{ + match_set_tun_erspan_ver_masked(match, ver, UINT8_MAX); +} + +void +match_set_tun_erspan_idx_masked(struct match *match, uint32_t erspan_idx, + uint32_t mask) +{ + match->wc.masks.tunnel.erspan_idx = mask; + match->flow.tunnel.erspan_idx = erspan_idx & mask; +} + +void +match_set_tun_erspan_idx(struct match *match, uint32_t erspan_idx) +{ + match_set_tun_erspan_idx_masked(match, erspan_idx, UINT32_MAX); +} + +void +match_set_tun_erspan_dir_masked(struct match *match, uint8_t dir, + uint8_t mask) +{ + match->wc.masks.tunnel.erspan_dir = dir; + match->flow.tunnel.erspan_dir = dir & mask; +} + +void +match_set_tun_erspan_dir(struct match *match, uint8_t dir) +{ + match_set_tun_erspan_dir_masked(match, dir, UINT8_MAX); +} + +void +match_set_tun_erspan_hwid_masked(struct match *match, uint8_t hwid, + uint8_t mask) +{ + match->wc.masks.tunnel.erspan_hwid = hwid; + match->flow.tunnel.erspan_hwid = hwid & mask; +} + +void +match_set_tun_erspan_hwid(struct match *match, uint8_t hwid) +{ + match_set_tun_erspan_hwid_masked(match, hwid, UINT8_MAX); +} + +void match_set_in_port(struct match *match, ofp_port_t ofp_port) { match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX); @@ -1232,6 +1287,18 @@ format_flow_tunnel(struct ds *s, const struct match *match) if (wc->masks.tunnel.ip_ttl) { ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl); } + if (wc->masks.tunnel.erspan_ver) { + ds_put_format(s, "tun_erspan_ver=%"PRIu8",", tnl->erspan_ver); + } + if (wc->masks.tunnel.erspan_idx && tnl->erspan_ver == 1) { + ds_put_format(s, "tun_erspan_idx=%#"PRIx32",", tnl->erspan_idx); + } + if (wc->masks.tunnel.erspan_dir && tnl->erspan_ver == 2) { + ds_put_format(s, "tun_erspan_dir=%"PRIu8",", tnl->erspan_dir); + } + if (wc->masks.tunnel.erspan_hwid && tnl->erspan_ver == 2) { + ds_put_format(s, "tun_erspan_hwid=%#"PRIx8",", tnl->erspan_hwid); + } if (wc->masks.tunnel.flags & FLOW_TNL_F_MASK) { format_flags_masked(s, "tun_flags", flow_tun_flag_to_string, tnl->flags & FLOW_TNL_F_MASK, @@ -1303,7 +1370,7 @@ match_format(const struct match *match, bool is_megaflow = false; int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 40); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "%spriority=%s%d,", diff --git a/lib/meta-flow.c b/lib/meta-flow.c index aa2ec01..8b8d174 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -231,6 +231,14 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) return !wc->masks.tunnel.gbp_id; case MFF_TUN_GBP_FLAGS: return !wc->masks.tunnel.gbp_flags; + case MFF_TUN_ERSPAN_VER: + return !wc->masks.tunnel.erspan_ver; + case MFF_TUN_ERSPAN_IDX: + return !wc->masks.tunnel.erspan_idx; + case MFF_TUN_ERSPAN_DIR: + return !wc->masks.tunnel.erspan_dir; + case MFF_TUN_ERSPAN_HWID: + return !wc->masks.tunnel.erspan_hwid; CASE_MFF_TUN_METADATA: return !ULLONG_GET(wc->masks.tunnel.metadata.present.map, mf->id - MFF_TUN_METADATA0); @@ -513,6 +521,10 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_TUN_TTL: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_ERSPAN_IDX: + case MFF_TUN_ERSPAN_VER: + case MFF_TUN_ERSPAN_DIR: + case MFF_TUN_ERSPAN_HWID: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -680,6 +692,18 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, case MFF_TUN_TOS: value->u8 = flow->tunnel.ip_tos; break; + case MFF_TUN_ERSPAN_VER: + value->u8 = flow->tunnel.erspan_ver; + break; + case MFF_TUN_ERSPAN_IDX: + value->be32 = htonl(flow->tunnel.erspan_idx); + break; + case MFF_TUN_ERSPAN_DIR: + value->u8 = flow->tunnel.erspan_dir; + break; + case MFF_TUN_ERSPAN_HWID: + value->u8 = flow->tunnel.erspan_hwid; + break; CASE_MFF_TUN_METADATA: tun_metadata_read(&flow->tunnel, mf, value); break; @@ -994,6 +1018,18 @@ mf_set_value(const struct mf_field *mf, case MFF_TUN_TTL: match_set_tun_ttl(match, value->u8); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver(match, value->u8); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx(match, ntohl(value->be32)); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir(match, value->u8); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid(match, value->u8); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, value, NULL, match, err_str); break; @@ -1391,6 +1427,18 @@ mf_set_flow_value(const struct mf_field *mf, case MFF_TUN_TTL: flow->tunnel.ip_ttl = value->u8; break; + case MFF_TUN_ERSPAN_VER: + flow->tunnel.erspan_ver = value->u8; + break; + case MFF_TUN_ERSPAN_IDX: + flow->tunnel.erspan_idx = ntohl(value->be32); + break; + case MFF_TUN_ERSPAN_DIR: + flow->tunnel.erspan_dir = value->u8; + break; + case MFF_TUN_ERSPAN_HWID: + flow->tunnel.erspan_hwid = value->u8; + break; CASE_MFF_TUN_METADATA: tun_metadata_write(&flow->tunnel, mf, value); break; @@ -1700,6 +1748,10 @@ mf_is_pipeline_field(const struct mf_field *mf) case MFF_TUN_FLAGS: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: + case MFF_TUN_ERSPAN_VER: + case MFF_TUN_ERSPAN_IDX: + case MFF_TUN_ERSPAN_DIR: + case MFF_TUN_ERSPAN_HWID: CASE_MFF_TUN_METADATA: case MFF_METADATA: case MFF_IN_PORT: @@ -1876,6 +1928,18 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) case MFF_TUN_TTL: match_set_tun_ttl_masked(match, 0, 0); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir_masked(match, 0, 0); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid_masked(match, 0, 0); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, NULL, NULL, match, err_str); break; @@ -2256,6 +2320,19 @@ mf_set(const struct mf_field *mf, case MFF_TUN_TOS: match_set_tun_tos_masked(match, value->u8, mask->u8); break; + case MFF_TUN_ERSPAN_VER: + match_set_tun_erspan_ver_masked(match, value->u8, mask->u8); + break; + case MFF_TUN_ERSPAN_IDX: + match_set_tun_erspan_idx_masked(match, ntohl(value->be32), + ntohl(mask->be32)); + break; + case MFF_TUN_ERSPAN_DIR: + match_set_tun_erspan_dir_masked(match, value->u8, mask->u8); + break; + case MFF_TUN_ERSPAN_HWID: + match_set_tun_erspan_hwid_masked(match, value->u8, mask->u8); + break; CASE_MFF_TUN_METADATA: tun_metadata_set_match(mf, value, mask, match, err_str); break; diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml index 933d4b8..144657c 100644 --- a/lib/meta-flow.xml +++ b/lib/meta-flow.xml @@ -1456,6 +1456,7 @@ ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
  • LISP has a 24-bit instance ID.
  • GRE has an optional 32-bit key.
  • STT has a 64-bit key.
  • +
  • ERSPAN has a 10-bit key (Session ID).
  • @@ -1715,6 +1716,87 @@ ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1' +

    ERSPAN Metadata Fields

    +

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

    + +

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

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

    + The ERSPAN version 2 header format is: +

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

    Geneve Fields

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

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

    + Only erspan interfaces support these options. +

    + +

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

    +
    + + +

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

    +
    + + +

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

    +
    + + +

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

    +
    +
    +

    These options apply only to patch ports, that is, interfaces From patchwork Fri May 18 01:57: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: 915966 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="ClugaEAg"; 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 40nBXQ5ptcz9s37 for ; Fri, 18 May 2018 12:12:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 86C1D1160; Fri, 18 May 2018 01:59: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 5F4EB110A for ; Fri, 18 May 2018 01:58:55 +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 D54206FA for ; Fri, 18 May 2018 01:58:53 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id p12-v6so2950390pff.13 for ; Thu, 17 May 2018 18:58:53 -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=O4MXqhem6GJ54D6ulZiGg1UNTwfHZdaE88A4raed0YY=; b=ClugaEAg/icd1ip+uNpyuXgpEC8IMWVINU4beuRW/KgNCoKajDqc5WwHjfkpOX+l0q RtGhd10GBVBhCDPcVV5VYOQd+R2A5JKXfuejXHcHlvcC+qcP0k13iO4++8i1FXRXSKOh jdtHsxnr10u/vl8tPFfCJTrvKWKw2UEjmkce2SvT3+9SJGKjyc8Pq7lLtIYMGNNUirDB /ViEPCcVkdMLUzFYwX7oK8UMWMbR9t2h6FRO+enVrY9ClM94GL0Hm/D+sWGx9LYJyHt9 /gBtCP2yLg9qWaUyMRUeSL7TOtwtcZrqNCRdtclm+uUxguZX80bRuRruZxDB5JBb/Dyp YyUQ== 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=O4MXqhem6GJ54D6ulZiGg1UNTwfHZdaE88A4raed0YY=; b=kR/PM5Yq7WsbWveaH863OIule5XyQjZIlFwErkojA1LFafW1qIpTUVBDAIIfFBtNlC qQkNRJC9bsPC8GFcxdwLtNotzD4GwSLfkcASP05BjXWsN/hQxOLUF/U7UMqh2Yfazhr8 07L10lE7biY7k5NR70X79N9leW3ha3CjJm1m/DguxEsqiEYI7lo1+J5/hpQs2qz61H0T fOOQe3ecGInWSiSsz1uz5QmEKkEMdbg2+5crbfEzcjlehTSVY+5JlixoltVOhmzgcn1h 0yPmK+lWkXKVYZPv+Bx+i838VmJKR5Dr+lta1eofag1QPEoF35ZOgvBsQa8twf1bqkVy e/Xw== X-Gm-Message-State: ALKqPwfVV9FOfa/GQ/WFGe4O7QBkdjf5xNPY6Znx4L/aao7dzp+glnVG ovWSRNj0mJ5hKpteMoXuu5c9wA== X-Google-Smtp-Source: AB8JxZo//B+0w0FLrFKSd7URkmb1iyQcST24JzeHLPo03G/fZjzY92IMJ5TIwB/U16j1fpeyD+N6gg== X-Received: by 2002:a62:399c:: with SMTP id u28-v6mr7391245pfj.95.1526608732630; Thu, 17 May 2018 18:58:52 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:52 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:40 -0700 Message-Id: <1526608674-12702-28-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 27/41] erspan: add kernel datapath support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu pass check, check-kernel (4.16-rc4), check-system-userspace Signed-off-by: William Tu --- lib/dpif-netlink-rtnl.c | 20 +++--- lib/dpif-netlink.c | 3 + lib/odp-util.c | 150 +++++++++++++++++++++++++++++++++++++++++- tests/odp.at | 25 ++++++- tests/system-common-macros.at | 5 ++ tests/system-traffic.at | 147 +++++++++++++++++++++++++++++++++++++++++ tests/tunnel.at | 93 ++++++++++++++++++++++++++ 7 files changed, 431 insertions(+), 12 deletions(-) diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 63d3454..817e544 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -90,9 +90,6 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_VXLAN: return "vxlan"; case OVS_VPORT_TYPE_GRE: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L3) { return "gre"; } else if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L2) { @@ -102,6 +99,11 @@ vport_type_to_kind(enum ovs_vport_type type, } case OVS_VPORT_TYPE_GENEVE: return "geneve"; + case OVS_VPORT_TYPE_ERSPAN: + return "erspan"; + case OVS_VPORT_TYPE_IP6ERSPAN: + return "ip6erspan"; + case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -256,6 +258,9 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, err = dpif_netlink_rtnl_vxlan_verify(tnl_cfg, kind, reply); break; case OVS_VPORT_TYPE_GRE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: err = dpif_netlink_rtnl_gre_verify(tnl_cfg, kind, reply); break; case OVS_VPORT_TYPE_GENEVE: @@ -265,9 +270,6 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg, case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: @@ -442,14 +444,14 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_VXLAN: case OVS_VPORT_TYPE_GRE: case OVS_VPORT_TYPE_GENEVE: + case OVS_VPORT_TYPE_ERSPAN: + case OVS_VPORT_TYPE_IP6ERSPAN: + case OVS_VPORT_TYPE_IP6GRE: return dpif_netlink_rtnl_destroy(name); case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: case OVS_VPORT_TYPE_STT: - case OVS_VPORT_TYPE_ERSPAN: - case OVS_VPORT_TYPE_IP6ERSPAN: - case OVS_VPORT_TYPE_IP6GRE: case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: default: diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index a8b3ec6..f5ae21e 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -788,7 +788,10 @@ get_vport_type(const struct dpif_netlink_vport *vport) return "stt"; case OVS_VPORT_TYPE_ERSPAN: + return "erspan"; + case OVS_VPORT_TYPE_IP6ERSPAN: + return "ip6erspan"; case OVS_VPORT_TYPE_IP6GRE: return ""; diff --git a/lib/odp-util.c b/lib/odp-util.c index fc842ee..84eefb2 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2451,6 +2451,7 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + .next_max = OVS_VXLAN_EXT_MAX}, [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = 16 }, [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = 16 }, + [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = ATTR_LEN_VARIABLE }, }; const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = { @@ -2774,6 +2775,23 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask, case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: tun_metadata_from_geneve_nlattr(a, is_mask, tun); break; + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: { + int attr_len = nl_attr_get_size(a); + struct erspan_metadata opts; + + memcpy(&opts, nl_attr_get(a), attr_len); + + tun->erspan_ver = opts.version; + if (tun->erspan_ver == 1) { + tun->erspan_idx = ntohl(opts.u.index); + } else if (tun->erspan_ver == 2) { + tun->erspan_dir = opts.u.md2.dir; + tun->erspan_hwid = get_hwid(&opts.u.md2); + } else { + VLOG_WARN("%s invalid erspan version\n", __func__); + } + break; + } default: /* Allow this to show up as unexpected, if there are unknown @@ -2858,9 +2876,19 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, (tun_key->gbp_flags << 16) | ntohs(tun_key->gbp_id)); nl_msg_end_nested(a, vxlan_opts_ofs); } + tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a); + if (tun_key->erspan_ver) { + struct erspan_metadata opts; - if (!tnl_type || !strcmp(tnl_type, "geneve")) { - tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a); + opts.version = tun_key->erspan_ver; + if (opts.version == 1) { + opts.u.index = htonl(tun_key->erspan_idx); + } else { + opts.u.md2.dir = tun_key->erspan_dir; + set_hwid(&opts.u.md2, tun_key->erspan_hwid); + } + nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, + &opts, sizeof(opts)); } nl_msg_end_nested(a, tun_key_ofs); @@ -3318,6 +3346,46 @@ format_odp_tun_vxlan_opt(const struct nlattr *attr, ofpbuf_uninit(&ofp); } +static void +format_odp_tun_erspan_opt(const struct nlattr *attr, + const struct nlattr *mask_attr, struct ds *ds, + bool verbose) +{ + const struct erspan_metadata *opts, *mask; + uint8_t ver, ver_ma, dir, dir_ma, hwid, hwid_ma; + + opts = nl_attr_get(attr); + mask = mask_attr ? nl_attr_get(mask_attr) : NULL; + + ver = (uint8_t)opts->version; + if (mask) { + ver_ma = (uint8_t)mask->version; + } + + format_u8u(ds, "ver", ver, mask ? &ver_ma : NULL, verbose); + + if (opts->version == 1) { + if (mask) { + ds_put_format(ds, "idx=%#"PRIx32"/%#"PRIx32",", + ntohl(opts->u.index), + ntohl(mask->u.index)); + } else { + ds_put_format(ds, "idx=%#"PRIx32",", ntohl(opts->u.index)); + } + } else if (opts->version == 2) { + dir = opts->u.md2.dir; + hwid = opts->u.md2.hwid; + if (mask) { + dir_ma = mask->u.md2.dir; + hwid_ma = mask->u.md2.hwid; + } + + format_u8u(ds, "dir", dir, mask ? &dir_ma : NULL, verbose); + format_u8x(ds, "hwid", hwid, mask ? &hwid_ma : NULL, verbose); + } + ds_chomp(ds, ','); +} + #define MASK(PTR, FIELD) PTR ? &PTR->FIELD : NULL static void @@ -3566,6 +3634,9 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr, case OVS_TUNNEL_KEY_ATTR_PAD: break; case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: + ds_put_cstr(ds, "erspan("); + format_odp_tun_erspan_opt(a, ma, ds, verbose); + ds_put_cstr(ds, "),"); break; case __OVS_TUNNEL_KEY_ATTR_MAX: default: @@ -4751,6 +4822,70 @@ scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask) } static int +scan_erspan_metadata(const char *s, + struct erspan_metadata *key, + struct erspan_metadata *mask) +{ + const char *s_base = s; + uint32_t idx = 0, idx_mask = 0; + uint8_t ver = 0, dir = 0, hwid = 0; + uint8_t ver_mask = 0, dir_mask = 0, hwid_mask = 0; + + if (!strncmp(s, "ver=", 4)) { + s += 4; + s += scan_u8(s, &ver, mask ? &ver_mask : NULL); + } + + if (s[0] == ',') { + s++; + } + + if (ver == 1) { + if (!strncmp(s, "idx=", 4)) { + s += 4; + s += scan_u32(s, &idx, mask ? &idx_mask : NULL); + } + + if (!strncmp(s, ")", 1)) { + s += 1; + key->version = ver; + key->u.index = htonl(idx); + if (mask) { + mask->u.index = htonl(idx_mask); + } + } + return s - s_base; + + } else if (ver == 2) { + if (!strncmp(s, "dir=", 4)) { + s += 4; + s += scan_u8(s, &dir, mask ? &dir_mask : NULL); + } + if (s[0] == ',') { + s++; + } + if (!strncmp(s, "hwid=", 5)) { + s += 5; + s += scan_u8(s, &hwid, mask ? &hwid_mask : NULL); + } + + if (!strncmp(s, ")", 1)) { + s += 1; + key->version = ver; + key->u.md2.hwid = hwid; + key->u.md2.dir = dir; + if (mask) { + mask->u.md2.hwid = hwid_mask; + mask->u.md2.dir = dir_mask; + } + } + return s - s_base; + } + + return 0; +} + +static int scan_geneve(const char *s, struct geneve_scan *key, struct geneve_scan *mask) { const char *s_base = s; @@ -4885,6 +5020,15 @@ geneve_to_attr(struct ofpbuf *a, const void *data_) geneve->len); } +static void +erspan_to_attr(struct ofpbuf *a, const void *data_) +{ + const struct erspan_metadata *md = data_; + + nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, md, + sizeof *md); +} + #define SCAN_PUT_ATTR(BUF, ATTR, DATA, FUNC) \ { \ unsigned long call_fn = (unsigned long)FUNC; \ @@ -5253,6 +5397,8 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, SCAN_FIELD_NESTED("ttl=", uint8_t, u8, OVS_TUNNEL_KEY_ATTR_TTL); SCAN_FIELD_NESTED("tp_src=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_SRC); SCAN_FIELD_NESTED("tp_dst=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_DST); + SCAN_FIELD_NESTED_FUNC("erspan(", struct erspan_metadata, erspan_metadata, + erspan_to_attr); SCAN_FIELD_NESTED_FUNC("vxlan(gbp(", uint32_t, vxlan_gbp, vxlan_gbp_to_attr); SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve, geneve_to_attr); diff --git a/tests/odp.at b/tests/odp.at index cdf3d66..aa61e83 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -80,6 +80,16 @@ sed 's/^/skb_priority(0),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt | s echo echo '# Valid forms with IP later fragment.' sed 's/^/skb_priority(0),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt | sed -n 's/,frag=no),.*/,frag=later)/p' + + echo + echo '# Valid forms with tunnel and ERSPAN v1 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=1,idx=0x7),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v2 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=2,dir=0x1,hwid=0x7),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt ) > odp-in.txt AT_CAPTURE_FILE([odp-in.txt]) @@ -172,7 +182,18 @@ sed -n 's/,frag=no),/,frag=first),/p' odp-base.txt echo echo '# Valid forms with IP later fragment.' -sed -n 's/,frag=no),.*/,frag=later)/p' odp-base.txt) > odp.txt +sed -n 's/,frag=no),.*/,frag=later)/p' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v1 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=1/0,idx=0x7/0xf),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt + + echo + echo '# Valid forms with tunnel and ERSPAN v2 headers.' + sed + 's/^/skb_priority(0),tunnel(tun_id=0xfedcba9876543210,src=10.0.0.1,dst=10.0.0.2,ttl=128,erspan(ver=2,dir=0x1,hwid=0x7/0xf),flags(df|key)),skb_mark(0),recirc_id(0),dp_hash(0),/' odp-base.txt +) > odp.txt AT_CAPTURE_FILE([odp.txt]) AT_CHECK_UNQUOTED([ovstest test-odp parse-wc-keys < odp.txt], [0], [`cat odp.txt` ]) @@ -358,6 +379,8 @@ ct_clear trunc(100) clone(1) clone(clone(push_vlan(vid=12,pcp=0),2),1) +set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))) +set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=2,dir=1,hwid=0x1),flags(df|key))) ]) AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [`cat actions.txt` diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at index d2a9b59..64bf5ec 100644 --- a/tests/system-common-macros.at +++ b/tests/system-common-macros.at @@ -297,6 +297,11 @@ m4_define([OVS_CHECK_GRE], [AT_SKIP_IF([! ip link add foo type gretap help 2>&1 | grep gretap >/dev/null]) OVS_CHECK_FIREWALL()]) +# OVS_CHECK_ERSPAN() +m4_define([OVS_CHECK_ERSPAN], + [AT_SKIP_IF([! ip link add foo type erspan help 2>&1 | grep erspan >/dev/null]) + OVS_CHECK_FIREWALL()]) + # OVS_CHECK_GRE_L3() m4_define([OVS_CHECK_GRE_L3], [AT_SKIP_IF([! ip link add foo type gre help 2>&1 | grep "gre " >/dev/null]) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index 58db095..2c74161 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -339,6 +339,153 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([datapath - ping over erspan v1 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24") +AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL([erspan], [br0], [at_erspan0], [172.31.1.1], [10.1.1.100/24], [options:key=1 options:erspan_ver=1 options:erspan_idx=7]) +ADD_NATIVE_TUNNEL([erspan], [ns_erspan0], [at_ns0], [172.31.1.100], [10.1.1.1/24], [seq key 1 erspan_ver 1 erspan 7]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +dnl NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +NS_CHECK_EXEC([at_ns0], [ping -s 1200 -i 0.3 -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over erspan v2 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24") +AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL([erspan], [br0], [at_erspan0], [172.31.1.1], [10.1.1.100/24], [options:key=1 options:erspan_ver=2 options:erspan_dir=1 options:erspan_hwid=0x7]) +ADD_NATIVE_TUNNEL([erspan], [ns_erspan0], [at_ns0], [172.31.1.100], [10.1.1.1/24], [seq key 1 erspan_ver 2 erspan_dir egress erspan_hwid 7]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +dnl NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +NS_CHECK_EXEC([at_ns0], [ping -s 1200 -i 0.3 -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over ip6erspan v1 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad) +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL6([ip6erspan], [br0], [at_erspan0], [fc00:100::1], [10.1.1.100/24], + [options:key=123 options:erspan_ver=1 options:erspan_idx=0x7]) +ADD_NATIVE_TUNNEL6([ip6erspan], [ns_erspan0], [at_ns0], [fc00:100::100], + [10.1.1.1/24], [local fc00:100::1 seq key 123 erspan_ver 1 erspan 7]) + +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([datapath - ping over ip6erspan v2 tunnel]) +OVS_CHECK_GRE() +OVS_CHECK_ERSPAN() + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-underlay]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"]) + +ADD_NAMESPACES(at_ns0) + +dnl Set up underlay link from host into the namespace using veth pair. +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad) +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad]) +AT_CHECK([ip link set dev br-underlay up]) + +dnl Set up tunnel endpoints on OVS outside the namespace and with a native +dnl linux device inside the namespace. +ADD_OVS_TUNNEL6([ip6erspan], [br0], [at_erspan0], [fc00:100::1], [10.1.1.100/24], + [options:key=121 options:erspan_ver=2 options:erspan_dir=0 options:erspan_hwid=0x7]) +ADD_NATIVE_TUNNEL6([ip6erspan], [ns_erspan0], [at_ns0], [fc00:100::100], + [10.1.1.1/24], + [local fc00:100::1 seq key 121 erspan_ver 2 erspan_dir ingress erspan_hwid 0x7]) + +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100]) + +dnl First, check the underlay +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +dnl Okay, now check the overlay with different packet sizes +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([datapath - ping over geneve tunnel]) OVS_CHECK_GENEVE() diff --git a/tests/tunnel.at b/tests/tunnel.at index 620f4c8..315453d 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -478,6 +478,99 @@ AT_CHECK([tail -1 stdout], [0], OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([tunnel - ERSPAN v1/v2 metadata]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy \ + ofport_request=1 \ + -- add-port br0 p2 -- set Interface p2 type=dummy \ + ofport_request=2 \ + -- add-port br0 p3 -- set Interface p3 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=3 \ + options:key=1 options:erspan_ver=1 options:erspan_idx=7 \ + -- add-port br0 p4 -- set Interface p4 type=erspan \ + options:remote_ip=1.1.1.2 ofport_request=4 \ + options:key=2 options:erspan_ver=2 options:erspan_dir=1 options:erspan_hwid=7 \ + ]) +OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP + +AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl + br0 65534/100: (dummy-internal) + p1 1/3: (dummy) + p2 2/2: (dummy) + p3 3/1: (erspan: erspan_idx=0x7, erspan_ver=1, key=1, remote_ip=1.1.1.1) + p4 4/1: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=2, remote_ip=1.1.1.2) +]) + +AT_DATA([flows.txt], [dnl +in_port=1,actions=3 +in_port=2,actions=4 +in_port=3,tun_erspan_ver=1,tun_erspan_idx=0x7,actions=1 +in_port=4,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0xf/0x1,actions=2 +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +dnl test encap: in_port=1,actions=3 (erspan v1 port) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0x1,dst=1.1.1.1,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))),1 +]) + +dnl test encap: in_port=2,actions=4 (erspan v2 port) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0x2,dst=1.1.1.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key))),1 +]) + +dnl receive packet from ERSPAN port with v1 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no +Datapath actions: 3 +]) + +dnl receive packet from ERSPAN port with wrong v1 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0xabcd),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no +Datapath actions: drop +]) + +dnl receive packet from ERSPAN port with v2 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=1,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: 2 +]) + +dnl receive packet from ERSPAN port with wrong v2 metadata +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=0,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: drop +]) + +dnl test wildcard mask: recevie all v2 regardless of its metadata +AT_CHECK([ovs-ofctl del-flows br0 in_port=4,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0xf/0x1]) +AT_CHECK([ovs-ofctl add-flow br0 in_port=4,tun_erspan_ver=2,tun_erspan_dir=0/0,tun_erspan_hwid=0x0/0x0,actions=2]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=output:3 + in_port=2 actions=output:4 + erspan_ver=1,erspan_idx=0x7,in_port=3 actions=output:1 + erspan_ver=2,in_port=4 actions=output:2 +]) + +dnl this time it won't drop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no +Datapath actions: 2 +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel - Geneve metadata]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \ options:remote_ip=1.1.1.1 ofport_request=1 \ From patchwork Fri May 18 01:57: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: 915964 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="WPiP/Xj5"; 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 40nBWs4Zlmz9s19 for ; Fri, 18 May 2018 12:12:25 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E90821156; Fri, 18 May 2018 01:59: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 C2F881105 for ; Fri, 18 May 2018 01:58:54 +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 817666FB for ; Fri, 18 May 2018 01:58:54 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id c22-v6so1940877pgn.11 for ; Thu, 17 May 2018 18:58:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6gPwmbsxlJ++SQ1QOTKcmra14PfdL0ZHlWMKQ4vPL58=; b=WPiP/Xj5KZC+F8VTAxzLvmZHTNsWXLgjl2lC5kYCqcSis7+HKbj5PDCsPy3bkipZ4B tdgtwyTLlwt8LVKuykD855iO9wYxoBmnobfhieDbZcjOKf6Th8hfa/tM51668mDJqdcY fO/rXGu3ZkYZxSZda6qZIEmThvFN+XTo73+sF57Vk6cwAAskJAwP2aUxY8z61gOyGsQg YywbsZAFBXplxTIuleuC6aJQfYL+x1+/+t6qXURbMJjeFqF1FB89I0KDoDraFtQZBZuK 4AsHm9PyDkK+iYZuBnE6lRbPOVXvAKHCYchUBQRvFCNmYVe0thvzeYfWGs6dYOpmAG+Y BXZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6gPwmbsxlJ++SQ1QOTKcmra14PfdL0ZHlWMKQ4vPL58=; b=C2//bEiGnLESHoWoJg9XUm9i/1GU6vfGAQLtxxBYIVbL/4a2rUpxX+Hgj4r+UMOXvh r04x0gzb21IKmPHy/np/T7SKpCmbLdXC0ok+GBwfUZHk0xMgDqrl6ZNG1PxdDo/dCNMM 3jnBhT4wlO70shCFXr/Df1F5N+ixB9fn9rTo4ZOyBG+GrzOSmYRSizPRaJbJkzD8hKGa Y2TNhhNpNebroccSaZhGXTEhoxso4hg5gA+Q+O/+fGJ/8h6R87NM7Tl0QVynAWzuX68s ngDlFajnos+iFA0JBuXe6AmrX2bbiL7HC4h51o6muRc+gKvPJC7eRqPshQNPxsUQtHrK X4AQ== X-Gm-Message-State: ALKqPwdSygIays5mKFPtSki5/qAAP4tjjXA3siTQ6roVg/cpGiSpOp0W ZwytrwR1P28DLPbkC16pOSzSUg== X-Google-Smtp-Source: AB8JxZrnJ4NlhiiSdJTAxQPCnr9PtaAnlInqHr0de8/H6HAr+HNk1Wu1n5jHJyUjewnYvQKewJaFcw== X-Received: by 2002:a65:4b8d:: with SMTP id t13-v6mr5911765pgq.53.1526608733821; Thu, 17 May 2018 18:58:53 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:53 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:41 -0700 Message-Id: <1526608674-12702-29-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 28/41] openvswitch: fix vport packet length check. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 46e371f0e78a82186a83cbcb4f4b8850417c7dd5 Author: William Tu Date: Wed Mar 7 15:38:48 2018 -0800 openvswitch: fix vport packet length check. When sending a packet to a tunnel device, the dev's hard_header_len could be larger than the skb->len in function packet_length(). In the case of ip6gretap/erspan, hard_header_len = LL_MAX_HEADER + t_hlen, which is around 180, and an ARP packet sent to this tunnel has skb->len = 42. This causes the 'unsign int length' to become super large because it is negative value, causing the later ovs_vport_send to drop it due to over-mtu size. The patch fixes it by setting it to 0. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/vport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/datapath/vport.c b/datapath/vport.c index f4131be..184c859 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -520,10 +520,10 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb, return 0; } -static unsigned int packet_length(const struct sk_buff *skb, - struct net_device *dev) +static int packet_length(const struct sk_buff *skb, + struct net_device *dev) { - unsigned int length = skb->len - dev->hard_header_len; + int length = skb->len - dev->hard_header_len; if (!skb_vlan_tag_present(skb) && eth_type_vlan(skb->protocol)) @@ -534,7 +534,7 @@ static unsigned int packet_length(const struct sk_buff *skb, * account for 802.1ad. e.g. is_skb_forwardable(). */ - return length; + return length > 0 ? length: 0; } void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto) From patchwork Fri May 18 01:57: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: 915967 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="iYyCj391"; 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 40nBY40nb1z9s19 for ; Fri, 18 May 2018 12:13:28 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 35692111C; Fri, 18 May 2018 01:59: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 5CA461096 for ; Fri, 18 May 2018 01:58:56 +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 6D1416F3 for ; Fri, 18 May 2018 01:58:55 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id n9-v6so2606697pgq.5 for ; Thu, 17 May 2018 18:58:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EJrXAlS7rn25ITrnXEOaZl5ND1LXojmiV0efrc4UHrE=; b=iYyCj391wK+P7g+xfIYWyNcO6zaNua9mVa+JmOj3UeWb025EBNvxFqXfVJoogV9Ijv UhA3LBc+8aEk+Bhx7TNtlqmWQXYAsiBFsh/RRLAgn/DVOIJ4UZJva65ik/AVQ9NAFPit aVUnvxwyEvvPGbZZqcpgaVI62RgCqNzkeyKOPeB4kJqY57IyJ11Wc43Oa4qg9oe5D2Ta gWFE2HsRryE17F8FoLHXWOFFgaDQdNn0myLubVgnikWfm2j1gQMXu5XhvjtCnqcTr+MB 00JUDoWNe+l5sJJCJEgG28I3E7jQ8cCvGkrm8QIpy+GaTyp+qUkxtouzPY6gxSizoIrE OTGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EJrXAlS7rn25ITrnXEOaZl5ND1LXojmiV0efrc4UHrE=; b=CYhTY7eozY9SOpJ/zo2DDLG03P+SVZXlBCePbxIqjxeBA4cMiz6SpA/ziKU+hSaVhE Hl+prv5ZG6Pf2Ldm/T34MDF421us12Ji1LmofjEndGzW8Kbate2exg6qCYRjJZARMsx/ K+TPhOpq2vUyVEvQn9gcCKi5la06GKQqqQjio2/s22wLtckNFTg5Gnc+SpmMmX1wwDG9 O8Oue2P8hdagiFxnWFFg2i8xtD8ZXyfMTEHI6Zm0WQU1wm04MNggQL/KB5MypGe06Hsz koa9O0CkSkquiwzUiG+Ng5eezF2GZSj8aUQs0lKd1byDba9HUqqB8ytS4RhF1RddUvfk WtVQ== X-Gm-Message-State: ALKqPwdGE+BfsRn2e28O64VI8MLeMVK3GKU+prnKvwdo6o1tyi72HOyH 6Mtb5rl3HLu0F2dY9DTAmMi49Q== X-Google-Smtp-Source: AB8JxZpkvUu9Oxfi/EJf7APkbxp3pxBcAIsPqD5xX4hSxeUd8iS42PZCiVMN0PqN7AFOAL8uzhpAHg== X-Received: by 2002:a63:18c:: with SMTP id 134-v6mr5812394pgb.138.1526608734766; Thu, 17 May 2018 18:58:54 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:54 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:42 -0700 Message-Id: <1526608674-12702-30-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 29/41] erspan: auto detect truncated packets. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 1baf5ebf8954d9bff8fa4e7dd6c416a0cebdb9e2 Author: William Tu Date: Fri Apr 27 14:16:32 2018 -0700 erspan: auto detect truncated packets. Currently the truncated bit is set only when the mirrored packet is larger than mtu. For certain cases, the packet might already been truncated before sending to the erspan tunnel. In this case, the patch detect whether the IP header's total length is larger than the actual skb->len. If true, this indicated that the mirrored packet is truncated and set the erspan truncate bit. I tested the patch using bpf_skb_change_tail helper function to shrink the packet size and send to erspan tunnel. Reported-by: Xiaoyan Jin Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 6 ++++++ datapath/linux/compat/ip_gre.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 085d04f..e0246d1 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1069,6 +1069,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, int err = -EINVAL; __be32 tun_id; __u32 mtu; + int nhoff; /* OVS doesn't support native mode ip6 tunnel traffic so @@ -1087,6 +1088,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, truncate = true; } + nhoff = skb_network_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IP) && + (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) + truncate = true; + t->parms.o_flags &= ~TUNNEL_KEY; IPCB(skb)->flags = 0; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 958965f..6b40013 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -631,6 +631,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, int tunnel_hlen; int version; __be16 df; + int nhoff; tun_info = skb_tunnel_info(skb); if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || @@ -658,6 +659,11 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, truncate = true; } + nhoff = skb_network_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IP) && + (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) + truncate = true; + if (version == 1) { erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), ntohl(md->u.index), truncate, true); From patchwork Fri May 18 01:57: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: 915968 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="hZpw50jy"; 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 40nBYb52qRz9s19 for ; Fri, 18 May 2018 12:13:55 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D31E0111D; Fri, 18 May 2018 01:59: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 EBAEAF5D for ; Fri, 18 May 2018 01:58:56 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f50.google.com (mail-pg0-f50.google.com [74.125.83.50]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 88BA7196 for ; Fri, 18 May 2018 01:58:56 +0000 (UTC) Received: by mail-pg0-f50.google.com with SMTP id v7-v6so2630733pgs.0 for ; Thu, 17 May 2018 18:58: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=t0WAnqh3HKrbZ7DWSPJki/Yw/IFUv3eRO2sVkcfRdrU=; b=hZpw50jyB9GKveqR7pNd694t84a1EeAgb/FZXAme67lqjBSlnIdBroCR7eFQgCQZ9Q ls6ENOCBLH/McKCd0AmgnCJ6ZhjBiuhYQ7dyvyRq8A6AUnDdO1yb9wxuPq/7TeUo3pjA Q006HC0Gu5Z27wwbsGPWk0BaWKI281D2IOKE6V+kcClD7s5kAIkW16SpLbhIOK/vLcMn rtoEQ43ho5WpgTebJCTMn9yc7ONcvw34bDUeRXiZM0IdtqeQDukrYLA2xLDktY+DhKQ1 V7OghEYfZbp0YSyY2+XmbK67NAMxvWlmYUJWatnIS1Ue9vbaeJdoyFF84z5b33pMfSxH vYuA== 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=t0WAnqh3HKrbZ7DWSPJki/Yw/IFUv3eRO2sVkcfRdrU=; b=i5IbvhA3O/mFP3yVkjp0KauAtIFBEuU/BiP9fYJpigyFT/uJrnwPpHdPBXvge2l6Jy 0xo4WLYJENFz52w+4U1xOVJldPiB4ZyifF9sBYAJENPNdaanWo7iOlhrcJr0zHYuoxJf Pn8rq+lDZja44jWwJLiiWIrQ97SvBIkHR6AngSETCr8M4xqI7iIBs99WPmDtlZHOjKLU Nm/YrYdzsVqlkyVo4i+hfomajzXmL115HnXmdUW/BIhz1r8bOvV7vkCxJnTC7g3SpAJk bJBCfM9tba4YsIiWhZOwWmaHj1FmgK1jtEJEmmEyTa7CYZ0cIKT22SrUUgMhUhDys2lg oHtQ== X-Gm-Message-State: ALKqPwcNogSLmPY9bdkv6ZK8QvmM6dI/5L2vWE62YHdcNClFpMRhGRzy LDbehKbylsKhGPkTlpqgffwNzg== X-Google-Smtp-Source: AB8JxZpcylq0uU2GvaJ8S4DzF0WkduwrEzS6LK8wPpObED+ygQaikw2pH8hyNdYn2F8XBVjAMAIQgg== X-Received: by 2002:a65:4a87:: with SMTP id b7-v6mr5869560pgu.271.1526608735870; Thu, 17 May 2018 18:58:55 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:55 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:43 -0700 Message-Id: <1526608674-12702-31-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 30/41] ip6gre: Add ip6gre vport type X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Add handlers for OVS_VPORT_TYPE_IP6GRE Cc: Ben Pfaff Signed-off-by: Greg Rose --- V2 - Folded in additional change from Ben Pfaff as per his suggestion. --- lib/dpif-netlink-rtnl.c | 4 +++- lib/dpif-netlink.c | 7 +++++-- lib/netdev-native-tnl.c | 8 ++++++-- lib/netdev-vport.c | 4 ++++ lib/odp-util.c | 9 +++++++-- lib/tnl-ports.c | 2 +- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 817e544..bec3fce 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -104,6 +104,7 @@ vport_type_to_kind(enum ovs_vport_type type, case OVS_VPORT_TYPE_IP6ERSPAN: return "ip6erspan"; case OVS_VPORT_TYPE_IP6GRE: + return "ip6gre"; case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -349,7 +350,8 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, nl_msg_end_nested(&request, linkinfo_off); err = nl_transact(NETLINK_ROUTE, &request, NULL); - if (!err && type == OVS_VPORT_TYPE_GRE) { + if (!err && (type == OVS_VPORT_TYPE_GRE || + type == OVS_VPORT_TYPE_IP6GRE)) { /* Work around a bug in kernel GRE driver, which ignores IFLA_MTU in * RTM_NEWLINK, by setting the MTU again. See * https://bugzilla.redhat.com/show_bug.cgi?id=1488484. */ diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index f5ae21e..607b497 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -791,9 +791,10 @@ get_vport_type(const struct dpif_netlink_vport *vport) return "erspan"; case OVS_VPORT_TYPE_IP6ERSPAN: - return "ip6erspan"; + return "ip6erspan"; + case OVS_VPORT_TYPE_IP6GRE: - return ""; + return "ip6gre"; case OVS_VPORT_TYPE_UNSPEC: case __OVS_VPORT_TYPE_MAX: @@ -826,6 +827,8 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_ERSPAN; } else if (!strcmp(type, "ip6erspan")) { return OVS_VPORT_TYPE_IP6ERSPAN; + } else if (!strcmp(type, "ip6gre")) { + return OVS_VPORT_TYPE_IP6GRE; } else { return OVS_VPORT_TYPE_UNSPEC; } diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 66eb18e..c70811e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -513,7 +513,11 @@ netdev_gre_build_header(const struct netdev *netdev, hlen = (uint8_t *) options - (uint8_t *) greh; data->header_len += hlen; - data->tnl_type = OVS_VPORT_TYPE_GRE; + if (!params->is_ipv6) { + data->tnl_type = OVS_VPORT_TYPE_GRE; + } else { + data->tnl_type = OVS_VPORT_TYPE_IP6GRE; + } return 0; } @@ -552,7 +556,7 @@ netdev_erspan_pop_header(struct dp_packet *packet) } ersh = ERSPAN_HDR(greh); - tnl->tun_id = be32_to_be64(be16_to_be32(htons(get_sid(ersh)))); + tnl->tun_id = be16_to_be64(htons(get_sid(ersh))); tnl->erspan_ver = ersh->ver; if (ersh->ver == 1) { diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 4311d2b..805f130 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -1042,6 +1042,10 @@ netdev_vport_tunnel_register(void) netdev_erspan_push_header, netdev_erspan_pop_header, NULL), + TUNNEL_CLASS("ip6gre", "ip6gre_sys", netdev_gre_build_header, + netdev_gre_push_header, + netdev_gre_pop_header, + NULL), }; static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; diff --git a/lib/odp-util.c b/lib/odp-util.c index 84eefb2..2109fac 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -690,7 +690,8 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) } ds_put_char(ds, ')'); - } else if (data->tnl_type == OVS_VPORT_TYPE_GRE) { + } else if (data->tnl_type == OVS_VPORT_TYPE_GRE || + data->tnl_type == OVS_VPORT_TYPE_IP6GRE) { const struct gre_base_hdr *greh; ovs_16aligned_be32 *options; @@ -1559,7 +1560,11 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data) } else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")", &gre_flags, &gre_proto)){ - tnl_type = OVS_VPORT_TYPE_GRE; + if (eth->eth_type == htons(ETH_TYPE_IP)) { + tnl_type = OVS_VPORT_TYPE_GRE; + } else { + tnl_type = OVS_VPORT_TYPE_IP6GRE; + } greh->flags = htons(gre_flags); greh->protocol = htons(gre_proto); ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1); diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index 5753179..1735304 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -172,7 +172,7 @@ tnl_type_to_nw_proto(const char type[]) return IPPROTO_TCP; } if (!strcmp(type, "gre") || !strcmp(type, "erspan") || - !strcmp(type, "ip6erspan")) { + !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) { return IPPROTO_GRE; } if (!strcmp(type, "vxlan")) { From patchwork Fri May 18 01:57: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: 915970 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="ndqEMt7S"; 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 40nBZp2STNz9s28 for ; Fri, 18 May 2018 12:14:58 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C1F94114A; Fri, 18 May 2018 01:59:13 +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 C241D1116 for ; Fri, 18 May 2018 01:58:57 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f49.google.com (mail-pg0-f49.google.com [74.125.83.49]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 80CCC6DB for ; Fri, 18 May 2018 01:58:57 +0000 (UTC) Received: by mail-pg0-f49.google.com with SMTP id 11-v6so974518pge.2 for ; Thu, 17 May 2018 18:58:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+n4LMYN2GxYv374ikJpaus4ggXX7aD+LICmF/ZSvxJg=; b=ndqEMt7Sd5do+mK0EMTBILHv2RjT+EYZqXEuKuCmnUBqsUGbaiCr1TZQj2YHp7hqOC Lia7bs6JpZQpzlTIAPpJrbQDYU08MI8HOLMwVTO9vObcTv86vLmpnAfAkxWJpweDJqg3 hB1AmZtfgcbCJWECxmYWx3vat6uZHtQwM4MgSJuzbP3wXK13vr2NtR5WaymqMOoawS3N fuK2pWOAS8hHcCzLY2/c7Z0ETDPIaASif7T5pjJT/+vV/H+QBbQpraLHIILw1q36ftyt woqrMHe2hDhdiQTd4xg4ndf8GWXhVWWytoVQ8Bqm1RF5PDp8qRG9/qNngqRYFv7GviuG 56Gw== 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=+n4LMYN2GxYv374ikJpaus4ggXX7aD+LICmF/ZSvxJg=; b=KxRcNup0JKT0dlLbFzfnbdDGDrGTx3+JfonJ9RIXgSCGq0f4hi8tHGxgh88X3Mt1k7 3UTwP9VbxoRxpZBN4vIf2rAFvdS4URd8VfejPEa7MbB/vAvh94z87Q7gZHGr0lSAwGK2 Z6x6raDyWMIykyiA71DorW7YTd9VbSQwkYxprUC6lEj30MqwMcfLcwq5ERYRsM22lcz7 HmzRimOwuyCf8gbEJ7uUe1KukXkDsyeqjuoW1oLmUDfzTAuFFrOC++agbJb9Bxtzff31 ppnrkJjHrhmNSlb0mW9p9c9F3BgIKdLWUhMRHFYnCkS6pLqQY7Vt7JasX5kAZvF5/Zi1 8MCw== X-Gm-Message-State: ALKqPwdT0U+aXKExGFJgCc4/sP7jynPmolz0y/Zp0Hh+bu51Lkvb5T8g agQtFKRh1Kf27mBQds1iqoDisw== X-Google-Smtp-Source: AB8JxZr6tBu5Kwogdw/spbrWn5SOewQANcNjgc5y8hIHnzU2wrM9JLtXhYKzXquZodFkE2POnY8+0Q== X-Received: by 2002:a63:a06a:: with SMTP id u42-v6mr5626362pgn.389.1526608736766; Thu, 17 May 2018 18:58:56 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:56 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:44 -0700 Message-Id: <1526608674-12702-32-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 31/41] lib/dpif-netlink: Fix miscompare of gre ports X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org In netdev_to_ovs_vport_type() it checks for netdev types matching "gre" with a strstr(). This makes it match ip6gre as well and return OVS_VPORT_TYPE_GRE, which is clearly wrong. Move the usage of strstr() *after* all the exact matches with strcmp() to avoid the problem permanently because when I added the ip6gre type I ran into a very difficult to detect bug. Cc: Ben Pfaff Signed-off-by: Greg Rose --- V2 - Removed strstr for gre completely as per Ben's feedback. --- lib/dpif-netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 607b497..20e1921 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -817,8 +817,6 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_STT; } else if (!strcmp(type, "geneve")) { return OVS_VPORT_TYPE_GENEVE; - } else if (strstr(type, "gre")) { - return OVS_VPORT_TYPE_GRE; } else if (!strcmp(type, "vxlan")) { return OVS_VPORT_TYPE_VXLAN; } else if (!strcmp(type, "lisp")) { @@ -829,6 +827,8 @@ netdev_to_ovs_vport_type(const char *type) return OVS_VPORT_TYPE_IP6ERSPAN; } else if (!strcmp(type, "ip6gre")) { return OVS_VPORT_TYPE_IP6GRE; + } else if (strcmp(type, "gre")) { + return OVS_VPORT_TYPE_GRE; } else { return OVS_VPORT_TYPE_UNSPEC; } From patchwork Fri May 18 01:57: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: 915972 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="r51H8gVG"; 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 40nBbx6pmBz9s28 for ; Fri, 18 May 2018 12:15:57 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id F21461178; Fri, 18 May 2018 01:59:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 708CF113B for ; Fri, 18 May 2018 01:59:00 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f48.google.com (mail-pg0-f48.google.com [74.125.83.48]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 1B7006DB for ; Fri, 18 May 2018 01:58:59 +0000 (UTC) Received: by mail-pg0-f48.google.com with SMTP id w4-v6so2605617pgq.8 for ; Thu, 17 May 2018 18:58: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=FE/2B0+qg1oPRTAI0pCC1eISnpYSh3OGOiK2h0k1cpY=; b=r51H8gVGGVeW1lc0wmGV4Jh2TK62bFzbrjEXmitPS6sUaERUZtwuXoAzdEFvzUCPI3 +r6uf3b/TjdHq0JZvB5iqGFmrqbVKQHD5kgPcum5+An1iURPwr6HPSal0WPyaLXPqKC1 qzZIqPirXlA1YT94cBXNCXMQKYOGSOKMjUC2egURnDgZW3fnQmgGi8RDqw4412LE3z4F pap5CivQvAZKVL94dfIcE2yNr58ocF5AZzs2zQXGxoaSCVYWLzSl2bSPNriSEcaQ7tWb GNXUqxuLqWnDIOPEif3xV2aDIvIdBDv032ZKENneagf4+iAkLKxZfXTHwOa2GWGLnSEy 0QZA== 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=FE/2B0+qg1oPRTAI0pCC1eISnpYSh3OGOiK2h0k1cpY=; b=Fzb94jsRdJrGNZ2sQ+hB5PTXxH/MiSGVOQkxjm02SE0qz/bjggEHagFH9ew8uGzZTF FCaX4A63ufVgwUT+5h7ZZzGinFSP9qyF4Ws75jtYHrjLLNR3+NYsBg4YNvv+6E6NyVz6 cjZxNv/Z9zVzU4c/G84kyZSmXnZzp+ef/wA+f5O0wgcXsvLSoQvwOV4ylj9/VbaynVba dNFEgcY4lKK+mws262p+qoEJrHJv/dccUWZzxnybkl38kXhd3XgfSWECqhc9EUfhUqGj FZlY8kFLk5Kdn349o6JQSvjLyAGkZZGfk72X2olRwaVEn4TXJ4zDyqzeEpXx8hkaXa33 o2+w== X-Gm-Message-State: ALKqPwdbD7TjbrpLt4idgO0ReSq6RSGixN1wDhu677490/Vcfnyysy/4 KRsZtaVlJSm6k5X2BAE92Druhw== X-Google-Smtp-Source: AB8JxZpWy2L+9stNNzMTkQmHnKcZHewjt2W98drfpxRr/1Nx8UUoUP6n597pzus6INphstKBTzx0dQ== X-Received: by 2002:a63:9711:: with SMTP id n17-v6mr5960585pge.431.1526608738039; Thu, 17 May 2018 18:58:58 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:57 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:45 -0700 Message-Id: <1526608674-12702-33-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 32/41] erspan: Add flow-based erspan options X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The patch add supports for flow-based erspan options. The erspan_ver, erspan_idx, erspan_dir, and erspan_hwid can be set as "flow" so that its value is set by the openflow rule, instead of statically configured at port creation time. Signed-off-by: William Tu --- V2 - A portion of this patch from lib/match.c was folded in a prior commit "userspace: add erspan tunnel support" as per Ben's review comments. --- lib/netdev-native-tnl.c | 38 +++++++++++++-- lib/netdev-vport.c | 120 +++++++++++++++++++++++++++++++++-------------- lib/netdev.h | 5 ++ ofproto/tunnel.c | 11 +++-- tests/tunnel-push-pop.at | 35 +++++++++++++- tests/tunnel.at | 68 +++++++++++++++++++++++---- 6 files changed, 223 insertions(+), 54 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index c70811e..c97491e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -628,6 +628,7 @@ netdev_erspan_build_header(const struct netdev *netdev, struct erspan_base_hdr *ersh; unsigned int hlen; uint32_t tun_id; + int erspan_ver; uint16_t sid; /* XXX: RCUfy tnl_cfg. */ @@ -645,7 +646,15 @@ netdev_erspan_build_header(const struct netdev *netdev, sid = (uint16_t) tun_id; } - if (tnl_cfg->erspan_ver == 1) { + if (tnl_cfg->erspan_ver_flow) { + erspan_ver = params->flow->tunnel.erspan_ver; + } else { + erspan_ver = tnl_cfg->erspan_ver; + } + + if (erspan_ver == 1) { + ovs_be32 *index; + greh->protocol = htons(ETH_TYPE_ERSPAN1); greh->flags = htons(GRE_SEQ); ersh->ver = 1; @@ -654,19 +663,38 @@ netdev_erspan_build_header(const struct netdev *netdev, put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1), htonl(tnl_cfg->erspan_idx)); + index = (ovs_be32 *)(ersh + 1); + + if (tnl_cfg->erspan_idx_flow) { + *index = htonl(params->flow->tunnel.erspan_idx); + } else { + *index = htonl(tnl_cfg->erspan_idx); + } + hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE; - } else if (tnl_cfg->erspan_ver == 2) { + } else if (erspan_ver == 2) { + struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); + greh->protocol = htons(ETH_TYPE_ERSPAN2); greh->flags = htons(GRE_SEQ); ersh->ver = 2; set_sid(ersh, sid); - struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); md2->sgt = 0; /* security group tag */ md2->gra = 0; put_16aligned_be32(&md2->timestamp, 0); - set_hwid(md2, tnl_cfg->erspan_hwid); - md2->dir = tnl_cfg->erspan_dir; + + if (tnl_cfg->erspan_hwid_flow) { + set_hwid(md2, params->flow->tunnel.erspan_hwid); + } else { + set_hwid(md2, tnl_cfg->erspan_hwid); + } + + if (tnl_cfg->erspan_dir_flow) { + md2->dir = params->flow->tunnel.erspan_dir; + } else { + md2->dir = tnl_cfg->erspan_dir; + } hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE; } else { diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 805f130..1dae7e0 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -545,36 +545,63 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp) tnl_cfg.egress_pkt_mark = strtoul(node->value, NULL, 10); tnl_cfg.set_egress_pkt_mark = true; } else if (!strcmp(node->key, "erspan_idx")) { - tnl_cfg.erspan_idx = strtol(node->value, NULL, 16); - if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) { - ds_put_format(&errors, "%s: invalid erspan index: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_idx_flow = true; + } else { + tnl_cfg.erspan_idx_flow = false; + tnl_cfg.erspan_idx = strtol(node->value, NULL, 16); + + if (tnl_cfg.erspan_idx & ~ERSPAN_IDX_MASK) { + ds_put_format(&errors, "%s: invalid erspan index: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_ver")) { - tnl_cfg.erspan_ver = atoi(node->value); - if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) { - ds_put_format(&errors, "%s: invalid erspan version: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_ver_flow = true; + tnl_cfg.erspan_idx_flow = true; + tnl_cfg.erspan_dir_flow = true; + tnl_cfg.erspan_hwid_flow = true; + } else { + tnl_cfg.erspan_ver_flow = false; + tnl_cfg.erspan_ver = atoi(node->value); + + if (tnl_cfg.erspan_ver != 1 && tnl_cfg.erspan_ver != 2) { + ds_put_format(&errors, "%s: invalid erspan version: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_dir")) { - tnl_cfg.erspan_dir = atoi(node->value); - if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) { - ds_put_format(&errors, "%s: invalid erspan direction: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_dir_flow = true; + } else { + tnl_cfg.erspan_dir_flow = false; + tnl_cfg.erspan_dir = atoi(node->value); + + if (tnl_cfg.erspan_dir != 0 && tnl_cfg.erspan_dir != 1) { + ds_put_format(&errors, "%s: invalid erspan direction: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else if (!strcmp(node->key, "erspan_hwid")) { - tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16); - if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) { - ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n", - name, node->value); - err = EINVAL; - goto out; + if (!strcmp(node->value, "flow")) { + tnl_cfg.erspan_hwid_flow = true; + } else { + tnl_cfg.erspan_hwid_flow = false; + tnl_cfg.erspan_hwid = strtol(node->value, NULL, 16); + + if (tnl_cfg.erspan_hwid & ~(ERSPAN_HWID_MASK >> 4)) { + ds_put_format(&errors, "%s: invalid erspan hardware ID: %s\n", + name, node->value); + err = EINVAL; + goto out; + } } } else { ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name, @@ -767,17 +794,40 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) "%"PRIu32, tnl_cfg.egress_pkt_mark); } - if (tnl_cfg.erspan_idx) { - smap_add_format(args, "erspan_idx", "0x%x", tnl_cfg.erspan_idx); - } - if (tnl_cfg.erspan_ver) { - smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver); - } - if (tnl_cfg.erspan_dir) { - smap_add_format(args, "erspan_dir", "%d", tnl_cfg.erspan_dir); - } - if (tnl_cfg.erspan_hwid) { - smap_add_format(args, "erspan_hwid", "0x%x", tnl_cfg.erspan_hwid); + if (!strcmp("erspan", type) || !strcmp("ip6erspan", type)) { + if (tnl_cfg.erspan_ver_flow) { + /* since version number is not determined, + * assume print all other as flow + */ + smap_add(args, "erspan_ver", "flow"); + smap_add(args, "erspan_idx", "flow"); + smap_add(args, "erspan_dir", "flow"); + smap_add(args, "erspan_hwid", "flow"); + } else { + smap_add_format(args, "erspan_ver", "%d", tnl_cfg.erspan_ver); + + if (tnl_cfg.erspan_ver == 1) { + if (tnl_cfg.erspan_idx_flow) { + smap_add(args, "erspan_idx", "flow"); + } else { + smap_add_format(args, "erspan_idx", "0x%x", + tnl_cfg.erspan_idx); + } + } else if (tnl_cfg.erspan_ver == 2) { + if (tnl_cfg.erspan_dir_flow) { + smap_add(args, "erspan_dir", "flow"); + } else { + smap_add_format(args, "erspan_dir", "%d", + tnl_cfg.erspan_dir); + } + if (tnl_cfg.erspan_hwid_flow) { + smap_add(args, "erspan_hwid", "flow"); + } else { + smap_add_format(args, "erspan_hwid", "0x%x", + tnl_cfg.erspan_hwid); + } + } + } } return 0; diff --git a/lib/netdev.h b/lib/netdev.h index 0c74dfe..71ffdab 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -134,6 +134,11 @@ struct netdev_tunnel_config { uint8_t erspan_ver; uint8_t erspan_dir; uint8_t erspan_hwid; + + bool erspan_ver_flow; + bool erspan_idx_flow; + bool erspan_dir_flow; + bool erspan_hwid_flow; }; void netdev_run(void); diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 2fd6ffb..03f0ab7 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -474,16 +474,19 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow, wc->masks.pkt_mark = UINT32_MAX; } - if (cfg->erspan_ver) { + if (!cfg->erspan_ver_flow) { flow->tunnel.erspan_ver = cfg->erspan_ver; } - if (cfg->erspan_idx) { + + if (!cfg->erspan_idx_flow) { flow->tunnel.erspan_idx = cfg->erspan_idx; } - if (cfg->erspan_dir) { + + if (!cfg->erspan_dir_flow) { flow->tunnel.erspan_dir = cfg->erspan_dir; } - if (cfg->erspan_hwid) { + + if (!cfg->erspan_hwid_flow) { flow->tunnel.erspan_hwid = cfg->erspan_hwid; } diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 1a181f3..8f2529c 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -9,6 +9,12 @@ AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=erspan \ -- add-port int-br t2 -- set Interface t2 type=erspan \ options:remote_ip=1.1.2.92 options:key=567 options:erspan_ver=2 \ options:erspan_dir=1 options:erspan_hwid=0x7 ofport_request=3\ + -- add-port int-br t3 -- set Interface t3 type=erspan \ + options:remote_ip=flow options:erspan_ver=2 options:key=456 \ + options:erspan_hwid=flow options:erspan_dir=flow ofport_request=4\ + -- add-port int-br t4 -- set Interface t4 type=erspan \ + options:remote_ip=flow options:erspan_ver=2 options:key=56 \ + options:erspan_ver=flow ofport_request=5\ ], [0]) AT_CHECK([ovs-appctl dpif/show], [0], [dnl @@ -20,6 +26,8 @@ dummy@ovs-dummy: hit:0 missed:0 int-br 65534/2: (dummy-internal) t1 2/3: (erspan: erspan_idx=0x3, erspan_ver=1, key=123, remote_ip=1.1.2.92) t2 3/3: (erspan: erspan_dir=1, erspan_hwid=0x7, erspan_ver=2, key=567, remote_ip=1.1.2.92) + t3 4/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=456, remote_ip=flow) + t4 5/3: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=56, remote_ip=flow) ]) dnl First setup dummy interface IP address, then add the route @@ -66,7 +74,7 @@ AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl Listening ports: -erspan_sys (3) ref_cnt=2 +erspan_sys (3) ref_cnt=4 ]) dnl Check ERSPAN v1 tunnel push @@ -85,6 +93,31 @@ AT_CHECK([tail -1 stdout], [0], [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x237,dir=1,hwid=0x7)),out_port(100)) ]) +dnl Check ERSPAN v2 flow-based tunnel push +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,4"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x1c8,dir=1,hwid=0x1)),out_port(100)) +]) + +dnl Check ERSPAN v2 flow-based tunnel push, erspan_ver=flow +dnl Dynamically set erspan v2 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x1->tun_erspan_hwid,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_push(tnl_port(3),header(size=54,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=2,sid=0x38,dir=1,hwid=0x1)),out_port(100)) +]) + +dnl Dynamically set erspan v1 +AT_CHECK([ovs-ofctl mod-flows int-br "action=set_field:1.1.2.94->tun_dst,set_field:1->tun_erspan_ver,set_field:1->tun_erspan_idx,5"]) +AT_CHECK([ovs-appctl revalidator/wait]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_push(tnl_port(3),header(size=50,type=107,eth(dst=f8:bc:12:44:34:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=47,tos=0,ttl=64,frag=0x4000),erspan(ver=1,sid=0x38,idx=0x1)),out_port(100)) +]) + dnl Check ERSPAN tunnel pop AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.11.93,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], diff --git a/tests/tunnel.at b/tests/tunnel.at index 315453d..2bc004c 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -408,11 +408,42 @@ AT_CLEANUP AT_SETUP([tunnel - ERSPAN]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=erspan \ - options:remote_ip=1.1.1.1 ofport_request=1]) + options:remote_ip=1.1.1.1 options:key=1 options:erspan_ver=1 \ + options:erspan_idx=0x0 ofport_request=1 \ + -- add-port br0 p2 -- set Interface p2 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=2 \ + options:key=flow options:erspan_ver=1 options:erspan_idx=flow \ + -- add-port br0 p3 -- set Interface p3 type=erspan \ + options:remote_ip=1.1.1.1 ofport_request=3 \ + options:key=10 options:erspan_ver=2 options:erspan_dir=flow \ + options:erspan_hwid=flow \ + -- add-port br0 p4 -- set Interface p4 type=erspan \ + options:remote_ip=1.2.3.4 ofport_request=4 \ + options:key=flow options:erspan_ver=flow\ + ]) AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl br0 65534/100: (dummy-internal) - p1 1/1: (erspan: remote_ip=1.1.1.1) + p1 1/1: (erspan: erspan_idx=0x0, erspan_ver=1, key=1, remote_ip=1.1.1.1) + p2 2/1: (erspan: erspan_idx=flow, erspan_ver=1, key=flow, remote_ip=1.1.1.1) + p3 3/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_ver=2, key=10, remote_ip=1.1.1.1) + p4 4/1: (erspan: erspan_dir=flow, erspan_hwid=flow, erspan_idx=flow, erspan_ver=flow, key=flow, remote_ip=1.2.3.4) +]) + +dnl Check ERSPAN v1 flow-based tunnel push +AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x1->tun_erspan_idx,2"]) + +dnl Check ERSPAN v2 flow-based tunnel push +AT_CHECK([ovs-ofctl add-flow br0 "in_port=2, actions=set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,3"]) + +AT_CHECK([ovs-ofctl add-flow br0 "in_port=3, actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0x0->tun_erspan_hwid,4"]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=set_tunnel:0xb,set_field:0x1->tun_erspan_idx,output:2 + in_port=2 actions=set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:3 + in_port=3 actions=set_field:2->tun_erspan_ver,set_field:1->tun_erspan_dir,set_field:0->tun_erspan_hwid,output:4 ]) OVS_VSWITCHD_STOP @@ -523,28 +554,28 @@ AT_CHECK([tail -1 stdout], [0], dnl receive packet from ERSPAN port with v1 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0x7,tun_flags=+df-csum+key,in_port=3,nw_frag=no Datapath actions: 3 ]) dnl receive packet from ERSPAN port with wrong v1 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,ttl=64,erspan(ver=1,idx=0xabcd),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=1,erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x1,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=1,tun_erspan_idx=0xabcd,tun_flags=+df-csum+key,in_port=3,nw_frag=no Datapath actions: drop ]) dnl receive packet from ERSPAN port with v2 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=1,hwid=0x7),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=1,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=1,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: 2 ]) dnl receive packet from ERSPAN port with wrong v2 metadata AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,erspan_dir=0,erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_erspan_dir=0,tun_erspan_hwid=0x1,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: drop ]) @@ -557,17 +588,36 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], NXST_FLOW reply: in_port=1 actions=output:3 in_port=2 actions=output:4 - erspan_ver=1,erspan_idx=0x7,in_port=3 actions=output:1 - erspan_ver=2,in_port=4 actions=output:2 + tun_erspan_ver=1,tun_erspan_idx=0x7,in_port=3 actions=output:1 + tun_erspan_ver=2,in_port=4 actions=output:2 ]) dnl this time it won't drop AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x2,src=1.1.1.2,dst=2.2.2.2,ttl=64,erspan(ver=2,dir=0,hwid=0x17),flags(df|key)),in_port(1),skb_mark(0),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no + [Megaflow: recirc_id=0,eth,ip,tun_id=0x2,tun_src=1.1.1.2,tun_dst=2.2.2.2,tun_tos=0,tun_erspan_ver=2,tun_flags=+df-csum+key,in_port=4,nw_frag=no Datapath actions: 2 ]) +dnl flow-based erspan_idx options +AT_CHECK([ovs-vsctl add-port br0 p5 -- set Interface p5 type=erspan \ + options:remote_ip=1.1.1.2 ofport_request=5 \ + options:key=flow options:erspan_ver=1 options:erspan_idx=flow]) + +AT_CHECK([ovs-ofctl del-flows br0]) +AT_CHECK([ovs-ofctl add-flow br0 "in_port=1, actions=set_tunnel:11,set_field:0x7->tun_erspan_idx,5"]) + +AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], +[0], [dnl +NXST_FLOW reply: + in_port=1 actions=set_tunnel:0xb,set_field:0x7->tun_erspan_idx,output:5 +]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: set(tunnel(tun_id=0xb,dst=1.1.1.2,ttl=64,erspan(ver=1,idx=0x7),flags(df|key))),1 +]) + OVS_VSWITCHD_STOP AT_CLEANUP From patchwork Fri May 18 01:57: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: 915971 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="NYNeb0gn"; 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 40nBbM4k94z9s28 for ; Fri, 18 May 2018 12:15:27 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C7BB51149; Fri, 18 May 2018 01:59:20 +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 F09641138 for ; Fri, 18 May 2018 01:58: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 86D686F8 for ; Fri, 18 May 2018 01:58:59 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id a14-v6so2966551pfi.1 for ; Thu, 17 May 2018 18:58: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=UU1RXYZ2uh97/O9sN4ItEWlkcFT7J3HGaVr9SSa3hu4=; b=NYNeb0gnbbvdZkA2WTwZcJUxajkCjGJS7wfCzAhUZNvYCFGt4D2WnQ6xjgwj6Fw3xB jDjtm3asoEzQjJT9cr8ZN/4Z2ft/IaWeqY3ca5X2LqcXp0GrFVp8PmRteauStwD0aAai WiDw5qzgWCERihHmptuwfU40Ay/Y2a0xVB2pTtNeaws6p3CrJHo215ADKIt4wuIVrtA/ +pRHx4oBcbZbG3ppJz7vJdgvEgFyHrPy+FiYkKJ1N6EGh+1gz+cXh5om5SCjFzJg/WDM LZuz+Bu5RP6yk9A9Q/ARx47pr3rB6doE9kZLKdQOri1Eu7XMKTFIpdSq7fSx/NW+1f9R ku+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UU1RXYZ2uh97/O9sN4ItEWlkcFT7J3HGaVr9SSa3hu4=; b=P35HcWrU+eojuMHKDwvxmolsMoLqw10Rx4pDM5GHsWr4yf9s4k12ZlYotUJe4hI7mT bKCX2oz4QFlLl/XFPMbmPMOl7jUgaTjACAYae6gOsSFFXXHm7/Rtk9lg9RDZGzdLBjPC ThCGdbUHjJGKF0q0veyQzCa3yAUNAw6uv8+AB9f+zMPO2RJXWjDff/sVUz9c1lYgbg7u zYU7mnTA0pOVihCdPU0sOVdbl7j6/1ttfJj97ogYJHoPi4KQcpfVCO0DKCbeikFBlkcb Kf0HJqLQQAB4a2hwsB0qjcqpw2lpSNcXGD1mpOUVdlm/jQNRsOHtKyHVbZg4DBp52WAB LK2w== X-Gm-Message-State: ALKqPwcFYPsojL0ZfLXUh0jNy/JAVnK3qhmiSzlpnqbEQ2mvyx2miFJ6 zAz7AjZi2cEmfC5QBhhdi5E65w== X-Google-Smtp-Source: AB8JxZqdIrbXvsDUXAq6Zp8VY9YkZLhRDro8k9QBxOqk5Te9GvojlZJjDllVpcyeAdg2vEuXkvJf8A== X-Received: by 2002:a62:6304:: with SMTP id x4-v6mr7406550pfb.94.1526608738910; Thu, 17 May 2018 18:58:58 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:58 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:46 -0700 Message-Id: <1526608674-12702-34-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 33/41] ip6gre: add erspan v2 to tunnel lookup X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit 3b04caab81649a9e8d5375b919b6653d791951df Author: William Tu Date: Fri Mar 9 07:34:40 2018 -0800 ip6gre: add erspan v2 to tunnel lookup The patch adds the erspan v2 proto in ip6gre_tunnel_lookup so the erspan v2 tunnel can be found correctly. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index e0246d1..2f5fe49 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -138,7 +138,8 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, struct ip6_tnl *t, *cand = NULL; struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); int dev_type = (gre_proto == htons(ETH_P_TEB) || - gre_proto == htons(ETH_P_ERSPAN)) ? + gre_proto == htons(ETH_P_ERSPAN) || + gre_proto == htons(ETH_P_ERSPAN2)) ? ARPHRD_ETHER : ARPHRD_IP6GRE; int score, cand_score = 4; From patchwork Fri May 18 01:57: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: 915973 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="SFG2n43G"; 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 40nBcX2CMKz9s37 for ; Fri, 18 May 2018 12:16:28 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D6966117F; Fri, 18 May 2018 01:59:23 +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 DF73C10E9 for ; Fri, 18 May 2018 01:59:00 +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 9EFFA6F8 for ; Fri, 18 May 2018 01:59:00 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id 11-v6so974561pge.2 for ; Thu, 17 May 2018 18:59: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=jKxD2n13S0k6MDXeNhgxpzMg3sDHDB0c/qSf7yEzrM4=; b=SFG2n43Gjlp/W2pO57R08l9do/JzOfrHBMi2DZ7qSC1EC7bt6GOkqSW6aDhDw/DVmd usG7j+VAlr/4ejpwlOmglXlIgfrQYtpHOsptmErV4cv6EzxpyWG+3C7RQldWNaDzSEQE nVnfm9+AvsCv7CQyPwfk4MgyFpZOGI+WD2WepT974Y/eIwd1IFvO9SWtxgVhIZmZhUqb XQ4oTlnlkaMNjZdWAd0qM0aAvUj4LxV86Fe+vEzXiw1Fn/X6pVSQbcBrMbmxtngFRikc 5PcblMbcO02fOP7vISSkqLsU2ANEveiZhVLPvGv7QjuqO6X73HkMd0KgWR2mJK0sEBl9 NJVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jKxD2n13S0k6MDXeNhgxpzMg3sDHDB0c/qSf7yEzrM4=; b=bkyky/22hwZK3XlqDWlThFJ5o9W7s3x3yQcXeKNMnSlM+SJJbDcuSJJVepumlaHsiE TXdai/MmUO58e0KQEII1n7viOm4gR2naCIX3t7FQrqtVesNfRarfmMeOZLnGJ0+Hnwn1 iF7G0/82BzfvKLKZrSojVPLFQ/sKQMw/HTj6zcH68ZIXUUVI5bQzdr6YipALLeaM6L2x wHvgW4I7oSk1uYT06kjbRGmOlQQkzQFTLcO77dpoIoyVf46uTDsBQEBnNGAEo4XFmVwU 36yaVk9qo7gCl+EC6jOis9oPihBQI3JD238FQjnA+0UMsWdi6JhyeN3OYIDxCh9crm5q qc8A== X-Gm-Message-State: ALKqPwfvP9G38d9UMimcOG9QvaVbIfA9Mw8QYX0eziBiANwnMgZUnwCN PFU9y02Q2a3W+JxYC5UFeA11Gw== X-Google-Smtp-Source: AB8JxZr46aFk3fwdyOyWy7Myo/2LlvFI7cFCROdu8q2rgEuFfRcG/BKpcUgtoHcYHU5/F/LmeWOMkA== X-Received: by 2002:a62:4353:: with SMTP id q80-v6mr7395729pfa.228.1526608740023; Thu, 17 May 2018 18:59:00 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.58.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:58:59 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:47 -0700 Message-Id: <1526608674-12702-35-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 34/41] ip6erspan: improve error handling for erspan version number. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d6aa71197ffcb68850bfebfc3fc160abe41df53b Author: William Tu Date: Fri Mar 9 07:34:41 2018 -0800 ip6erspan: improve error handling for erspan version number. When users fill in incorrect erspan version number through the struct erspan_metadata uapi, current code skips pushing the erspan header but continue pushing the gre header, which is incorrect. The patch fixes it by returning error. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 2f5fe49..25f24e3 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1136,6 +1136,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, truncate, false); tpi.hdr_len = ERSPAN_V2_MDSIZE; tpi.proto = htons(ETH_P_ERSPAN2); + } else { + goto tx_err; } tpi.flags = TUNNEL_SEQ; From patchwork Fri May 18 01:57: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: 915974 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="BlKfjNpi"; 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 40nBd43pL8z9s28 for ; Fri, 18 May 2018 12:16:56 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 863A1117E; Fri, 18 May 2018 01:59:25 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D9B1D1048 for ; Fri, 18 May 2018 01:59: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 983EE6F3 for ; Fri, 18 May 2018 01:59:01 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id j20-v6so2956716pff.10 for ; Thu, 17 May 2018 18:59: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=WfNAhJrgzuxp4IvFbYsjO81ly1shL5BQOn0687pWFS8=; b=BlKfjNpi8R27wfFEdWlQZJ5+Jp+vPSKEekekirUdpGPO1ve5naPvMjz3Hv3qW30Q5Q XdTS3usvQ55vhla7Ocv5J/oXfTqUkoWSXphz7i2xJoSh74r1j6kqB61y3QeV5e5xabo1 i8OAYza/wykvoHEKw0cyUVcl5nx/I4AfTRSls2n+eVg9Cxh/5AzT5cKwTSPhTFUjA3yQ +YDPyNA3ja4aq5hmY0doPOp7QXHfMpyyIG8IsL/rnznzlkzMlpgYKIQvSsYB4t7Dchc0 vKLn0FDvUTlooh1R2eSTo15ChfBJYsljzA1U0jY82APO1s6fcshlmBCLCsoOsyOrjbhH I0ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WfNAhJrgzuxp4IvFbYsjO81ly1shL5BQOn0687pWFS8=; b=Zu4CV4/znHgZK6WDIFCT4uFmtOOva3uft8ew8ppGWFLNi7IN7NPkBALxTFm8bA2svA o8byqHesQGl+ROhzy0JHrm73CT+YtraYe829WTt0xdsrTudM/sbwpP8sQRwDGB3dItX2 40zInjQ9VejEunO3wMomlR4TTqIZdOrzk0/0QeTb62qyzKgNVKixyQuJuBQ4FvoxC0Jx 0vmo55++pZ9y8yxGghpS6jbWgXxdqcnwTPB57InQpb8s1g8DQ+xEsN1h/Baxnf8jW6tG ajJLeWxzXXlOgPRcSEtckJXBPfPvalWWaekm+4zME7HBhcGzGbkhX405ATb7HY/lhUfd M0Ng== X-Gm-Message-State: ALKqPwfLVHx/uOHVliTpd7PkzgSa1zaJcXMN5qAV3o5V4pm4Rw19skKq yDw9dBrG/k+LYeSdgeRlbckcyg== X-Google-Smtp-Source: AB8JxZr8044eWuxEgZtaAgK6YKz0TWX+RaW6JEKE/Q9FBVT/tiopQUV7kLy2k+QCvU8dhKtJqxsjuA== X-Received: by 2002:a62:8785:: with SMTP id i127-v6mr7464432pfe.201.1526608741056; Thu, 17 May 2018 18:59:01 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:00 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:48 -0700 Message-Id: <1526608674-12702-36-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 35/41] ip6erspan: make sure enough headroom at xmit. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit e41c7c68ea771683cae5a7f81c268f38d7912ecb Author: William Tu Date: Fri Mar 9 07:34:42 2018 -0800 ip6erspan: make sure enough headroom at xmit. The patch adds skb_cow_header() to ensure enough headroom at ip6erspan_tunnel_xmit before pushing the erspan header to the skb. Signed-off-by: William Tu Signed-off-by: David S. Miller Cc: William Tu Signed-off-by: Greg Rose --- datapath/linux/compat/ip6_gre.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 25f24e3..c9bd80d 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1094,6 +1094,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + if (skb_cow_head(skb, dev->needed_headroom)) + goto tx_err; + t->parms.o_flags &= ~TUNNEL_KEY; IPCB(skb)->flags = 0; From patchwork Fri May 18 01:57: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: 915975 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="ZO6YUE5m"; 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 40nBfD037Yz9s28 for ; Fri, 18 May 2018 12:17:55 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0031F11AF; Fri, 18 May 2018 01:59:27 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8A1C11144 for ; Fri, 18 May 2018 01:59:03 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 3CAB26F9 for ; Fri, 18 May 2018 01:59:03 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id q22-v6so2957159pff.11 for ; Thu, 17 May 2018 18:59: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=4Jw8prR/6YlZpqCSVnDahtCXtFXLy8O9zvllDmNkO7c=; b=ZO6YUE5mtKZgON3ZQAD/W00FC5ftKy1J6WHTCFjc+rxVDV4t7ToQAqG1xEu+UaGQrF RdNI7bhrUexKScI9rRar2VDIdtEIo7Rdmiz6U9Y7wEp0p9/eda6B5YoJEmspuWC1og3b mnIWpM1EMm/aLZuyby/b4l9+GhmCpwVxp5msp5jThP793Etu+01ucFZd706QCD/A2eAA /iS93m1NQ/VJkYvcch3WgJwpON/hKUIjRguobuahuxwftx8KjgTDDpexcN6PidoIfUsV TvijZ1MQqMvDomhMKxuvHJeBoJpbHkP+8p0EDBuHBqlpjRiRiuIDiTRq9UMrC34VKmoS 7JMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4Jw8prR/6YlZpqCSVnDahtCXtFXLy8O9zvllDmNkO7c=; b=HvJfNRXO2aKC3seARVv2F5F5Rx0FgPiBbzW1qIYtNqO8nbRFLuUSibUkUkjXDAJZG1 DM4NVMpQAAk7ZtJP5/ZWSWXlHYeKV+KypccCTJWYISbf+co1EPMJGKRLyyUj3hZDa6To ltE2C5/pjrO4UKnD1k0U8qX4IM/0+R4+QBD9Y70OpMUrA0YPyfUH3bR1LNoyeiGiNCi/ K25b4uyQEryB28A0Xl8QpFzU48qLXzoao7HcWRYsrfq+lZRi6UEJfqhCvkQBm1zMKhrg XdEe1BUvUWWrcMyowl9E9rBmclbvX3WwTYfK4NDkKFxRb79Mh0HK4WbJkBkWuh6LXAey lglw== X-Gm-Message-State: ALKqPwflwRp87bzTDbwyxjmcUHobUvLj52eoz/lLmtVuISBBpqLnO0px BxeEgR6po2aSOR2/Hk7CArjSKg== X-Google-Smtp-Source: AB8JxZpD5fzUgfDLL+9xPxkIufP7n5mCUGorQH8HULsVb8KXus61fH/Ab/p/DhVCjqF1ou4CKvkCFA== X-Received: by 2002:a62:11dc:: with SMTP id 89-v6mr7441471pfr.18.1526608742581; Thu, 17 May 2018 18:59:02 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:01 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:49 -0700 Message-Id: <1526608674-12702-37-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 36/41] erspan: auto detect truncated ipv6 packets. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Upstream commit: commit d5db21a3e6977dcb42cee3d16cd69901fa66510a Author: William Tu Date: Fri May 11 05:49:47 2018 -0700 erspan: auto detect truncated ipv6 packets. Currently the truncated bit is set only when 1) the mirrored packet is larger than mtu and 2) the ipv4 packet tot_len is larger than the actual skb->len. This patch adds another case for detecting whether ipv6 packet is truncated or not, by checking the ipv6 header payload_len and the skb->len. Reported-by: Xiaoyan Jin Signed-off-by: William Tu Signed-off-by: David S. Miller Signed-off-by: William Tu Cc: Greg Rose --- datapath/linux/compat/ip6_gre.c | 6 ++++++ datapath/linux/compat/ip_gre.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index c9bd80d..59694dd 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1071,6 +1071,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, __be32 tun_id; __u32 mtu; int nhoff; + int thoff; /* OVS doesn't support native mode ip6 tunnel traffic so @@ -1094,6 +1095,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + thoff = skb_transport_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IPV6) && + (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) + truncate = true; + if (skb_cow_head(skb, dev->needed_headroom)) goto tx_err; diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 6b40013..6001d69 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -632,6 +632,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, int version; __be16 df; int nhoff; + int thoff; tun_info = skb_tunnel_info(skb); if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || @@ -664,6 +665,11 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; + thoff = skb_transport_header(skb) - skb_mac_header(skb); + if (skb->protocol == htons(ETH_P_IPV6) && + (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) + truncate = true; + if (version == 1) { erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), ntohl(md->u.index), truncate, true); From patchwork Fri May 18 01:57:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915976 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="UxWm6CY3"; 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 40nBfy1NP9z9s28 for ; Fri, 18 May 2018 12:18:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D117211AB; Fri, 18 May 2018 01:59:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 6A3F3114B for ; Fri, 18 May 2018 01:59:04 +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 1C8A86FC for ; Fri, 18 May 2018 01:59:04 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id w4-v6so2605709pgq.8 for ; Thu, 17 May 2018 18:59: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=uo9suIz8j3U5mzDWGfjg7845xUPK37Kcwx6xBEG/u5Q=; b=UxWm6CY3WfRJRBvnd0S9QEqmH7hcuL1BwBk/syn3TjICi30HEGc3GU1q/B+yNi/FgS GOrBRQy2DRKgGifNAQOZGQHVkHfc+c4WvBnn3apGM6lKrL0SoPjvjIjeisPQPe//l7Bo PckcCa0w1oXokZEotHzWcQmIpnC4rxCAxahF1i9KrySsZAX9hIwMP91COwR8k9k3nRpL MR0h/gQtuQBGNdTflHDy8Zj1K8jr/GHNoBHORkWmG0N4GUYRSV8Z7OGOle4qkxh3J017 iuHnlz+W4DwEMg9yQOhiNBaORRcZasCWTLDmht2F/bTZ6oZhBmHvyldbW360NZdJ/oOi wPww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uo9suIz8j3U5mzDWGfjg7845xUPK37Kcwx6xBEG/u5Q=; b=JuYToHYuo2YNa7JJ5teUiu63K4bHMSAJi4gdI1B5VG+uGYCmntkT/7lqx41tg3mXgY +9oVPFbpmsD/5IOzlGvjMwHE8KzmwralXjPgKwQpcJwe9DsFQiARZe1G304V424sSmpz MREsUy7WUxPa2dgoXMyrocbWC51Y8crRtn/XpYQ6k9ayWTedX/IEIxykj48/Jvw/WAaJ k8iALtlMRpupPU5FDL7slb8fzYNpiUQ7aqlBBfR6VEGHELIyyPAHjXR+Rlxb78fMKaD4 38glDcCn/1dLr7pI1TYAAyKJpx5meFHmqsF+ehUHPkyMd/gbNGXTfMbd64xYeDy989CS UT4Q== X-Gm-Message-State: ALKqPwcqCQqTbTccrnVAsYecqX8d0o+WQp/7fdPY/80H3ci79XclmuCt 2/UQsG73G5TBn1yEIV+uSD7UxQ== X-Google-Smtp-Source: AB8JxZrZLoaMEPJP5/IEPjb5slmuqIAoL5oekUKLfs3D719Wy04k0EckhqRweoyV9JTnl+3RhQSEsg== X-Received: by 2002:a62:d286:: with SMTP id c128-v6mr7442682pfg.240.1526608743449; Thu, 17 May 2018 18:59:03 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:02 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:50 -0700 Message-Id: <1526608674-12702-38-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 37/41] erspan: set bso when truncated bit is set. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu Before the patch, the erspan BSO bit (Bad/Short/Oversized) is not handled. BSO has 4 possible values: 00 --> Good frame with no error, or unknown integrity 11 --> Payload is a Bad Frame with CRC or Alignment Error 01 --> Payload is a Short Frame 10 --> Payload is an Oversized Frame This patch set BSO to 01 when truncate is true. Signed-off-by: William Tu --- datapath/linux/compat/include/net/erspan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datapath/linux/compat/include/net/erspan.h b/datapath/linux/compat/include/net/erspan.h index 813a9c5..8adc89f 100644 --- a/datapath/linux/compat/include/net/erspan.h +++ b/datapath/linux/compat/include/net/erspan.h @@ -268,7 +268,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, } *qp; u16 vlan_tci = 0; u8 gra = 0; /* 100 usec */ - u8 bso = 0; /* Bad/Short/Oversized */ + u8 bso = truncate; /* Bad/Short/Oversized */ u8 sgt = 0; u8 tos; From patchwork Fri May 18 01:57:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915977 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="pGN36I3r"; 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 40nBgT69wjz9s28 for ; Fri, 18 May 2018 12:19:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id BE9CC11B8; Fri, 18 May 2018 01:59:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 56D901110 for ; Fri, 18 May 2018 01:59:05 +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 DE4186F8 for ; Fri, 18 May 2018 01:59:04 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id c22-v6so1941018pgn.11 for ; Thu, 17 May 2018 18:59: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=DyH4ms+2Z8FzJmc4P9cO0FdwF851FOMUs6qEYMoZlfM=; b=pGN36I3r8g1YCA9Ro8M3M16jrs2vRxD/mnjC6P/PSW6jUnYGgBPnLU9btWHt4p+wAd qu+LDJltThwkLs7LBomAq1s+ccl9cOhaqTE+VLaQfT5zWyAIbyJ5prf5YwWH4FDoKSDH R6xxwaniF5RdtSZJ8IJIJsg0M+q66ts0jTIwIeB7Vku1bN28SmMkNo8JVty5RJ8qQDBM uG2H6fdXAsODIHReYlGvwPl8HWlPke9m0BWYXmLzaHVZZU8LFStQ5k6fHDFNRjc81iOj 83Tpx1gP05fDT3uFLlxHrx9ar7cEmmMmPBHGX+c+B2eH+GAIbUFfERwF/CZmVQPgJtIF DA5A== 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=DyH4ms+2Z8FzJmc4P9cO0FdwF851FOMUs6qEYMoZlfM=; b=ilbY0ZANaR/Mr35DmhWZFYmXjGgJs+ZI/Cr8I4Ss7etoWabZ3j/Tjjy3ot7o4SIBGr OSthYiydZ+Gs3RxG9wO6WuKALvISa/rlKDmlE0RscnpfOfbW5366NrvaXO+dXQGnqbsB DOF60BNyNWaQgEIDEkgkmGW/qAAM0lVtKpDzXoryfmm4p8ERpQIEsjUr3NanNBi6c0RL OJleygU6iueHDhTzOkdvv20Hr9l8NTjAtWRgi+bZi5XgZf55NcB1Cs+hCkYNgbkkRSPH uIMMEO4MQ5nWJ9MjnAAyV+TUx/zIwmrgGkDBnjzLcg9g3my1NQ3OmqBK1TsFCdyy0KgB GM3g== X-Gm-Message-State: ALKqPwfKzVCiQNsC1pNdnP4WB204nTzErhWBhA0WVEm3gBUcHSqfxqnd rAL2z2QkgUrS85j5tifB7gAkiQ== X-Google-Smtp-Source: AB8JxZpOt5zb3NKwkHAqpzom8QnTQ13a0OasK16pEp+kn4syyBn3pudUCcW8WF1a78DlND96pObojA== X-Received: by 2002:a65:6250:: with SMTP id q16-v6mr5956328pgv.113.1526608744306; Thu, 17 May 2018 18:59:04 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:03 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:51 -0700 Message-Id: <1526608674-12702-39-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 38/41] tunnel: add support for erspan and ip6erspan type. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu This patch adds support for erspan and ip6erspan. Signed-off-by: William Tu Reviewed-by: Greg Rose Tested-by: Greg Rose --- lib/odp-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index 2109fac..d7b5bcd 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2882,7 +2882,8 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, nl_msg_end_nested(a, vxlan_opts_ofs); } tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a); - if (tun_key->erspan_ver) { + if (!tnl_type || !strcmp(tnl_type, "erspan") || + !strcmp(tnl_type, "ip6erspan")) { struct erspan_metadata opts; opts.version = tun_key->erspan_ver; From patchwork Fri May 18 01:57:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915978 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="DMfFovmK"; 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 40nBgz6y3Dz9s28 for ; Fri, 18 May 2018 12:19:27 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EAD7511AE; Fri, 18 May 2018 01:59:30 +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 4D15D1100 for ; Fri, 18 May 2018 01:59:06 +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 D94FE6F3 for ; Fri, 18 May 2018 01:59:05 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id u8-v6so2601230pgp.13 for ; Thu, 17 May 2018 18:59: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=s4xT+Maj0ypq5XAqKLn9VglV89jRmLAcLKT4xq80cms=; b=DMfFovmK8wrf2dLKI+JE3mTaTIRiL+2ks7gYz3yRo3QgjTQZx/tVQn+IACUIIs/pZr lEU724dZW9K4tMFraIxXLMF03en/fMMb8AdvNftKTPzhNN5pdizpCXFjTlk1IDhu5d8z 7ObWbrowgP0XZyTxJ02Kw5z01sKHo6HDGEx4ZVGhOkVm8HFbR6nqPBxoHj9bs/sYJuaU t/VDb2kx3Zk2GicKEw8NyQf3CqnhshVt+9fMFvkbP+1+1FRDX7RosWjvheiD3ywxVZic viGKJxQkb0U+pJoy85UY67RSK25U9LcMeJ4Cb3orc+Dpab9gd8LqDgUkv9kAZ6SzPej8 yIRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=s4xT+Maj0ypq5XAqKLn9VglV89jRmLAcLKT4xq80cms=; b=N5CyvwOQN/m8lW0sM0b3uX6ChFOvQmlQ2mzgK/v9+XWULZLmIfT73qRlEBREzdxDnB CUKYLTygmni5Bmn9Km0n0o1PtJlHbJddGvzpK9tv9/NnjXcOMAYXYRXHtIM0gCqM9gS1 OhOInn7GpbVOCan4y0L8AHFxhUKtkLGXSpDKoqT/9mG5SwuikotoV5OZhL6A0BbuFzYj UrNijbcH0G4xb9v+P4uqH3kGEMCsMT5Tsb+vNpBnYvXJeVhauYF++iM0mEyIrz++nxOh z3xrFN1RbbugRrqzbsFGj+BsSOBNhyE0kJSVYaZf6RvwCy7L72mBxBPghywCrQIB08Uk G5hQ== X-Gm-Message-State: ALKqPwcki4+X+/CkavchdKmu6GOwLjfnZXR32rKT25HLF6bekZpYcSGE OW9ONQc2g4Mu5pkToRDVPPwbDw== X-Google-Smtp-Source: AB8JxZqgp34A7VWFCzrB8xTEfohrvmKLu9Fl/Pl11lH9gZ46DEdCqyL6/8VqGl4L/lzFbAcIWJTkVw== X-Received: by 2002:a62:b610:: with SMTP id j16-v6mr7367606pff.17.1526608745199; Thu, 17 May 2018 18:59:05 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:04 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:52 -0700 Message-Id: <1526608674-12702-40-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,UPPERCASE_50_75 autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V2 39/41] rhel: Enable ERSPAN features for RHEL 7.x X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Enable ERSPAN on RHEL 7.x Signed-off-by: Greg Rose --- acinclude.m4 | 15 ++++++++++++++- datapath/linux/compat/ip6_gre.c | 13 ++++++------- datapath/linux/compat/ip_gre.c | 12 ++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 8962862..2351792 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -531,7 +531,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ [OVS_GREP_IFELSE([$KSRC/include/net/ip_tunnels.h], [iptunnel_pull_offloads], [OVS_GREP_IFELSE([$KSRC/include/net/dst_cache.h], [dst_cache], - [OVS_DEFINE([USE_UPSTREAM_TUNNEL])])])]) + [OVS_GREP_IFELSE([$KSRC/include/net/erspan.h], [erspan_md2], + [OVS_DEFINE([USE_UPSTREAM_TUNNEL])])])])]) OVS_GREP_IFELSE([$KSRC/include/net/dst_cache.h], [dst_cache], [OVS_DEFINE([USE_BUILTIN_DST_CACHE])]) @@ -866,6 +867,18 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c], [parse_gre_header], [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ENCAP_DPORT]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_COLLECT_METADATA]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_IGNORE_DF]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_FWMARK]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ERSPAN_INDEX]) + OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h], + [IFLA_GRE_ERSPAN_HWID]) if cmp -s datapath/linux/kcompat.h.new \ datapath/linux/kcompat.h >/dev/null 2>&1; then diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c index 59694dd..c48c389 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1693,30 +1693,29 @@ static void __net_exit ip6gre_exit_batch_net(struct list_head *net_list) } enum { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) +#ifndef HAVE_IFLA_GRE_ENCAP_DPORT IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, IFLA_GRE_ENCAP_FLAGS, IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_DPORT, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) +#ifndef HAVE_IFLA_GRE_COLLECT_METADATA IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +#ifndef HAVE_IFLA_GRE_IGNORE_DF IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) +#ifndef HAVE_IFLA_GRE_FWMARK IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_INDEX IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_HWID IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, IFLA_GRE_ERSPAN_DIR, IFLA_GRE_ERSPAN_HWID, #endif - }; #define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 6001d69..eecd41a 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -814,25 +814,25 @@ out: } enum { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) +#ifndef HAVE_IFLA_GRE_ENCAP_DPORT IFLA_GRE_ENCAP_TYPE = IFLA_GRE_FLAGS + 1, IFLA_GRE_ENCAP_FLAGS, IFLA_GRE_ENCAP_SPORT, IFLA_GRE_ENCAP_DPORT, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) +#ifndef HAVE_IFLA_GRE_COLLECT_METADATA IFLA_GRE_COLLECT_METADATA = IFLA_GRE_ENCAP_DPORT + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) +#ifndef HAVE_IFLA_GRE_IGNORE_DF IFLA_GRE_IGNORE_DF = IFLA_GRE_COLLECT_METADATA + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) +#ifndef HAVE_IFLA_GRE_FWMARK IFLA_GRE_FWMARK = IFLA_GRE_IGNORE_DF + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_INDEX IFLA_GRE_ERSPAN_INDEX = IFLA_GRE_FWMARK + 1, #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) +#ifndef HAVE_IFLA_GRE_ERSPAN_HWID IFLA_GRE_ERSPAN_VER = IFLA_GRE_ERSPAN_INDEX + 1, IFLA_GRE_ERSPAN_DIR, IFLA_GRE_ERSPAN_HWID, From patchwork Fri May 18 01:57:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915979 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="FdWL/ODA"; 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 40nBhW71nnz9s28 for ; Fri, 18 May 2018 12:19:55 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0089C11BC; Fri, 18 May 2018 01:59:32 +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 EF75310FD for ; Fri, 18 May 2018 01:59:07 +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 303926F3 for ; Fri, 18 May 2018 01:59:07 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id u8-v6so2601250pgp.13 for ; Thu, 17 May 2018 18:59:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ialQS4bWXLbkKIzfK2jAH9gDaWxY8I6EZlbVhIAhz5E=; b=FdWL/ODAIAM8eKfmc/oEgSR0MPb92Nd9JJTsuO5OzJzjDlQUGIo+JYrgk+KBNBLWaw cjy6mvpzqrTpy2/SJZLg+EvDsgwtEYXuSyM9hMsF1mOiu0dJbny1aE8QcCMnYmEQyC3p uchqVEzLFCN2fKTxAf1wofUaTpIOWCBrFW97k32PLmXdAVhPfB7A5gDw0N9pEWv08VND UGPUFtjePnVdwLkGKHw/+eD6KylHGZyTflMINmDTS8WtAfUv+ZgGdQPA5II032QxdL9q s0U3mXS1g51FfRlk8gKBQdpNsYepGKWorAT+IDypGXmekz8NKMwHyfeW3XHFwToGUHLW 71wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ialQS4bWXLbkKIzfK2jAH9gDaWxY8I6EZlbVhIAhz5E=; b=DhyQVMlhDvrXc1tAIGe9R38WG6X/PokKVzydGu29FM0Enwobhx40OzYXeflNukZdvM vuqwFBsNd6bM//qZJ/BwsN/B4t2PnwTQ4bkth5UPrZ51tLHC9ln4UyAkK+O5L4LJM48K HxcIrN/GUEDTMrjwRZtDA+px1exAUle2InS7I7rxilXz6RTqPnY7/zjvm7u1JSF2tG7p ed3X6uMFoVnZjK+TfqufUGwH4JtXzgxP4eYEDnyUScUpWSJn3rRbHDJNGELP0WOgI0I1 U3BOmRWl62y6nWo6OxFDdL+nvOQ+E4AD4+bCuTiRuZfxrXvaM9klaLHvpajcKfMQWgay NMuQ== X-Gm-Message-State: ALKqPwc3GeMCs4/fWFGepmMOOX0rww2xz5R9epFQjfzr76MSmto4eLJn rTT8FpAxyEbwjLcZr4ynYq9fTg== X-Google-Smtp-Source: AB8JxZoeaoJvg/Xb6yoOZBAC7hKhX7SV4XgTqGr2plGTL7IwCRKf/B3QBUciHcCLh+drAL+FB3BnXg== X-Received: by 2002:aa7:8354:: with SMTP id z20-v6mr7364518pfm.166.1526608746451; Thu, 17 May 2018 18:59:06 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:06 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:53 -0700 Message-Id: <1526608674-12702-41-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 40/41] gre: Resolve gre receive issues X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org On newer Linux kernels or on older kernels such as Red Hat that backport from newer upstream Linux kernel releases the built-in gre kernel module will interfere with OVS gre code in the receive path. Fix this up by placing the gre kernel code within the openvswitch driver so it will not have to depend on the built-in gre kernel module. Signed-off-by: Greg Rose --- datapath/linux/compat/gre.c | 113 +++++++++++++++++++++++++++++--- datapath/linux/compat/include/net/gre.h | 18 +++++ datapath/linux/compat/ip_gre.c | 38 +++++++++-- datapath/vport.c | 13 ++-- 4 files changed, 164 insertions(+), 18 deletions(-) diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index 7d16aee..b45f8b4 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -41,6 +41,104 @@ #ifndef USE_UPSTREAM_TUNNEL #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) +static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; + +int rpl_gre_add_protocol(const struct gre_protocol *proto, u8 version) +{ + if (version >= GREPROTO_MAX) + return -EINVAL; + + return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? + 0 : -EBUSY; +} +EXPORT_SYMBOL_GPL(rpl_gre_add_protocol); + +int rpl_gre_del_protocol(const struct gre_protocol *proto, u8 version) +{ + int ret; + + if (version >= GREPROTO_MAX) + return -EINVAL; + + ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? + 0 : -EBUSY; + + if (ret) + return ret; + + synchronize_rcu(); + return 0; +} +EXPORT_SYMBOL_GPL(rpl_gre_del_protocol); + +static int gre_rcv(struct sk_buff *skb) +{ + const struct gre_protocol *proto; + u8 ver; + int ret; + + if (!pskb_may_pull(skb, 12)) + goto drop; + + ver = skb->data[1]&0x7f; + if (ver >= GREPROTO_MAX) + goto drop; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (!proto || !proto->handler) + goto drop_unlock; + ret = proto->handler(skb); + rcu_read_unlock(); + return ret; + +drop_unlock: + rcu_read_unlock(); +drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static void gre_err(struct sk_buff *skb, u32 info) +{ + const struct gre_protocol *proto; + const struct iphdr *iph = (const struct iphdr *)skb->data; + u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f; + + if (ver >= GREPROTO_MAX) + return; + + rcu_read_lock(); + proto = rcu_dereference(gre_proto[ver]); + if (proto && proto->err_handler) + proto->err_handler(skb, info); + rcu_read_unlock(); +} + +static const struct net_protocol net_gre_protocol = { + .handler = gre_rcv, + .err_handler = gre_err, + .netns_ok = 1, +}; + +int rpl_gre_init(void) +{ + pr_info("GRE over IPv4 demultiplexor driver\n"); + + if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { + pr_err("can't add protocol\n"); + return -EAGAIN; + } + return 0; +} +EXPORT_SYMBOL_GPL(rpl_gre_init); + +void rpl_gre_exit(void) +{ + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); +} +EXPORT_SYMBOL_GPL(rpl_gre_exit); + #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen #define gre_calc_hlen rpl_ip_gre_calc_hlen static int rpl_ip_gre_calc_hlen(__be16 o_flags) @@ -142,25 +240,20 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, return iptunnel_pull_header(skb, hdr_len, tpi->proto, false); } -#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ - static struct gre_cisco_protocol __rcu *gre_cisco_proto; static int gre_cisco_rcv(struct sk_buff *skb) { - struct tnl_ptk_info tpi; struct gre_cisco_protocol *proto; + struct tnl_ptk_info tpi; + bool csum_err = false; rcu_read_lock(); proto = rcu_dereference(gre_cisco_proto); if (!proto) goto drop; -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER - { - bool csum_err = false; - if (parse_gre_header(skb, &tpi, &csum_err) < 0) + + if (parse_gre_header(skb, &tpi, &csum_err) < 0) goto drop; - } -#endif proto->handler(skb, &tpi); rcu_read_unlock(); return 0; @@ -194,7 +287,6 @@ EXPORT_SYMBOL_GPL(rpl_gre_cisco_register); int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto) { int ret; - ret = (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, proto, NULL) == proto) ? 0 : -EINVAL; @@ -207,6 +299,7 @@ int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto) } EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister); +#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */ #endif /* !HAVE_GRE_CISCO_REGISTER */ #endif diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index 11a95a5..141ed2d 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -32,6 +32,15 @@ static inline void rpl_ip6_tunnel_cleanup(void) { } +static inline int rpl_gre_init(void) +{ + return 0; +} + +static inline void rpl_gre_exit(void) +{ +} + #define gre_fb_xmit dev_queue_xmit #ifdef CONFIG_INET @@ -153,6 +162,8 @@ int rpl_ip6gre_init(void); void rpl_ip6gre_fini(void); int rpl_ip6_tunnel_init(void); void rpl_ip6_tunnel_cleanup(void); +int rpl_gre_init(void); +void rpl_gre_exit(void); #define gretap_fb_dev_create rpl_gretap_fb_dev_create struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name, @@ -164,6 +175,11 @@ int rpl_gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, #define gre_fb_xmit rpl_gre_fb_xmit netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); + +#define gre_add_protocol rpl_gre_add_protocol +int rpl_gre_add_protocol(const struct gre_protocol *proto, u8 version); +#define gre_del_protocol rpl_gre_del_protocol +int rpl_gre_del_protocol(const struct gre_protocol *proto, u8 version); #endif /* USE_UPSTREAM_TUNNEL */ #define ipgre_init rpl_ipgre_init @@ -172,6 +188,8 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb); #define ip6gre_fini rpl_ip6gre_fini #define ip6_tunnel_init rpl_ip6_tunnel_init #define ip6_tunnel_cleanup rpl_ip6_tunnel_cleanup +#define gre_init rpl_gre_init +#define gre_exit rpl_gre_exit #define gre_fill_metadata_dst ovs_gre_fill_metadata_dst int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb); diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index eecd41a..9240ab2 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -96,13 +96,14 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER /* Called with rcu_read_lock and BH disabled. */ static int gre_err(struct sk_buff *skb, u32 info, const struct tnl_ptk_info *tpi) { return PACKET_REJECT; } - +#endif static struct dst_ops md_dst_ops = { .family = AF_UNSPEC, }; @@ -746,11 +747,28 @@ static void __gre_tunnel_init(struct net_device *dev) } } -static struct gre_cisco_protocol ipgre_protocol = { +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER +static struct gre_cisco_protocol ipgre_cisco_protocol = { .handler = gre_rcv, .err_handler = gre_err, .priority = 1, }; +#endif + +static int __gre_rcv(struct sk_buff *skb) +{ + return gre_rcv(skb, NULL); +} + +void __gre_err(struct sk_buff *skb, u32 info) +{ + pr_warn("%s: GRE receive error\n", __func__); +} + +static const struct gre_protocol ipgre_protocol = { + .handler = __gre_rcv, + .err_handler = __gre_err, +}; static int __net_init ipgre_init_net(struct net *net) { @@ -1631,11 +1649,19 @@ int rpl_ipgre_init(void) if (err < 0) goto pnet_ipgre_failed; - err = gre_cisco_register(&ipgre_protocol); +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + err = gre_cisco_register(&ipgre_cisco_protocol); if (err < 0) { pr_info("%s: can't add protocol\n", __func__); goto add_proto_failed; } +#else + err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); + if (err < 0) { + pr_info("%s: can't add protocol\n", __func__); + goto add_proto_failed; + } +#endif pr_info("GRE over IPv4 tunneling driver\n"); @@ -1658,7 +1684,11 @@ void rpl_ipgre_fini(void) { ovs_vport_ops_unregister(&ovs_erspan_vport_ops); ovs_vport_ops_unregister(&ovs_ipgre_vport_ops); - gre_cisco_unregister(&ipgre_protocol); +#ifdef HAVE_DEMUX_PARSE_GRE_HEADER + gre_cisco_unregister(&ipgre_cisco_protocol); +#else + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); +#endif unregister_pernet_device(&ipgre_net_ops); unregister_pernet_device(&erspan_net_ops); unregister_pernet_device(&ipgre_tap_net_ops); diff --git a/datapath/vport.c b/datapath/vport.c index 184c859..73dd778 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -66,7 +66,7 @@ int ovs_vport_init(void) goto err_lisp; err = ipgre_init(); if (err) - goto err_gre; + goto err_ipgre; err = ip6gre_init(); if (err) goto err_ip6gre; @@ -76,15 +76,19 @@ int ovs_vport_init(void) err = geneve_init_module(); if (err) goto err_geneve; - err = vxlan_init_module(); if (err) goto err_vxlan; err = ovs_stt_init_module(); if (err) goto err_stt; - return 0; + err = gre_init(); + if (err) + goto err_gre; + return 0; +err_gre: + ovs_stt_cleanup_module(); err_stt: vxlan_cleanup_module(); err_vxlan: @@ -95,7 +99,7 @@ err_ip6_tunnel: ip6gre_fini(); err_ip6gre: ipgre_fini(); -err_gre: +err_ipgre: lisp_cleanup_module(); err_lisp: kfree(dev_table); @@ -109,6 +113,7 @@ err_lisp: */ void ovs_vport_exit(void) { + gre_exit(); ovs_stt_cleanup_module(); vxlan_cleanup_module(); geneve_cleanup_module(); From patchwork Fri May 18 01:57:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915980 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="SeuMcu5E"; 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 40nBj305Kwz9s37 for ; Fri, 18 May 2018 12:20:23 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EF38511C0; Fri, 18 May 2018 01:59:32 +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 6A1EB1115 for ; Fri, 18 May 2018 01:59:08 +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 353F7196 for ; Fri, 18 May 2018 01:59:08 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id a22-v6so2961013pfn.6 for ; Thu, 17 May 2018 18:59:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+7npVpruVivgEdzdzlmzo2EG9C5oiUgfnBhOyaLQpTc=; b=SeuMcu5ETMyx/4pJLD70uzb4gWaq1vugBxITX3SG+aH1JGfVCyerB3MRF/8+sb6A2G ZZeFhQEQa2gxjhlCyCrWNxmOIBdQiYAZDyBpEwderameThX555Um/GZARKCKmlCLB0PX PzOGcEN3KZ94MlWud35k5FlTxFYbh1//kQ76Q6hEgvL4L71e0UrjB2BwKpq5mlEXrTmV AVDJK6hj1VMiyB0GUjtsre8uWruXj5CQt9JHK21OCmcO6jDBk6hDyqaztH3b7yuFAonW ivAFKK3/3Gup/35llNRWFGOCuK1tx3dXFVUkRMIQPYY88TVDMA0diSsOHgt20LTHGZYZ ay/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=+7npVpruVivgEdzdzlmzo2EG9C5oiUgfnBhOyaLQpTc=; b=rpSgse16ez+e9KUW7IFTgYv8rHqJ3zZHJhncxxxODhEhpgc2hjm1tXlT3Xo0J3fNrF xfbz7PVtKHXk2EpqVXmAvlLf+75zTFrfYBz1ZkiD9WkwfB3CS9dV315uHfRFTtR66Nb+ R9+VW7pWZID6af+J50YHovONHahMxHKmyNvt+UHcOH46l3u4Ys5tRwUsRsFsFLIbwXku ZwJaArIspF5OeJoaMTBvd02VucBCvw8iyCFjJfW5+DWoEa6VxwV1QSb5YCao3goDisfw 2JCSiOiFqSJt+GZf0zqXMGR7ZuE/U3onGL3Si5z5DrtxD9ZHK3HpSGHsSfq1PwG/AH5s OGSg== X-Gm-Message-State: ALKqPwdTvPYgRzT+B6PoukK9b55ZdAy1ESbjuBEJeQsPoVaITm7GeWXK x2PtW1XmYetxDGZj5BZo4KMGUg== X-Google-Smtp-Source: AB8JxZpEAXbr5atYe7Elt7Ckg7OjdtSuxQUjAyqsVBwbJfaVkwqu4vrU8Sp+8Rk/VS1dgyhA5GkptQ== X-Received: by 2002:a62:ca4a:: with SMTP id n71-v6mr7388330pfg.149.1526608747570; Thu, 17 May 2018 18:59:07 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id d15-v6sm10564908pfh.97.2018.05.17.18.59.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 18:59:07 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 18:57:54 -0700 Message-Id: <1526608674-12702-42-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526608674-12702-1-git-send-email-gvrose8192@gmail.com> References: <1526608674-12702-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 V2 41/41] erspan: fix invalid erspan version. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: William Tu ERSPAN only support version 1 and 2. When packets send to an erspan device which does not have proper version number set, drop the packet. In real case, we observe multicast packets sent to the erspan pernet device, erspan0, which does not have erspan version configured. Reported-by: Greg Rose Signed-off-by: William Tu --- datapath/linux/compat/ip_gre.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 9240ab2..484a890 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -1006,10 +1006,12 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, erspan_build_header(skb, ntohl(tunnel->parms.o_key), tunnel->index, truncate, true); - else + else if (tunnel->erspan_ver == 2) erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), tunnel->dir, tunnel->hwid, truncate, true); + else + goto free_skb; tunnel->parms.o_flags &= ~TUNNEL_KEY; __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));