From patchwork Thu May 17 21:14: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: 915773 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="UO7eCjwI"; 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 40n3y13gc5z9s33 for ; Fri, 18 May 2018 07:16:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 50F41E04; Thu, 17 May 2018 21:15: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 3EC0ADB4 for ; Thu, 17 May 2018 21:15:40 +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 CF3886A3 for ; Thu, 17 May 2018 21:15:38 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id c19-v6so3273290pls.6 for ; Thu, 17 May 2018 14:15: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=iYOSj8PEEuNe50fP3PddKF9HVz/hjRJf8qZkd0VME+I=; b=UO7eCjwIEHB1jM9Z9LsELKizkWYUHiqG6S6REnaoH/fx+/0VjEa/Yqf15rAP1U7Rb/ rgM0/dM7TdmVAj6G28dcqTrnsJSChk6uWWzyMlKhDL0OyndSXDt2k+cZlqp7P7jx1yQU uXjRD5PG1Znu5e1IgXB6l00RofGMGUzRoUlHFlJNHLYFXXZsaMBaZHDHByc77bAEXsqm 3ShiNqsJGnu0yKwvqDX/l0LgfN42xrTU0UT1RitpwDlIo+NdIZZ5Oxa+ldUolQNrs3Zm b7Ps4qxsNrZzQnfkSPyHGdOw2RundUzqqK7LOYzeWsm6muB1PqDvMqOz8CwPvHaPQOP4 6e9g== 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=k34NkDl5VWTI1f2i3JIHu934ZAG05Twu6aikvH21yaYXjtwwuPKuwaAsRxv4ABicXl 3r2M0/YlY67FkgZSSvUcFsDIbGiD0nDHJv/eRYXlxD10zFPGmP5m/0r6BmFnzWFLL5Ja LVjd2jPpruKTYFeKLKs6b++PXn4h+wid/TG/pj8G4FiW1Voq9w2olvh5/vtljcxDRa/V QjKCCsISkYB7Jyt72OAwxL86GGWHxkspmXyAiF5GHZ7gfNrzUynN8cC9fDflhtesJIhW EO9G3M51YqeELAwdCW7tZA2WP4Ui+x34xBSGjfro3dLPbBP7peUVcTYKBrVeiHN0eTKD Jx+A== X-Gm-Message-State: ALKqPwdRgy9j3iC4eQ2kj0ujVsDLlG6LcMEm38gRAZQt9Uze7eIfGSVd ++CAe1EIjq4BDsMz2Hhdc6P/2w== X-Google-Smtp-Source: AB8JxZp+wIZGBxJp82QGLUK6yrO8Cnl1AkdhvbLnCgmBZjThlH1zJ1b3yISVaJmSensTPOv9WoTkUA== X-Received: by 2002:a17:902:b788:: with SMTP id e8-v6mr6755650pls.263.1526591737907; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:37 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:53 -0700 Message-Id: <1526591733-4450-2-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 01/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 Thu May 17 21:14: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: 915784 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="ier/1lbB"; 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 40n41x6m9sz9s37 for ; Fri, 18 May 2018 07:19:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 84764E74; Thu, 17 May 2018 21:15:55 +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 C5FEDE3C for ; Thu, 17 May 2018 21:15:45 +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 6B96A6CF for ; Thu, 17 May 2018 21:15:41 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id bi12-v6so3257522plb.12 for ; Thu, 17 May 2018 14:15:41 -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=ier/1lbBCxvv9GPMEJX84qDqfIn5X9OZOurETSqlSunNarg3VKb2hXRLUcLmhkwkbf b23gzaYg/7lwyNGMBj8VsyokI7lPy+TYK/UUxcH24qnBWy/saXNj7SgO9uaAzSxR01Wj 6Q4YoL945kWEVCiKvi7aVfXzj4iNgfaLJIBPI08EfEp8tEfVDQGl9O2BVrQskhs1ClWo e9/cl/RK3q7N/juwEwYxtIHBT/wRjUVff17z3hPPPFteGT66a5E9Iepph1vcD7D4VrNu h4SqRAoWcIsy/mWdwmOUJ6kl7jo7eeK9BZxJQrgiJTDXXg3wx4uRoaSnh+eFRqLw6R8Z tSQA== 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=Y+M61ALI257248zyE06c87AKDlDkxKPkSGeZAjQ7h0Nnc0/cyCsJk7/p8AA0c3yJ37 dO2QW3cFPpNmwQIX1Ivm8VVMTxkIZwgkHYESJdfnQCK3g46JlZuylKRE5bGIhD3T0p8F UTOS7hu+9NoatiSpPlPD7QjZdKY3J5Zo0mUovO16o3XURV5HJwsYim9kJdIaJvjNQuaw wShzPRw2WUwBbY6wx+e7LjpaB0/Xpt3FiGr4BQF9muP99eJBAugFxxSOwrs/o6exALK8 ZkyOuLE09/iLQR+649WKRO69XN1GTzW5cE/42r+ebhcGmiThIIc3ubZABX4VLpaB8LLJ 606w== X-Gm-Message-State: ALKqPwc+uO6VKFUvToon6nKbPeEoftI9Ol0MOH/iP7wX+F+yyrBU+kB0 BNt4z50h6WYAYTicyPOwE6cpWA== X-Google-Smtp-Source: AB8JxZqbD2s35O9gTkO6gPNb2MMhdUYZUaiuROp2+FXoUcgVbCsxfmBzWKsz0XOAk9Xm2wam2P1R8g== X-Received: by 2002:a17:902:4483:: with SMTP id l3-v6mr6767584pld.282.1526591739335; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:38 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:54 -0700 Message-Id: <1526591733-4450-3-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 02/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 Thu May 17 21:14:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915774 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="eQanuQIF"; 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 40n3yk1FZcz9s33 for ; Fri, 18 May 2018 07:16:46 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 25759DDE; Thu, 17 May 2018 21:15:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 497D1DCA for ; Thu, 17 May 2018 21:15:41 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f45.google.com (mail-pl0-f45.google.com [209.85.160.45]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id CCE3B6CF for ; Thu, 17 May 2018 21:15:40 +0000 (UTC) Received: by mail-pl0-f45.google.com with SMTP id t12-v6so3270836plo.7 for ; Thu, 17 May 2018 14:15:40 -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=eQanuQIFfcHEYa6maD5x69VOnX3Elp4E8kZjsG6Qou9wX9qwlQzhn3Lt2leFK9zppA sUXu5ivoLUuHzKVTitIJ7AnYTS7zDDl82/AO6EtKcnhEIhZhmoc9NPw8BIejzexKEDQl mW7VZSZjlTquGIWwgs/+krLTxvRKLGzk6kLKGO0mZoxDRh8JemqQLiNdSPl+r9+/J/pM c7A8exOiKjYAT3cnLA8idXJ48HiFqv/LC8HBnvP+edkthqm4dyj8uFFnD2TPRpVs9lGg giPFITkxubdLYx1tVAgJF5fK54iAlq1OHxJ67DAFj+4/yUKxSzsAWy9G+d0vkaBN9TQF hBrA== 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=HLTNhKjcnpirHdy4hy60HYl7qBB9viuik2ieeFwcM72GK8nxay2lhaZdOnRegmqPNq bqr3HsibS31DHxn7UUuGNI75A4nGyLP7/Qi9KlYfY4CVbM2HudXQ6Fx5CgM42LVO4vw1 y/QuKTlBO7zay7mz5ZB4gIHLpZsF4VAJ7Dfth1nuuHor87Kp2zysEXoqDzDpjfQGV7SP oxY+0zGONjHxdqFsSQFOZZ4UjUuV9SNk/C2XT+JOHgp7hu+wUapUKFOSzoBv94IdRuKb hIJGQ9w78nDW/ybQlIO3J8f5tUiQs2sNiYPpEglkEMUUVWsdrnMZsjp3SElC6Zy7/FKb +x1g== X-Gm-Message-State: ALKqPweBkhg38hCfMiTj3E47eKeJXQHD/boL7XuKYMd5EVdHaZTUxaBW 7hhT6xD++9FB2yhOeVQ2mGbAkQ== X-Google-Smtp-Source: AB8JxZrbzW0v8GzGziNiw3+Bw25kvWWBR9jIBw+A1ahLm1QXp3RopBmfBfbeeM8fvJNI3DYt+yfHXA== X-Received: by 2002:a17:902:4303:: with SMTP id i3-v6mr6854679pld.394.1526591740177; Thu, 17 May 2018 14:15:40 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.15.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:39 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:55 -0700 Message-Id: <1526591733-4450-4-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 03/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 Thu May 17 21:14:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915778 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="c72ZL5ov"; 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 40n3zF5vDPz9s33 for ; Fri, 18 May 2018 07:17:13 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 51377E36; Thu, 17 May 2018 21:15: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 4A021DB6 for ; Thu, 17 May 2018 21:15:42 +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 008056A3 for ; Thu, 17 May 2018 21:15:41 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id c19-v6so3273359pls.6 for ; Thu, 17 May 2018 14:15:41 -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=c72ZL5ovkAD8udzuhSyuij6cLLlVqCVrDoQwO3ZdN7eywD+wkOU7GnN/mYNRn7efxb jlqzUN1w2M9xrW9XbJ2I4/0hqdjaca3NoLu63xUzrYjHPXcCHvMya3YZ/0PMpHCugURn +Ayol1NNrxvNx2q7Nd4DVEnbGYn+KLxn5Xo5CUrvjb+kiZ1t/Y4a6voHnxSjddnYtMt4 0RXc9FIbDKbZWvRjhUv+wHj5FglQsrKZiox+h1Yf1Hdt1FEk02psIo+fUoMANjazLhuq bc2wT29247gg8N+buIDJqR7XaFB+SPfV3GYzNx4BqGyZiS5DqmJxP5o73Zo70ryOil5l gl7g== 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=R5VwrOHsmDabDXb4VN+DRznLTCWpsDjBvAQs7g3p+3NSKjzTxlzijGVZebr/xDnot9 NK7+TLSMC/K/80hiKNc9FYoa6ccXzi/mhEBErrYOJdYoSIGOT78AG7ncsEOm7pZpM2OW +j+XFh/+ML37GD1CJEWdwDlnMeLv+cYQPQfCkH1NZHqr2pwhUZNj0EZWW/I0ffykkd+5 2J7/Qm5EB4TEL4J3vcazRE2TBEvfI1HdwMrDkrkhQx8lnKfenKo5dQgp0DC7xmFqU534 q+eLkTYR2ihEXAssRJRWpyWaah0OY53iTXKGBaAOCvV6iUJ0VgX9VnSZ7L9uRTp5P5p4 rPgA== X-Gm-Message-State: ALKqPwcGVDTVj5jgjq1cjFtnXPSOdEhq5xKWpumqF9DQJEVABueH6A28 fd4gJYyld+4xKa7TFt0oqHQYuQ== X-Google-Smtp-Source: AB8JxZr/Brp0/1tMpfKLTC0ZtUMKnzMsE/9I8aqjSnRLA3l6Yg50PjAhP6vWUvYEDkhTS6AEtNX7dw== X-Received: by 2002:a17:902:4081:: with SMTP id c1-v6mr6750721pld.60.1526591741376; Thu, 17 May 2018 14:15:41 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.15.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:40 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:56 -0700 Message-Id: <1526591733-4450-5-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 04/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 Thu May 17 21:14:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915779 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="PzPckW85"; 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 40n3zm1Wlqz9s33 for ; Fri, 18 May 2018 07:17:40 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 15C3FDC0; Thu, 17 May 2018 21:15: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 6D06DDB6 for ; Thu, 17 May 2018 21:15:43 +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 EB5566A3 for ; Thu, 17 May 2018 21:15:42 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id c11-v6so3276491plr.5 for ; Thu, 17 May 2018 14:15:42 -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=PzPckW85xIovaPu5HJk6M8B0vrjJ4aupwNQmTHI7STt6g1nh2EqPVdsvP4gevaqSRu XZ7tgq/BYO16Z7x88HjLB2s/78jfpBnZkM6H8HjgNVRVYxjwXom8MC+uxEIW1R+pWI3S Vbi6VrG3hX0Kl4x2zb45VHTjJ9u9IcrmqHVRtWYAibz+vZCf8IEAD5Jh+kme4tdZsuqJ +yCWEXSS0GPbeaZBs9ndR9uVain3RUGJ+GzGFRnFI3jzemm80AlAHeHnl7jHKIJcUL+H XnVr694vDa7evfpC+0WZcS9a5hddvAL8ERDzzsl3BVpT4v21T2j9CuckKhOHv1P8NlsP wqUQ== 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=Ci4M0p2uR/tMaHfmGmCb/3uPP5XUlTL4koJ2rOtO6mH2bOostJvHJ3Za4EUQo9RxuI f9gx5BXreGb+y2GP4R0tpxuljoI6hjzUFJ7ZSmGVb5AtgzclVLgkqDoJ1X7vetvfBv8n AfnFYAhLDEIEouHNte+uWoa5sKji7eh8rY9eUBeNhSXYSHzFiUMIMJ4LG5CgGVVsCK70 K8zK4dwp/RAWdKiu+FI8J4VsRMoa6M8GqxUZhIT5zXvk2yvILBoF6mtzQqnHUZo4otkT F0eab+yb35ZDJXkEavaSR0pZjAsnbR7vopNdsuWvoZVBBxF045AP+jNsHYs6Zrsp8tcI K1+g== X-Gm-Message-State: ALKqPwdsLh++8uhgZfPSnxilEGQZXG6WBBamucIY36lzJNM3s980YTE6 vsoDrT+JgbzzKSA+s4aVDnCcCw== X-Google-Smtp-Source: AB8JxZphPLKMpEMoGnzlr9RXDj3tU2cbAzMMkgSy594vTTJtTdDneugXAgseJF0wsQmFvp38gY4UrQ== X-Received: by 2002:a17:902:7e05:: with SMTP id b5-v6mr6546226plm.230.1526591742259; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:41 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:57 -0700 Message-Id: <1526591733-4450-6-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 05/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 Thu May 17 21:14:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915780 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="frYWH47G"; 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 40n40J1Fj5z9s33 for ; Fri, 18 May 2018 07:18:08 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E25F1E57; Thu, 17 May 2018 21:15:49 +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 328C6DDE for ; Thu, 17 May 2018 21:15:44 +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 C105C6A3 for ; Thu, 17 May 2018 21:15:43 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id e6-v6so3259284plt.11 for ; Thu, 17 May 2018 14:15:43 -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=frYWH47Gv7ckhVHbG+frFc5XNC7TlL65w+58nYNbCelyD0e9Ngm7o7rfW+Nu6WhYWO VOznnj9PeNw18lL66sjnoZj/6D1T2tidTdhWtP0Avwo4k0h8Iqv1BMWU33Ih8/HetchA mD/cfdZPbfdzQRo8wThjL64AU89l/4FQDgTak+j2MwL/0b2MsvYDyqTWsQbzFi5y5Fb1 3WNXVRnWmi+Hb7ClLH+kMrSGATCxn4VfjYZ4WiQZqnfyuXtrQmT+421v4zW456/J/KCJ 1KehxQ6UGVcwJ2O9+gpbo9BZV6ybzTWBXrOyk67VgC1IlwJLd3WdA+hY8WEkSQKbHCGW bG7g== 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=d2HwGWyH8xtI+8U7AKRVmHxu0I7E+iVON4SsRW5fka5gbkb04IPBomxcPtWRQSCqjk BbCa/OghVVLcac5TP2I4OhHC/rd9sJ1IGDnrRg+35FeeypazDA1p+FC4XWKGWiJFpoeF mZBT3onEC2sC9EYXUb8OFtpm2wlr5FWKlL2tCMzYIUthgmxiF2L3pSODO8AlHvOm1Tow 67hhMPn0WbgYfOqFaunwrBwrYGB8yqUEokH+eQBc63ZfuhgjzKj2guvJpuD8lAZo3zs0 Nx4Pxdr9zEqNxlJH0B3u93vZHu9RrCCixFWHTzZnEq++QknDY3T13Rjgo7/NFiiMJoE/ QYKg== X-Gm-Message-State: ALKqPwd2UuX1s0l5SHaIw8uU1yRgePojLYbIthOPnmQ4D8sfNNzCvro0 ozpBbZx7aMjJuxVwG5gsYP8RFQ== X-Google-Smtp-Source: AB8JxZp3yWhGQcYUTg2K0/dnwgM6F7mxjp22HKZH58TxUjk0Mm0tlgCkQyY7kDAfe4GhmqzNRJhMiA== X-Received: by 2002:a17:902:c5:: with SMTP id a63-v6mr6719514pla.149.1526591743089; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:42 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:58 -0700 Message-Id: <1526591733-4450-7-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 06/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 Thu May 17 21:14:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915782 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="grCBSHIS"; 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 40n40t1V5nz9s33 for ; Fri, 18 May 2018 07:18:38 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B4D64E24; Thu, 17 May 2018 21:15: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 CE8D3E1F for ; Thu, 17 May 2018 21:15:44 +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 97C5C6A3 for ; Thu, 17 May 2018 21:15:44 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id w19-v6so3272009plq.4 for ; Thu, 17 May 2018 14:15: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=+4gwZ/YT8fTkXmnFJi/mh4xs6by5eXesmR5SjzufJb0=; b=grCBSHIS3kfz/TASu0uaArTWVskopBCwVr9nvRQ8lbaq0T8eohfHF3Sq7VPM1wWTci Jz05C8Jm+jPBgpPRtqvYrYKsQUoGgsO5CPEKR+6AyKHx60BKu8zbCK69Ulpy4ex49BBA JtG4Izab6qqLBxOKEICKua4eUJvAUSmAB19J/a+oEWUUm7di0WykhatQfC6iemg6lN2+ mgoIPU7EWanHCn95PxLO5NT7czqVAS8VV2LAk+P2qj9HwfLAum8aLxYwewSAnsMFQ1NV cgtyIcim3McfroxzIYt0MEHemZCUhczBasi8sYxxU+WTbwIzc6ZhEMerWfst3f+m4dbC ROgQ== 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=Wi6JYOEyXBR1UdvI3pPBwww+SOoI5bQrrK1xQufmkxMvI/+Rzg4NshB+huoCkjI7gH 9bDI40C4KS3P2DibP42wIZwi1qw7YDk/O5kWPKlp9cr1QwvkOjh/Z2o9zyAq7Ro81k+f enjsgPAGe3m9rEiGLnE6geF0OHd1BZr5kZ1UScdRyrMjA/akwd2kxqK9kBAPOZSDjzMq n9KDPaJFMQk/01wjwwW1AxB3HBZ+kLc0eeqQWB5VZZSSXHyTwUEjAgvAoa/dbzwfrcgY yoOeTwxSiPUFKlqaJeyN56PqSbYJtTOFLM0Pe31U3DZERIO++uNzgUblcqodj402QVxO cpSA== X-Gm-Message-State: ALKqPwc6y+EU+zV9DvKmRCO8rIZNirY5dTO9o8RoqB0AEN+BFhZLIo1h D5sLiyIR7cuKx4uK4OlMRzQE3w== X-Google-Smtp-Source: AB8JxZpm3Z+qSK1kbgoNh4/oX9UixxGCVNM2d4b551v95IKk5kWKuqmVvILlqpbmaqXjnoL/L2pLBg== X-Received: by 2002:a17:902:9a4c:: with SMTP id x12-v6mr6537430plv.213.1526591743993; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:43 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:14:59 -0700 Message-Id: <1526591733-4450-8-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH 07/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 Thu May 17 21:15:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915783 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="Axws3NeV"; 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 40n41Q26cWz9s33 for ; Fri, 18 May 2018 07:19:06 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1AAA0E92; Thu, 17 May 2018 21:15: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 D01F9E41 for ; Thu, 17 May 2018 21:15:45 +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 92ED06D2 for ; Thu, 17 May 2018 21:15:45 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id c11-v6so3276557plr.5 for ; Thu, 17 May 2018 14:15: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=DAP8s1FTQPQd2Sl1OV9NRPCXD6MxrYhzc5r6pMbggc8=; b=Axws3NeV9AA2QNwFh3OdTmyfE6fJUtvOr0C3hXTVLUhCboLKQRF2fD2c7ESiqjMAd+ K8CMkg/onjznBgMuWEJWy5bjKEGL1z5iWwMQE1LqIfmbrLUTkY6SFmXs9LC3BYT3v0HG VKJNBfyYCUbFl+K4s+Dczz/XpO+QrNtM77gqRuZueXUUa/H87f6bPPk+qCzkOnGmEYC6 D5fbdVF9f8RCYOoBzMLdXavLtB7azYLRX4CtqCYOO5ekU5wiVgaZm24wbg5a2NewTCgn YkpvDPCzaGNv5DhiYcVUv8jcLuYOrDb9AqEyIcOdR5RQBhyyu9xY/lYXP2JtrxVJbZhP OAdg== 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=ShtwHWxlutjtkirkaEVeUBdhcE7wz0uRIpKwr6/Gj6yCkgZP1nEINhBQe5+LdUBf78 dfeQYDD5LXBxStiftQMxkXbShvExoFYPvHht/i3gdo9haTSjCnCQUx1VF4LgiVxBdSHj sEbD+D31WupsfvaqoUTfvh5Afa49GCltWtItQJZc8+bmlFdLLkd8UJQ5bOKCCTnNii1N OXk4tkzSxesahnzvxFcOBjnB4kgizH6uy7sooZufPl4B8qmQ3Un73y0/4IkXWUWptg9x OSZpSMJ0DcfZQ/N9zg2yFS8Qyxh4nwfAz39WIfuYw8UnSp6PFUbWS/WlVnMLx1nlW6ta 3zcw== X-Gm-Message-State: ALKqPwey5TltAz8/hqPTj4uJBAPWEP85VR+Sggood9uMcC61LkH+zo6C jSYStgPqbGCr7m0a5LUZKD7DEQ== X-Google-Smtp-Source: AB8JxZobcq2hmhWW0FJDLYXXhEevUJ2PxnBaY6C1Bt4stOpi4x4kQehNbhdHJkCrX8ns/oJnHnDaBg== X-Received: by 2002:a17:902:6a85:: with SMTP id n5-v6mr6663392plk.288.1526591744956; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:44 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:00 -0700 Message-Id: <1526591733-4450-9-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH 08/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 Thu May 17 21:15:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915785 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="d6lUq8UX"; 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 40n42X5GBQz9s33 for ; Fri, 18 May 2018 07:20:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0D34FE9F; Thu, 17 May 2018 21:15: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 B7569DC0 for ; Thu, 17 May 2018 21:15:46 +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 7E82E6DC for ; Thu, 17 May 2018 21:15:46 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id t12-v6so3270972plo.7 for ; Thu, 17 May 2018 14:15:46 -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=d6lUq8UXkUNeZzzg4S5jJ1Q3lE2vYarKouMCy+s1JMn0EUPy3+ubR3fgLPSOh4DQc3 xV8wgrWH/kKjfeuVLSJOSIgGkt3BGXyWhs0MkXxqJLC0ayGnCJ4nD8FVohp8SMXLo9G0 eX1YyfMGu2RVYyBl91RHzDZcfn31ZB3kfRlxWh3VOGRLg0joeD9ulsvThOx3jnaKNgQD 5ldgfkt2ZMzkkr+wxNd8CyT3LKQ3FiHqWOEl4AUN9UyItohHtDH8KOXhvp/NOnQetHxv kkQoJXzIwzhzV00Nbt4rz2Z3Ms5ez84tiTjt3jYKUGn4xKT8lkAhgSxARvyq1gCM2hAC ZTpg== 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=uYxSYRRVzHSDYKjj0ljB15S5RC6jumWESbv1VzJLYv+A9C0nMbL/i0TyyK27DmbStH 5/LCacGMwahbmmOuyHdXFEJK6LNRG517zUAcFWSUW2SsH6pqcj3DCCKr2A5oTYWDuSSD AIpaVWR4FCS32ztqk7l9u2Ctwg5TRHh+wlbl7Ig1Untm4bfazwgul5+bI8haMxhnQeZm Ym6aUxtDoWX15RoIcxd9eDsxlQXDkGNkHaz0YDw6UlcR3EjwYLILYJ8TT6v8ektIwySY JAeIREJrG0ohrXbU+jw9VpQwnlAKorg1hE1Gj8NxjrYgCctQyvLzKd6A0SNesB+kRlC9 X/uA== X-Gm-Message-State: ALKqPwcBO8hYtYiCvjd8C95HtEO1/eBVt/dPymobm9pGhwTLewrt/hUu flW7vB4jlpsnoBopbM3gstTinw== X-Google-Smtp-Source: AB8JxZo1M8aNuXS0mOrag9+w579ekyZAXvA6vcI1Mx3y8LVlTBJGUPkkO15roGGZ8li7mK3TNCPmQA== X-Received: by 2002:a17:902:9304:: with SMTP id bc4-v6mr6694751plb.189.1526591745849; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:45 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:01 -0700 Message-Id: <1526591733-4450-10-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Xin Long Subject: [ovs-dev] [PATCH 09/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 Thu May 17 21:15:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915787 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="WALolHUA"; 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 40n43h2bCKz9s33 for ; Fri, 18 May 2018 07:21:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B1867EB4; Thu, 17 May 2018 21:15: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 B6F42E4D for ; Thu, 17 May 2018 21:15:47 +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 435B26CF for ; Thu, 17 May 2018 21:15:47 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id c11-v6so3276593plr.5 for ; Thu, 17 May 2018 14:15: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=babftoUnK0pk26h1AJsGLjEqIvzFlZ3FZ7vywR6MyU0=; b=WALolHUAJlHGitbAmgcPDDnLAlU/IQEyZpd09nCui/kgj3V/yWBrVU5rrCgM3s1VV9 6Dx/f6P8Kwp0pMHfo2lh91j6R074VrbCRjXQ5YRI6XYLLcwYRnOWpsNuvrxKpPdDMYqz JCZxW7dyrco+D6EnNSZEJU0PzA1QyWWkRpZTtp2Chp04yi0TQ0atOJXhJ08WjFqh4Tcq vmXy7Bb6xKJ3iFcabI2i4jVF7qILLEpIYecJxFdVn/NuCXRWnz+iF93kwa00Vh7QPHqJ 5qPqqC5jFN09nAdLFcIpKk12e2clwz6nBcNeEbivuuVWMjPmsek9TwdQw/l+r7vs8gpp PdDw== 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=LNZ5JTwsWjY2ytdGBjiV9Pbp6jh/ClzsRz0psQGZ1Jrbp0B+mnHsiHBoygIUrs56gX wSH+4j9N3TBOwK5CmOg7H3F795DuMWsPXSJaMu17cA1H3Vdw5G3SnYOO6bPFCu1KrDsL LbgmjgKHrqXBLmZDVkpy7jWixyyf5ECSaH0keAkCkzrckx7wolwUMMgVN8k1WkjgzSyW 5j29L8h1nYNwBZ4va+qPmjwSjaqajANbdehV07ifTDGyPdDMcuIvdu2z5rUcHM3zg/lU atKbPrYG6Od87Jo71IrYjQvr0nAn+q1XKh/7+7F9JAY54jKhKHlVuDNXYWsHSEQA2ydb NEuw== X-Gm-Message-State: ALKqPwd9ad2BKngHeh7HJjCqLZzHVHFqD0Dd9BOVEasjPSERquDtMKNo Bj1jHwuWa4JJ2qU4UjlWLSZ5aw== X-Google-Smtp-Source: AB8JxZo3at1kqXx9E3kZpRKD2/zDFOiThxAvcNqOPKw9wB8M6MVxxCP/v+W9VemKwLHWiKp/jK9AwA== X-Received: by 2002:a17:902:b946:: with SMTP id h6-v6mr6876915pls.3.1526591746637; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:46 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:02 -0700 Message-Id: <1526591733-4450-11-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 10/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 Thu May 17 21:15:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915786 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="JO70nJwX"; 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 40n4353t7kz9s33 for ; Fri, 18 May 2018 07:20:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 74A5FE73; Thu, 17 May 2018 21:15: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 65AE8E56 for ; Thu, 17 May 2018 21:15:48 +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 12D1F6CF for ; Thu, 17 May 2018 21:15:48 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id bi12-v6so3257654plb.12 for ; Thu, 17 May 2018 14:15: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=VZz/zuNPtgeUnXbCsL0xG7uI3C3TsChxgcO2OJIDHk0=; b=JO70nJwXSzg2uHrnh+T82pOQefYljR05INqfNFI9dualjX0hnvuCT/S1ZL7llaTCwQ 2k7/XmpwBHwQGHXLnVqWz1jKSy0d8lU8jd6Q9EIClcyQ4PAL7poFC/DAjZsGGSXezWEb 6yQwdm9tsDYvk1O+QP8tAMp4+DBh5r7OAxOKAmgCxRDT4/B+zEazojmcgfss8Cfi9Lw7 5CsSUtYLsfBeqUNNLY7WPDjq887ZIhXWH/P0iEOuWYvVayv3BGxWX23RPtON+RuAEVQG 0S2pTot9KhFawbzIdWWKKPyn5rPzJ8S/pjnvYizMWw1vnT0uOaZ2s1PXdd7bmzrNosS2 A/kg== 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=QvLgWD2Gx6wQvSd6JkOP02DBUQG8IYbMCv8tuA4SbrTm6HKlbt0rNAkJlOOvFGc5Gd 7bJUnaJ8phis0zVZsX+JLrYZfS/UevHahkqfYhIMWbeYHOMAIUhoJPcN8X65ovs1Wxsy gJqi/3xAtaS2gU1ygCVSSgyWH+YECTnLgTgzUuuujPSu8Sb7SaXaP/jTUJ1T0Ynx2ovA 8MYj4sbaC5loAgX85EH3KxsRSZSkpYOallixHm6y1MHN0LcSMXiKJMA1kiTshI+5+Hc2 65RswPhGBAGMeSNJj+bDfTgrGHTf+GWpthA2bn5LNuxSyH+T47K0kqtXc6au1MXjojtT eytg== X-Gm-Message-State: ALKqPwf6v4/CX/d9TrM2FIaJydvhZ4x1heGFrG18KXVXN3Pp44u4OXCU VMPtGkCl8wd2GEO59MqOXl6qqQ== X-Google-Smtp-Source: AB8JxZoUQoVftJwLh7GyiNXqu3s159/OGFT1RZzEAxIdXxAX5pOW6HTcUk2uWUpt8n2ThuvHBsHp3Q== X-Received: by 2002:a17:902:547:: with SMTP id 65-v6mr6838000plf.388.1526591747474; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:47 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:03 -0700 Message-Id: <1526591733-4450-12-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 11/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 Thu May 17 21:15:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915788 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="ucFLa2up"; 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 40n4444bZTz9s33 for ; Fri, 18 May 2018 07:21:24 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0BEE9EB7; Thu, 17 May 2018 21:16:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 27FE7E61 for ; Thu, 17 May 2018 21:15:50 +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 2B1806CF for ; Thu, 17 May 2018 21:15:49 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id e6-v6so3259389plt.11 for ; Thu, 17 May 2018 14:15:49 -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=ucFLa2upBsPjII+JxcbkzEOECwikWbHDzVjAMVQPOEDahjuu5+CbRWVaUH6vKUSsXj dRTzcps0eQV5jUDAf3cbT5tOYJSMAkN1K5nyOYLwUF6bAGROwWf4E/PYPVmnpvxZeuI3 Zn4hUkVHxXh06k/rVkACUJ22H9p9/7WzXvAnw3EqIy3du0fpCcSfodbn+OF60GHnXiPm /MY3DjBuaN7aJM+Y0HV0Zk08uekFdEGC6yzC5iaL6CJLysNzVzdpIKClkYoDAm4Pprjz QJGbuLvGTgc+CmxW+TPQX68/9J3FoC3K1eMav/ur7HlQQRF803u7tL+/dz86WTe3BKq0 UfpQ== 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=ITIVTgdSV47bxRJQyA8NhVtB1VJte2HFnTNjLcb5R4wK43DdXfrYyGkkzaG04fYw3T xceEG5i/HVvBgu309UgKct/+GuZA5DkjuhGilzYAVADsEBAUbtK4ymPRV9kakxAoQ8kn 1RNm4DHoZeqJSU5hjv3imhNYBkllARRWddXgjGbu+okiLsfepgiSno7be5hdJg3s90Bs hD7xWbObDMH783IcYzFQjmjd98dg1EWqAx/zslfnESdqWA8oxQQLUGXar0CYb9DsDESq AbHxmcPbSKeORJjtu0TslTjvqYCHB598MqBUHLy6VDz/XZbUIzGLXGZSQ9xtaWUTEI22 yYgA== X-Gm-Message-State: ALKqPwdKKCoMx34MJwJEOkrEo/+xCPYxclAfCTEGN1nQV1llUl25h9cw g99I5J1jWCNdBjpkeKoskdfVqQ== X-Google-Smtp-Source: AB8JxZodNxclpnScgP9WCYCYbpb/tmKoQpOUQBQGk6LaME7W0bKGtgtcZzAFQ0mwIbj8uMjAn5Cp2g== X-Received: by 2002:a17:902:1347:: with SMTP id r7-v6mr6640154ple.62.1526591748554; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:48 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:04 -0700 Message-Id: <1526591733-4450-13-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915789 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="Q3f2PaOU"; 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 40n44t3Rwkz9s33 for ; Fri, 18 May 2018 07:22:06 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 299F0E88; Thu, 17 May 2018 21:16: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 9F8FAE6B for ; Thu, 17 May 2018 21:15:50 +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 3BAEC6CF for ; Thu, 17 May 2018 21:15:50 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id ay10-v6so3278368plb.1 for ; Thu, 17 May 2018 14:15:50 -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=Q3f2PaOUGJNsbL+cLRviwvtvhGVJ6zPXNtBBKHBZygh1ea4Un5Xe0FLHGTPglmFAvV oy21YOtLbmHwGZv9DP+QhjYuCUz79rp5zcbm+uoAixNJzPhFeGvzu1+3iPJb7Fpxu/x/ PSSf2VuEczST7cr299xyDhtxmLK+sppr9seyRcCO8aH8+L30CxiFrM7DcCaq7j6mbWi0 35JDazVAfYFteXmusOihOVS8mtCQUacknZnzhxEkVhkYiE6xwoP9PIdqiJA3dNHz5hhz a9gpG4DtnRIP4kfY5InSJTvVdy3rg/oGlKn9YH7Py5v8HSRl6AaA2/1KWNX3L/3J6aoH 45ug== 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=Nzz2IobuNhe/sAwC0kFx6CnYLG51yoDDX5awVntmwVADHKFLOvOSHMM8s9mcW+EHCS iEqkRLD6kHhrFVv9e064epUJdy7MiAN7VJ9wSzXiB8BxNJE6os7DVZQCGCeBFADwTjpt plXek4my2q9CzCEEz/VogOzy6OJqRkC6sJYwEWrHk7nEMwSKPiIT7jqAyDmd5V34a4Pv O15Vj84TULuHQrQmGzQ99TBn+1pVPoNTnpXYQpDFSJHKTrV2OTgVMYVhbJjQ9WxOxXok 20FsfSh1YGJp6HyBa5dLIPqSufWVj7hDrhbm48ZD4uWdMepPuKUDIwD13Sv0o6mb4htD zdWQ== X-Gm-Message-State: ALKqPwcyS8gPdh59cJL2lC46TQv+EG6FAmbgCrzoRMdIJdefWbjTeumy eLpd1vtnjbymyHo9gbbDP1Ndkg== X-Google-Smtp-Source: AB8JxZpG/QYqG0XdT41PqGxg+drG4Vf/8g8h2VZ1LxvthpGGLbq7dXuwKREwW05zRaeYWFQWx2N8Xg== X-Received: by 2002:a17:902:6bc7:: with SMTP id m7-v6mr6503944plt.162.1526591749439; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:48 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:05 -0700 Message-Id: <1526591733-4450-14-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915790 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="Mh7bH2o3"; 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 40n45T0DR9z9s33 for ; Fri, 18 May 2018 07:22:37 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7BEEFEC9; Thu, 17 May 2018 21:16:03 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 36233E63 for ; Thu, 17 May 2018 21:15:51 +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 E9AE96D2 for ; Thu, 17 May 2018 21:15:50 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id ay10-v6so3278390plb.1 for ; Thu, 17 May 2018 14:15:50 -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=Mh7bH2o3aU4oX3WkBO/Sz1df1fL4oy1nc96l4TvEer2h3ET2XkSOXGJ2yfp0OwBY81 CKu0NWtdQCHo5baEYrHqBmGP9fLTZtNnuk6VqE+dUwHT81jkyOewsj3AmdUnSHzSCjDd dThznndgv9KxU1hLWs/Dl9gGHzqLHt+T0mba7XTX9KOZ0nw2T+qsz8+gzXYvbOTCJ0hl AIGLiehlKoZvruGrtW2vd9di2xQLpsSKanLLYuzRP7FEktSY/H+mVkw5xa0kSclBnD2b Whrvhwx4Y/4MMs0Cxx4JiA2NFeKvxxlJ868yX6QJeqkvCoFAbPARXfMLaK5Ijt2WqwHs nS0w== 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=KpCPXmPLNHVg0RzA93bp8Y6yzam9GFmd7dMudB97nHCugt188K7eIrN/fjwbOi+V0K 3Rty6qaD6nEzwH9TJvT5CPzIC2s2u1I68yVe34YgtgnD0GFWRdG1Y6yp5vbpCqJ6iRg2 PgUkcEUteYkfQNL1Iwpt6aqCQMC/SB8sVCxAnr7gcVNTAkwbPek68WJ856dj/7wgqGZO WrK2uo/VWLfQO18tK6xbG84Ph5Ktx22IrFZctMTXqzaVaoVr+yQFhuNqWq7erLbg0M/p 6gHDOPsI4JCBLVEYlNwxuMGngqXoHIiJh8nx11HyHvg08jrWpeezYmXXh5Glq17MJRfv B0YQ== X-Gm-Message-State: ALKqPwdor/RYTmfpclaevhBqKmbZ2euzzure6qWsWfr8IhTQ9IyH2Qho g4ZnYBouZ/8Bss/H+dKUJEWw/w== X-Google-Smtp-Source: AB8JxZoP+l2lqVbsCtzGtVMRsV+aFYrUPVCExhrbeec0zR9l1+YrHygBxdpQGfArcsJGEGHYc5xT2Q== X-Received: by 2002:a17:902:694b:: with SMTP id k11-v6mr6754720plt.334.1526591750284; Thu, 17 May 2018 14:15:50 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.15.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:49 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:06 -0700 Message-Id: <1526591733-4450-15-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915791 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="H6SR8k/z"; 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 40n4645npVz9s33 for ; Fri, 18 May 2018 07:23:08 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D0E32ED9; Thu, 17 May 2018 21:16: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 12564E59 for ; Thu, 17 May 2018 21:15:52 +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 D22E96DA for ; Thu, 17 May 2018 21:15:51 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id n10-v6so3272537plp.0 for ; Thu, 17 May 2018 14:15: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=HZK7C8YNQRG2Iqi/YKxcnbsTb2OFcwVj0I4V6oqEb7s=; b=H6SR8k/zNV8GCHmx6zNf6W3f+k+6dyu68mzrL3NzpIDlJD2j6Fiuw0lRiHitVyLC02 Ta0elR5saeZWiHs8hWLo1KYdEBMZtdOwgGGB4ke284UKJm/UzaG1w7+BMRdzXYR0xV1i txD9kXU3qxC7W4rmK2+HM5HJrSUB7/galDUo+nzfJON9mu9wBhHJYKj0s6wGq+KJZsym ev5mSkyIuZ9IwSU96YBqRQn329MyUALrT9wvxRBtU+sjAPUtALwQWO0hQqECDIPoO40O QMslYqNjcavlqADPpefZtHXZMdY6qF7cxfLNERKzfBo/kWMoMtfoufNqtaaJiyWVizzR Yj+Q== 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=ldGAh+YYAAGnTILCjV07teH4RgJvEwBmdFW3utxJhQO1OoOhPpcEkQnRDkTOslwns1 FxIC5uy1gd30UbrHfheLDtO64yFnzgokCSo7HJxq9TeT0uE/2CNmEhlHl3d8WGYvID23 7JMZY5DuOjbskQbWBJBC6ucFHgJ+iOrXirzUIkyk5k/Ztg1gg62K3PZ+RsiyX4tqSobN rf6d9R8LtArE8NhNPi5ubnsHr0XvUgWns/7bVo1JJ+Oe6bJwTGCeVdFmA9PwIAtJW/+H 9UJMu7CC4FeP2WDdpWEAB4dL3imBDUH3GawQEN6X+P+5L2bV64wlzT/LpL2wYfJdw+pN RnaQ== X-Gm-Message-State: ALKqPwfi/bP85se9vqphbDOaRZD/i7QSeOCK+CwnHST6Jz4AZDos9iJ9 fxiNoLi7LSUVHndIK9YbsURHyw== X-Google-Smtp-Source: AB8JxZpPnvDEmryt9dto9eir3gZ5Frm1BOLd1S0cAiqOVfMOQxSHtJY1OPRCeNA8GIQNHGa3neqpdA== X-Received: by 2002:a17:902:b788:: with SMTP id e8-v6mr6756395pls.263.1526591751223; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:50 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:07 -0700 Message-Id: <1526591733-4450-16-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915795 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="q91Umm+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 40n46h2kfsz9s33 for ; Fri, 18 May 2018 07:23:40 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3EA38EDE; Thu, 17 May 2018 21:16: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 11778E5E for ; Thu, 17 May 2018 21:15:53 +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 C33496EF for ; Thu, 17 May 2018 21:15:52 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id v24-v6so3275487plo.3 for ; Thu, 17 May 2018 14:15:52 -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=q91Umm+Pm++4np6xPNdPXGh1Q6N7hEsi8eDKOdfT7vBRLBjWroOh9o3e4kp63Hr2+4 Wkbvd/lo1KWKhasmFoe6YeT7g2u7IiPvbn3OCb4bi06P+8gkgYi4qBhxQbGwkgeqtkCf ic8ZJ/WtYDtyOpOvAh9bmW/EDtlBj6HfyuqB0UMK4ITFZF4zUq924MyPLTMNjvXAQope wCxwA/CMpVgrCi3N84kHKWWemR9PscAsiAc8w0fMsrpgNSYp4FO0Pv5qVE938XhQTECq 2l3PGUD2UWnUHSS2hQmm3vYOwcU4ntEaZWCFzxbm8IcIiAJ4Vt0t/Zj064qi8n5TbkFV lfNg== 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=R82Byaq41hDfWVn/0JHXKdBu/bWzBDyT8g6CJeqQhk6eCg829P+Bmi2F22evBMNHy+ ziQ0T3T/qwagJnZe9lrWZ2jqcpuhRU1L7nTKZHTx3SLYwF5WlaJUI5h5g12S7/r4KgFq 1DYHpznHdxf8DrzDmRYIcuJWO5FKZOhJbTutlPTKTflvMX03PgsM6Qsc6aTpvmOvU9DC x922WwTzu6/UzvSrFS58aqaI3zAEBQoDe5EWWc9QpI2VVvUNP/eLtqJ1bRkZ/JTXWofK zsKkbtiRevTs7Iqgfdfa434872u0yPtgnbduOhSAL+AKDxYMLxgR4OcwET1Ec+sMmLNw /l4w== X-Gm-Message-State: ALKqPwd1ycel7r7cKLBgsXxxYRYDyRmn1kGKe7sVvOQUnAqOlpOU4tJz 29oqSe4KXRg6XAX7TMHIXr/JlQ== X-Google-Smtp-Source: AB8JxZp8PmLnr4VIdJG3/X6ceeFA2Wrbm2Ex+d/HsfoRb2DNTxjdkZLHy2Kf2HARdTGYj4VNupTpew== X-Received: by 2002:a17:902:4303:: with SMTP id i3-v6mr6855335pld.394.1526591752053; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:51 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:08 -0700 Message-Id: <1526591733-4450-17-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915796 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="niat/yqp"; 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 40n47f1F53z9s3B for ; Fri, 18 May 2018 07:24:30 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4ABEAE9A; Thu, 17 May 2018 21:16: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 837ACE41 for ; Thu, 17 May 2018 21:15:54 +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 A81FB6A3 for ; Thu, 17 May 2018 21:15:53 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id v24-v6so3275504plo.3 for ; Thu, 17 May 2018 14:15: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=CmaZO21AUFpxKJpglNW4aNaKQGz/lP0ouLyKOF1IR/w=; b=niat/yqpsh5KUc83HzJERgoQmb1hNqtC50gWPJpMz9nxUQ8iXbcy0lyP7EzCgtQujh 7Nc9nZc3JgfScmJaZpqfKY3l3EOEc3FI6wY3GxQmUiN9KNb122HwD46KRewedn0OSALn qw0+l7/T0AvumhNG9PfjUEnjCujdqlY8R+vabKfOcCzSZmPTGMU7ppbW1olvVAW2e/2i Y7QqEjE5z6/1tLYf3k0uzuSX9Rfv/u9Gl0giLV3VZ1AupM/7zDm5SXxl4JHRRWBtJehd podoo1yHQf9dDMCYPYLu4jO7drBfrTtsbvV2NxUxWiSItW1+jx2jnXKenR62KlIcUrKi vn+g== 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=L1ouo1pkeFOSN50Hz5PrS4HbOUtJBftmtkHRb2LvHbW/agqx3a20umIcw2D6JKB4tG pt0AzLiEHxoV7fC8nFZ3J+1XlL8HknL3Xg3pqYAx9V4Vno2j2+SsABbvMkGfmbofwZPI yFG3/B1fESmXADP40/BI5OPEmi1Oj1oYYF4puVXmlyoHB+0JT4F+MAgVYsnDFxzlQK1Y kIUvEdycsp3rOl6aELou0DKrUXaaFyvjuVhLCo16tlL4EZ1HOWWrR3nrBErosk/WBcrt RRtQOQ/DSuFURzmRYbF9h3PZDnuQCNicq0C07Uy72aPq0OeSNoSUiU4XK9OQWFOOpluQ 1WGQ== X-Gm-Message-State: ALKqPweDRIfJynBRcSVvdns0K97USaV63V2DyHaZRXjwhalUNACTm5Ns PEkxoCqJhPcTKIAyn1doZAaAUw== X-Google-Smtp-Source: AB8JxZpRXOow+Z4ma3IQJyeuiYoMY1ogFm2o65C4VU+odv6DRIETbMSqj+nQnpk0+BdufEf47CkeXA== X-Received: by 2002:a17:902:781:: with SMTP id 1-v6mr6750489plj.150.1526591753004; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:52 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:09 -0700 Message-Id: <1526591733-4450-18-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915808 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="j6C7/GRL"; 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 40n4G14249z9s33 for ; Fri, 18 May 2018 07:30:01 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 95E68F92; Thu, 17 May 2018 21:16: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 AA6B2EE3 for ; Thu, 17 May 2018 21:16:06 +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 DC9026CF for ; Thu, 17 May 2018 21:15:57 +0000 (UTC) Received: by mail-pf0-f195.google.com with SMTP id p14-v6so2677373pfh.9 for ; Thu, 17 May 2018 14:15: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=rEEtHeNS2s/pe+otCSyfZQuo4ReZp/0R6IwqOWIZX6Y=; b=j6C7/GRLa0WaMeATLx9omP5XSDARfQvZRfuAjHzcpc1ZYg/wjmhA7ah5bW5S6/+IUH Uuc9szLS5lYzK8wAo6VtpZzuS29e2nywz67N1ihfhoxtYR8lkc3HYv2xyHIbmbg3gJGj 7eupzTas0M5BaP6sK9SPSzLaEKrzIR0FSHCW+QzqJGKErQaqdHaj1WhqW2k/KPOjDjLU XvMuXJf+2jp4p3t7TYvwB/Z97AMsGIv576EnpTi+GxvJirPGtrQlY2HAG6KKolnjsKK2 oBkqTfN1agQjlV3lkJn0chgPrkJfEDRQjYshRJnaYklFIV7XlfkZcZ3zdzZzH05gMRBo W/eA== 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=Yuv9/l1nfsNvmTKxTd71DHD6k6eKAAf8CM+HZzqQO8JczowBYFKZ+oh+mLhaptyqj8 mP2fTN/91nv/P6xRB5H/NPTtpgAUnh79hMzAccse2vkWDHnJgDVjmC3FptkbszKdoqto qAqH1O08HF6XR63IXX4R7Si1e3QcUwyAbBLBCLrhRIWpeI3QrlE6qp0wjjRQhyeCEU5I BXDP4W+lsV55LGQCxzcHNGcft/oZ2XF/bM/ERbws05W5+LktwipYwva18/g4q89x5T75 Hpkkx1WnsCarifq9Tl29TcarjkdMK3QDc8LaVdKNABHxK2DUDbxip0TTLhUAOLf6xTFQ AICA== X-Gm-Message-State: ALKqPwcYcXLKil4Nsa9PljdptGpVmz5qLcKSiyGkd4eSQVZ14z0/yLsq ycoLiY+PKiSmjhNde57lHBIZ+A== X-Google-Smtp-Source: AB8JxZpKkLflwhcprvx1AKXpH7hjVg7A1CBpScvXv/BtzJJjJqamfgc3aU2PTpIQIkjD7NC63Uxk4w== X-Received: by 2002:a63:7543:: with SMTP id f3-v6mr5296310pgn.256.1526591754670; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:54 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:10 -0700 Message-Id: <1526591733-4450-19-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915797 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="ke05AprV"; 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 40n4881BLSz9s33 for ; Fri, 18 May 2018 07:24:56 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0D504F24; Thu, 17 May 2018 21:16:15 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DF624E7E for ; Thu, 17 May 2018 21:15:56 +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 41E376D2 for ; Thu, 17 May 2018 21:15:56 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id p14-v6so2677344pfh.9 for ; Thu, 17 May 2018 14:15: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=QONi4bMB9a+QOmH5das6ahnsp7WJmQxwZ/R4O8w54oY=; b=ke05AprVQQjdVXMEYgVnIo252a4WkYEuKHN5GpbmW0DFvQ7Vvxv6yUrEeaDO+sHBcN 9hXg/S+F13ssNqMs+oupHbKGPDTc9lajiwViBJAHZnEfJKHQixROPUxV4LxGo/4ZMkco TJbMwUAk4DVqsIu/ZUv0kGvSt+hGD8J227SOPUz/aoclGAW+BXcqDWcuNNIeiN8/smvp yj8+wl+3/iLuAQxvQ64atz9e2WFr/iEa9iYmgeNC/yloJCy0iwpdYf5uKC+NTNt794+v LAc61agz2UnneErOMLS8F4ZdbFJVvf05ZqKMrPnym33EuGAIImCWQNeD0IGiaqn1FDWN nrSg== 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=iD0yoKb7/5n2eyoCRz4epBX0w3xInVv3pvnh41oKeRFQ1x0uaLUSRUg4+Jmv2nEWTe rSxgiLtRvdUSxECTEMOnhAR9mo0eZibZ1lCe7QHPabtD48FzSY1JnEBUUHSC3BCrproq PsKufBsnn3bxkRQ+XicqFLt9/ItnY/4juA7m85h24HaOwLV9jKkXsj1GICNw2EppBon5 yIRXU+jjTRwoMTe4ucg/OIXdJvWdCGh0e/TNK+W0juVA5EwvnkU66eRC9ubKiUbMkRYc aOVvKYcSXLvPD/8tF/5Euf49a/X4l959I+QncSVbZEvUIQ6dT8C/iVjNhv3IlEIitmx+ XGrg== X-Gm-Message-State: ALKqPweM0Y1S91hLV4BiaD9Yvk/5hKTsWzLwRC/3eLWJx0NCs6MuhdcA ss7vdSeFmIcKdCZ1YYmE1pUbcg== X-Google-Smtp-Source: AB8JxZpcIDNcgc9HYd1Qbhwo4o6R6N9f31k9os1PNifg4lyMvNGmfU7GG/aoSClVv1hpfO+g4JXTRQ== X-Received: by 2002:a63:380e:: with SMTP id f14-v6mr5326570pga.242.1526591755480; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:55 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:11 -0700 Message-Id: <1526591733-4450-20-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 19/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 Thu May 17 21:15:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915798 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="V9icpBJE"; 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 40n48h6QJDz9s33 for ; Fri, 18 May 2018 07:25:24 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 88A64F3E; Thu, 17 May 2018 21:16:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 6EBE4E2A for ; Thu, 17 May 2018 21:15:57 +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 0D1A16CF for ; Thu, 17 May 2018 21:15:56 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id c22-v6so1683144pgn.11 for ; Thu, 17 May 2018 14:15: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=Ql5zHckoutwzkwrh+yOq+iYve1l5vcpvoK6Htq7JVWA=; b=V9icpBJENmHcdq3tspcfccHjaaHKU7ZOSNAh6YhLFXlyq346DPS14MnarS61+XUis1 NLMyTWWWhitWSDMnnCqOUDY9pI5GGxS/lpaA1jklhWkGwKtDFWyerbLa2leEG9n4bBIU 1erLP1sKyi9R57HeHnqbFww5B6hW/f6T3TCd6SBkOpKoIJQNLd7a6JLBCC/TPpjCdrgq Oi+x/2Kx7vrF48YeDtQIrVp+R/T2PbEYjPSKjV7Iypjkd1Jk1YMRoS3Ta7FG/xtndypq Hf0R6LKmEGAuF7zZ+HTVVJHyqdsOtayjS9blkBVSEwGp0W+veLp0Ql1yDhLTYUIpglqb VqvQ== 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=gBB/DwAgSfG1STLagmmSkIlP9rgmqj8ZWslaji2keJeRSykmd2z6uXD1+AhozfFGEV 3u7VB6yt0m3L2qQvzh3P7oSA7fyXtttdLMNrmOg7LJIo5Y/BglA6aQMp4yd0q3/AhzB4 svzCMu44AyCHAW6AAPxXaFmr8O0k4khlqu7BSRnnzWWmwOhuVx3lvQbmbHEwUFzhjgWm 4pyHkLiP2c2vom9fyJU3EvBHtM8U3ByUn4rMl7ebjXHvUxBDeeKYM+dZQ0bN+454wuae 5UXKDNJ4QdoZ1SOs2o4Mzq0uoGIla1hjoeXm30bARP46911BC7jcqR9rKMCbBRvF+5m1 L2iQ== X-Gm-Message-State: ALKqPweOEq4Tb71hidLfuOjVMMJP2i965h01OK41RXcvuNpGSYlp4ISL kcvU58L7eaWARjj3i5MTs4fWcg== X-Google-Smtp-Source: AB8JxZp72ZBHJIfHPf7B9H//YmgZ699qsbs37Aoivw4DYO3z5ig+YcXEdCrrofiun+hy963VbCNKuw== X-Received: by 2002:a62:4b16:: with SMTP id y22-v6mr6623571pfa.29.1526591756386; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:55 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:12 -0700 Message-Id: <1526591733-4450-21-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 20/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 Thu May 17 21:15:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 915799 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="dyBdIor+"; 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 40n49C0YgRz9s33 for ; Fri, 18 May 2018 07:25:50 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CF34BE95; Thu, 17 May 2018 21:16:17 +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 9B241E41 for ; Thu, 17 May 2018 21:15:58 +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 DFB416DD for ; Thu, 17 May 2018 21:15:57 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id c11-v6so3276830plr.5 for ; Thu, 17 May 2018 14:15: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=AN3kBEMJAPx+b3R3KzG8xQfJhvNeYLRnhie23KlFAbU=; b=dyBdIor+zbiy703bTaXSBH2ecOjr8EUt1cxCqQQ7gW3Ufje8c8oeAb8tb+LXzU8FK6 NZV/JcQtFTtcGQYZvcvuuv/H7GM0cVgiI7treSGaIOT506v9PpzLtS5kdIZ3Mv8BcKl9 XtkgSErr8VliBFwBbvfCKIPtcNN4dsDwXd5jys6HHwfjBj5wSjcXhIx3qMmx+3k6VsFH dMUh9169Ow2THxVBp9HehHWwsEchllf/t3Mbl9GJli86d6gsii++3sC+ECgbbSBc/pnO kdaUafwpmOSD0t03kGKsRWu7ICD9iKT+EUjMGp6HB/uRrIpI0xz/WhfAiHf0wP39qFno zfaQ== 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=e76/kdqbLGGJQd9TRBvJYzuzbjPOKklLK7IAgF4RSznRAd4NHySNyFq+AGK0epuXoS tNBQTz0oBL37aM6b2qQiVSeL4Ct0VGdT9idqaylwaKgsiD+d4L4yjEKGjmEYlQT4Trsf rG71P2dCzZPCXkwp4o8mESG0FaxWu53/QwmDbmATsN4m32ICeevaF/cyL66n8Bp9Jq8N xjcxS1XWej3sHOnkg0EUg95y09ycWAXMYQSuu1ej/9SAMTZBcBpTfuvx/wZCoocF3zgm JfPLa7dXOnGukZJKzFvPSm6Bcq8q7A2U4RROAZqWkQYT5j0Ygvzr0uvYX+BbHYEQcQQa vuLw== X-Gm-Message-State: ALKqPwe5fyz0wZcHHtxwYooKZ3Q+nk1USQch9ixRvIAJUGqQhHc3k0w1 zm+/ZLMwgZFgCeG/N54UzkXDRw== X-Google-Smtp-Source: AB8JxZqRFDXunCVfWIymvMxCp701UtpMxlwrv0/+GhX2D5acieh7OT3I+4G0l5U3RQDs1qbS/geTqw== X-Received: by 2002:a17:902:b946:: with SMTP id h6-v6mr6877503pls.3.1526591757292; Thu, 17 May 2018 14:15:57 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.15.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:56 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:13 -0700 Message-Id: <1526591733-4450-22-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 21/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 Thu May 17 21:15: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: 915800 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="m187YAST"; 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 40n49h5ncJz9s33 for ; Fri, 18 May 2018 07:26:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C7845F61; Thu, 17 May 2018 21:16:18 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 183DFE5B for ; Thu, 17 May 2018 21:15:59 +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 AB4636DD for ; Thu, 17 May 2018 21:15:58 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id l2-v6so2347353pgc.7 for ; Thu, 17 May 2018 14:15:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=180UToHz+/5upm/xU7/kHY7oDrdiwqCL4sXyx3n4SVo=; b=m187YASTjZV76OSBxLU/hlfxKw3aCV8Q6STjCNxLxRgZlAdZYBQtka52ynHyQR1OsY NNKJjFSgjrORehwT6z2nyJBwt0iEYvfYA6ykbcR1B8MwMCUXSe8+nLwik6gA6igVXPix SceUhBk5A9Cm81fwHDcmUbs/9NouuIFtDZAMCBzaijZeG24QdTStKs9Lg0nPEio5h92e GEnylsYrS3orrJA9xrKzv7bdORIBZkDzdEVOrLhdpbfjvknXr+zQFInHSjKiCWT1nAaf yIoGaTEcYRH28I6O4ZBcyDDrmhzmJdwdKlsSMtHrS0xCiTD5DHi6RmO0PiJF3XDw4MO+ TFxQ== 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=s+lFQ/ZuBGWANrZKUmERczbSgCvR5QWz7sOCmsVy4+9dlpj4CZ8CeyRmu5XJ91IKg8 ElfZmkxX65toEt9br1DbOy58CvJmVE8tFmp6wYF+p7Y6+2i/A3Fzbr0pt2krWnZc40eL 1GEZYtSzoDEMe0T8hRbd8NNARPHHL4832ddGVb3np8TVsv0lVqk6eNnOshnyRFHZbDPc tsxBw3KjxLJOh2mixGynACZcdww3XEys/eLlEEE37OySHJTlX5XhVhrmOpKi7ZLajwil m7YxmHYvkSZkKYfqrlipBW5p8g1r0KHZXCdEcY7NDq1gikBbUWnBYa0tC7N801lEJSHj IR3w== X-Gm-Message-State: ALKqPweVVv8BAaqRzTrMGYFdOI36GiOvQPJ3RHffHsXDKDaDI1JOUps1 KEXLh2FsbxlJhAUbmZE1XE/Y6Q== X-Google-Smtp-Source: AB8JxZoo4h2pCM8+Hw2UgkrJJlKzJyMGN3t2cA/8/QgmOD850q46+QZRRb2A6ZAe4KPCuQLJfcbLbw== X-Received: by 2002:a65:4a46:: with SMTP id a6-v6mr5291562pgu.227.1526591758115; Thu, 17 May 2018 14:15: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:57 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:14 -0700 Message-Id: <1526591733-4450-23-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 22/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 Thu May 17 21:15: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: 915801 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="pH5BvEVK"; 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 40n4BD3Rw1z9s33 for ; Fri, 18 May 2018 07:26:44 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8E058F67; Thu, 17 May 2018 21:16: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 AD12BE41 for ; Thu, 17 May 2018 21:16:00 +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 EE4FC6A3 for ; Thu, 17 May 2018 21:15:59 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id o76-v6so2684521pfi.5 for ; Thu, 17 May 2018 14:15: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=4GQY7z5NyC1wygOl0cT8Us2f2XQ6o5sdFTQJM17wRSU=; b=pH5BvEVK1XpxtqWIogE3Pu1HSdTLVLghVTkwxKtvg69R3yD9zy7zSHFbn973qy6a23 nyMaf9giePOl0gA7ECSQF6/R/XL1r3k6/JwOySu4QqXOKCzEiPEWz6j3tmA4EKhEpOZ9 rKZi56ME3ciKdbL830S3JrlD2Mgcc7wjb00RpOl/QEozCVVP/L30CSGMT76KABzKpmbL sMmMIkIpmBFIO/TGSPdRIjs4EeOCsEvF9E9Kzstq5MMbJ2MeYOVWAuwy4mfbvZMi6iaM 44i8zhzncDfTDSphgRm7v803ccUvX+uuhN79b5ChVR+mGiNfd8zyu6vk7tcz2Hwk1Sun lS9g== 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=XhQkrdsGxqL8Z3ZD3aGoDQ1cPTUjBh/H4lgdKeWJjEH7Z7eekVAdJ9c8CYa4s065Su E7QJ3Dq+Z+3PszxhBNWEewUpnpESf/W/Cnq7ij2oc/nxDmAMnAEHmbVElPacBzgcwoHX F+mATNBkS0rJaVmwsfE78hsrtYdNmO3RwroGiTzmKsMExoqFMeQqDH3H7uFFqFnJgA9w 3Tp2cVIx+/AQknY6JYPSIO1h9ykdMT/rXogUY5hKhWZ5aMe+6FZtB7l6gBBvyN/ryh+/ onifHJrn4uQwBrkJF+kkmizjVWwSW9omeB6x9+Wdg426uSLnWrJcYjsO1YFYT3p+UU4p fsEw== X-Gm-Message-State: ALKqPwe7K9e1uAUvqAlapxmghRiIucWaNcvkVQBnrqiHRwQ4tX9oCOxL 2Yim+018qNhFEnmydKPtCkpetQ== X-Google-Smtp-Source: AB8JxZoCwTV3lzLkHU6HFvWAmbyYyaYlFHLA93Njid8TuPpzGVe5NTG5J8eVFi1tQKg6JUxgQiwjgg== X-Received: by 2002:a63:b144:: with SMTP id g4-v6mr5205734pgp.253.1526591759217; Thu, 17 May 2018 14:15:59 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.15.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:58 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:15 -0700 Message-Id: <1526591733-4450-24-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 23/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 Thu May 17 21:15: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: 915807 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="foyfZCr+"; 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 40n4FP53H5z9s33 for ; Fri, 18 May 2018 07:29:29 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id E51CFF89; Thu, 17 May 2018 21:16: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 A2A08EE9 for ; Thu, 17 May 2018 21:16:06 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f45.google.com (mail-pl0-f45.google.com [209.85.160.45]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 4FF3A6D2 for ; Thu, 17 May 2018 21:16:02 +0000 (UTC) Received: by mail-pl0-f45.google.com with SMTP id w19-v6so3272362plq.4 for ; Thu, 17 May 2018 14:16:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MazlFv4tb+EYTkAn48diiaIjY10U/E34qI5lN7s2mVg=; b=foyfZCr+K/8CoyO52Kzr3jHez4hmesgoHXXKmuZ5EC3Cx2uYg/vajqd63uQDQzzYS4 ph4x/CbLXpS0IbpERIAWpyi1SSsyV0yeONUD8+a5yPbvyzPo9LTGRzTKk6xBdebV8coa Q2uXpWjr1t6A4dr0klOwieSTfImGTji7Jib3JdG84miC+EjOlUllwhPETSnwXg/1dujE 4wQrpZss5iLDasIxNAuXeNNhfJkfX7DnzVFMl7kDhUq3YLdi/iKFmGExywf/QM3xDZKu 8xvPC2aG+Tdf9P8segqxvjEosUX8/rR1q1Xywot2E+dlRW30lv5yvPTz1D0sh4XI8rXh 59jA== 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=MazlFv4tb+EYTkAn48diiaIjY10U/E34qI5lN7s2mVg=; b=S3J4OgE70pbvjtxEZDZHkY50KSu3EMVzNOMGlSrqaqrxa3DV+7h/KdUNvBqEwn6VvX qUpNcq4c24IRZlN1qEWTVZkwgbenZafA5hVzycQozxOsGTYWfX+ALW1IBByTKrOUUWJ3 c2tX319bxuUkMpIi9inaVNLcIP6c5U0LMV9fm5ghFE/KrFssKQbcWIuZcmCHGqzrEVqx Swk11Uy53O4NE1fZEosuh1Q0UQ2v/tSRbsQJATS67+6OWek9eijZLtj9nERUeHuXBoW3 mG7yQECqpYKbEc9kPyAp5h90iVxSeJ7UhTyvgXlS9zzSBGgZa5jotL2htAJMVJmbRic1 iaJA== X-Gm-Message-State: ALKqPwcF34/hXyxCb//HLaWQJy9R8+kO93Gbz0cuN9FoPg2jOCJVl+vK o2I3PVgI2tdoQEE/D6eG1wJAtg== X-Google-Smtp-Source: AB8JxZofWE6H+JmHGqD98qgvijKdIKf/Nba5QuHgtx48Tn46MpUt21w9ntIbMeJynwm5tA0lGrm2Hg== X-Received: by 2002:a17:902:547:: with SMTP id 65-v6mr6838663plf.388.1526591760483; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.15.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:15:59 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:16 -0700 Message-Id: <1526591733-4450-25-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 24/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. Signed-off-by: William Tu --- 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 | 86 ++++++++++++++++++++ lib/netdev-native-tnl.c | 173 ++++++++++++++++++++++++++++++++++++++++ lib/netdev-native-tnl.h | 12 +++ lib/netdev-vport.c | 54 +++++++++++++ lib/netdev.h | 4 + lib/nx-match.c | 13 ++- lib/odp-util.c | 83 ++++++++++++++++++- 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, 1122 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..2c1be7f 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. + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_IDX(11) since OF1.5 and v2.9. + */ + MFF_TUN_ERSPAN_IDX, + + /* "tun_erspan_ver". + * + * ERSPAN vsersion (v1 / v2) + * + * Type: u8. + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_VER(12) since OF1.5 and v2.9. + */ + MFF_TUN_ERSPAN_VER, + + /* "tun_erspan_dir". + * + * ERSPAN mirrored traffic's direction + * + * Type: u8. + * Maskable: bitwise. + * Formatting: decimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_DIR(13) since OF1.5 and v2.9. + */ + MFF_TUN_ERSPAN_DIR, + + /* "tun_erspan_hwid". + * + * ERSPAN Hardware ID + * + * Type: u8. + * Maskable: bitwise. + * Formatting: hexadecimal. + * Prerequisites: none. + * Access: read/write. + * NXM: none. + * OXM: NXOXM_ET_ERSPAN_HWID(14) since OF1.5 and v2.9. + */ + 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..f1b450c 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, "erspan_ver=%"PRIu8",", tnl->erspan_ver); + } + if (wc->masks.tunnel.erspan_idx && tnl->erspan_ver == 1) { + ds_put_format(s, "erspan_idx=%#"PRIx32",", tnl->erspan_idx); + } + if (wc->masks.tunnel.erspan_dir && tnl->erspan_ver == 2) { + ds_put_format(s, "erspan_dir=%"PRIu8",", tnl->erspan_dir); + } + if (wc->masks.tunnel.erspan_hwid && tnl->erspan_ver == 2) { + ds_put_format(s, "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..8c7aa00 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,91 @@ ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1' +

    ERSPAN Metadata Fields FIXME

    +

    + These fields provide access to features in the ERSPAN tunneling + protocol. The ERSPAN header is defined in the draft +

    + +

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

    +
    + +

    ERSPAN version 1 header format:

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

    ERSPAN has a fixed 8-byte GRE header, including 4-byte GRE base header + another 4-byte sequence number. The ERSPAN's 10-bit session ID holds + the tunnel ID. +

    + +

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

    +
    + +

    ERSPAN version 2 header format:

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

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

    +
    + +

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

    +
    +

    Geneve Fields

    diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 876718a..7152f3e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -518,6 +518,179 @@ 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_be32 *index; + index = (ovs_be32 *)(ersh + 1); + tnl->erspan_idx = ntohl(*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; + + md2 = (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; + ovs_be32 *seqno; + + greh = netdev_tnl_push_ip_header(packet, data->header, + data->header_len, &ip_tot_size); + + /* update GRE seqno */ + tnl_cfg = &dev->tnl_cfg; + seqno = (ovs_be32 *)(greh + 1); + *seqno = htonl(tnl_cfg->seqno++); + + /* update v2 timestamp */ + if (greh->protocol == htons(ETH_TYPE_ERSPAN2)) { + ersh = ERSPAN_HDR(greh); + md2 = (struct erspan_md2 *)(ersh + 1); + 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) { + ovs_be32 *index; + + greh->protocol = htons(ETH_TYPE_ERSPAN1); + greh->flags = htons(GRE_SEQ); + ersh->ver = 1; + set_sid(ersh, sid); + + index = (ovs_be32 *)(ersh + 1); + *index = htonl(tnl_cfg->erspan_idx); + + hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE; + } else if (tnl_cfg->erspan_ver == 2) { + struct erspan_md2 *md2; + + greh->protocol = htons(ETH_TYPE_ERSPAN2); + greh->flags = htons(GRE_SEQ); + ersh->ver = 2; + set_sid(ersh, sid); + + md2 = (struct erspan_md2 *)(ersh + 1); + md2->sgt = 0; /* security group tag */ + md2->gra = 0; + 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..4b54e59 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -712,6 +712,30 @@ 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) { + const ovs_be32 *index; + + index = (const ovs_be32 *)(ersh + 1); + ds_put_format(ds, "erspan(ver=1,sid=0x%"PRIx16",idx=0x%"PRIx32")", + get_sid(ersh), ntohl(*index)); + } else if (ersh->ver == 2) { + const struct erspan_md2 *md2; + + md2 = (const 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 +1423,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 +1601,58 @@ 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)) { + ovs_be32 *index; + + ersh = ERSPAN_HDR(greh); + index = (ovs_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); + *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 = (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..61888da 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_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 Thu May 17 21:15: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: 915804 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="Vxnd043r"; 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 40n4Cs64bwz9s33 for ; Fri, 18 May 2018 07:28:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7BC59F7F; Thu, 17 May 2018 21:16:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 34BCCEDB for ; Thu, 17 May 2018 21:16:05 +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 5D2A16DC for ; Thu, 17 May 2018 21:16:02 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id u6-v6so3270700pls.9 for ; Thu, 17 May 2018 14:16:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=NYXuT+GbgKl0lCLSWbjbb12rlpsIwuKJyTrTwnB4N/s=; b=Vxnd043rxxoHr3dyfW6wKM1ZzIQrBaap5P+chhXIVnMbUq0l3Q87mfjb7NCJHBYA7a Bz54GuMfNOeNqnctHTb5nUK2mYYWTfEU+TNuiR+V8zfT5f0jSEl7EpiaLfjzpyE+XwlX 8/1MEFeMRIkerlaSWEoQoBhhTn8TWb6y2iZSTYgHEK/HMG7ZD4i1eoP6/275h66rzBpw eYDesR+4jbq5jMBgXE5hYlxc5TadoFjonfcV5l2+a0innF1YdguBl7+LZSOIL0YrJ9nk 5wbigARHN1Ym2xC+gItkYAThy31xbbzFCJRg//Le7yYNYlxoVqIwMJDRnDxHSU8xeRdE sV6w== 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=NYXuT+GbgKl0lCLSWbjbb12rlpsIwuKJyTrTwnB4N/s=; b=WX96Uh9a/QOUSuIJhsKhednldPI+/nN8XQ6BjOsj0T4pgF17YXrjALnBATOn1s3FmC BF/yA6D9N+HPK5RG7kkkvHGuhcruXdF9wPNzfw1ieXXa3XU3q6V/Cw03v9ZA7X0NeTWT mKII2P8HxZ249d7a03RE9En/04n85U9/QKGIOgGnkeSm2YgBN/V6ab7lp2OI/M29EM0F yyl3rq+9DKmepQ9ZqX57YYiwScHdQmNLXb90eTkg/83ZguTnjZgaiQaRe3pNuR3ByBn+ htnJAzKF29UhLCEPi1mL8Zdu9VgbLkacgm4WObsS3U/kPwzP6YFnYocBWDkyctJEKIEz KBvw== X-Gm-Message-State: ALKqPwdomouGSkriahD7TuYwQ72nnksLxMfQln6MANGgTpfuW1CcP9bE Z/noqL79kIaF39ArqoK+zYBXUA== X-Google-Smtp-Source: AB8JxZpZKoPPOUJMX8uGPc0X02x4r98C3J054v1Q9KR+eBmsO6hPcQ9tW0BAaHq9hStgLWPintd7Gw== X-Received: by 2002:a17:902:3381:: with SMTP id b1-v6mr6721501plc.248.1526591761290; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:00 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:17 -0700 Message-Id: <1526591733-4450-26-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 25/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 4b54e59..ed11c22 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2454,6 +2454,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] = { @@ -2777,6 +2778,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 @@ -2861,9 +2879,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); @@ -3321,6 +3349,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 @@ -3569,6 +3637,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: @@ -4754,6 +4825,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; @@ -4888,6 +5023,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; \ @@ -5256,6 +5400,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 Thu May 17 21:15: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: 915802 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="bR6k+7uu"; 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 40n4Bn1WNpz9s33 for ; Fri, 18 May 2018 07:27:13 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id AEF8CF6C; Thu, 17 May 2018 21:16: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 3089EE78 for ; Thu, 17 May 2018 21:16:03 +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 B11006DD for ; Thu, 17 May 2018 21:16:02 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id e6-v6so3259664plt.11 for ; Thu, 17 May 2018 14:16:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6gPwmbsxlJ++SQ1QOTKcmra14PfdL0ZHlWMKQ4vPL58=; b=bR6k+7uui1zmXwXPmbaEEnJqwUCs5jI660DwhbKGoOYIWZwcF5dJshVc3SgqJ3cO2m Eb2eOmouqyWAlRdGT3v8VLgBBq+3zgDmEbPPbov+lh7nvV3qaLu/xqd4kGr2iTSpPIuL evCgMDQl8KUJWU5uYPQbYbKuO5i4TlKYTuXuFA7Ph/e8vp+1I9ZvTe1lD54cIMjTJUuk ST4xS5kGjkn/SIspse4lh7/slcc/n00RfYQy0k9vBQ4dRD7mc20OJBeQ8vjON1rSr1II nfRq0/JSsQ6kadOk6mCKwM3NrVkgA4nmkFhf3jKPfHKL6ICT1ML4NYM4KQCurKzWKrJF LIhg== 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=VU1ScyF9seeVELDHDpRGoCw8Vun+DgqaHmFmKU4EZFdSH/19/XZziSJ8KFQTD3HtWB I4GjXAZri9nnhS7O+t7G+/7JNIYFiAdoGYgKhXbyAD6zPdWB7lASf5WyxgCPumkLrnFb CrrIuPRkuFTv2tTAzRr3NGzQd1VfJUV76U263HJiAxVmb9WNtEM9K7pqxowr+mJiMgrY WcumYqUnaYaaqwPFCf+s3EtDa8fCnN14neGRqpADA3NZ651OnAMUIvZ7VgY+cEr8TxMs NwLk7GBKeJYyKGqHFnLGCQS85/181chI2m6c4AQ2v2kAP7hT2X3kqhMQLN+kLW9OQx4i 0EQw== X-Gm-Message-State: ALKqPwem0hrjhphlv4wpG6uuYU0qgbSAZBt1QnPPzf/sqMWiM2xGbKY9 I4yEbcOLO6AV1grHqnyAlWW/3g== X-Google-Smtp-Source: AB8JxZrS/95MQgXzAMDIxIScF5XA4GFs5mqOrZcsEINM3HfksHLNfERaZT3i59aH7XNL9xFgtqnbHw== X-Received: by 2002:a17:902:4603:: with SMTP id o3-v6mr6905107pld.49.1526591762057; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:01 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:18 -0700 Message-Id: <1526591733-4450-27-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 26/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 Thu May 17 21:15: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: 915803 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="fDffxUfj"; 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 40n4CM25NCz9s33 for ; Fri, 18 May 2018 07:27:43 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 379C4F76; Thu, 17 May 2018 21:16: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 55D8AE59 for ; Thu, 17 May 2018 21:16:04 +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 BEAE16DA for ; Thu, 17 May 2018 21:16:03 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id n10-v6so3272811plp.0 for ; Thu, 17 May 2018 14:16: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=N6+3suwiNSv3a39R0QYQA9rHIqsjOR+VjQzGIJMNqz0=; b=fDffxUfjhC5687XyIWHGE6tlNkKXOmdstrt0qtfzunJL3hS/2ndkP0KkTC2lz+80bg AHKx1riDaKG4skU/8e462jx52KgTjFaaGriCXiQdDnz7a70p0ajrUztoTFlTlE8QSDu3 NAGP+x76j+su3eMsvtwFPy28yrL0up9oSO8eM+/Amu8Htic6ZrOXnScE5swcRsbjKBB0 Qf8U6eCjJB1LUWhZSZCd5QBh3v13PpAofKW790v/NeKGgaco6+oEKl1ZYtBPcy0SAkC3 LpV6/tAMsPuGqwbiIeE7wET7627cHkfMLkEylbbRFrnn2GzO2CwIDmILhp3KM39R/lcZ 6MDw== 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=N6+3suwiNSv3a39R0QYQA9rHIqsjOR+VjQzGIJMNqz0=; b=nzXO5luTN5zRYFvTuJNB1PZdAHcXeZysv4zUknHDxMvODImymBGLF/ljaiRsYQQobR gU+B6h/7L1JSPlUCpwFbQKgccYPDcdT4B2/7VhREG5veeBSAyj4GGg7CVwn7XO9db+7J 2v4tFAf+OLiz/s1LFRFOjJNs3e++ShI331tBxSSOHurmxif9Z/cupPrb1ew8o8WGOwbg SJzcsk6zM7DsydMcZN4bVrGU9iFG0UtHYWoHsRNChstjDY0yCxBNox2A+eb3bSlYBWd4 7pWMBIMmKGMw33gcyAO5O1VDMgodVKTBrSDJ6omFvzhGbsoW6uj0hpZ7+u6FuLn4kvcc fvTw== X-Gm-Message-State: ALKqPwfCKx7qzzu9yHSxbOjNgPKTbFLo1fXuFk7x67RBAAhVAQEkeBO4 X1mIW4VxdyiSgOuC0U2t61J80A== X-Google-Smtp-Source: AB8JxZr3VWMwmdyShipDNuQe/Hl3ltvfV7vWTzyM3u0eDT9yhYrPAki7zunv7nv5BXwOfu9CkSTwEg== X-Received: by 2002:a17:902:8:: with SMTP id 8-v6mr6529461pla.287.1526591763112; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:02 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:19 -0700 Message-Id: <1526591733-4450-28-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 27/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 23b1c83..da14ca1 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -1070,6 +1070,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 @@ -1088,6 +1089,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 Thu May 17 21:15: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: 915805 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="j2LK2Kc7"; 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 40n4DM6Hpbz9s33 for ; Fri, 18 May 2018 07:28:35 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1A42FF8B; Thu, 17 May 2018 21:16:26 +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 8E398E83 for ; Thu, 17 May 2018 21:16:05 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f46.google.com (mail-pl0-f46.google.com [209.85.160.46]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id CAD566EF for ; Thu, 17 May 2018 21:16:04 +0000 (UTC) Received: by mail-pl0-f46.google.com with SMTP id 30-v6so3256741pld.13 for ; Thu, 17 May 2018 14:16: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=UjTf8KvkgQFnL4hzE/iqcf8OsimPisHnYcJ+g5ACmvg=; b=j2LK2Kc76JzBsNDXVt8QDY/cvR14f3vPEkj4LHttHQOO2Y9oD3gIKdazOTS4tLFia1 6D/slmVMlNpgbD/Fa+brMES9PQFyaraLFalICGUEvNgJcX1McDSmBto8ss16UPJNus7C eu0uMS1uW4Teq7igM7PHo/x/xNsJa5sPmDRhzc8KZqI0Xz1F4uwc8nASW1djCux5i0F1 9Ko+4GCUJqUx4Fbusi/chNLrkslCBnFyaTlVnlHzSGunR0E8JB/UiEw6jITIXBZOzwjV 7ViXj5NCRcIoKZumtR0U3cv9IuNdaGHk/DwKg4zsxbs36KTCakRxb5Wwo32bM8AwlcnI nF9Q== 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=UjTf8KvkgQFnL4hzE/iqcf8OsimPisHnYcJ+g5ACmvg=; b=q+3vrD0ePvhIzMnCI+5ZCci3EFMNHhKtCmJc5G0/Wv76FrWayIdn/JO4DoI1Qyv6zq YgTV3OeYNRL8+lKebqtY9BEYnYAQsXFruA4EUKuGxwKlf5rjV1BmIJ2xyQY7W9EHId0Z uxn/HdRhuvANJmsQak7w0/4BBSujFEDVIRYCMYJibNao0fd5H3wfU/rSDN9Xfd/DnrZF MllHmNI/WwF5HVCgqOHPBpc1JeGRWy5JGpOxiU4M5nPTJl1boGxTIv71RqMw298Qly3r 1SXhkwcZvnV5v+DtDqf1QztanmNN+sL3cE803QZq1PdZf7N/B3cMlk78WHYzrLPCyT9J EjgQ== X-Gm-Message-State: ALKqPwde4U1wWVF6z+GnMgt4zXmUE5Z0kg0gein+jT17cf36zDXBCyvF zKo1BRcg3At/GQio1IjvSraUAw== X-Google-Smtp-Source: AB8JxZpOZRq71kdPXoWz20LL2h0HDNxgNy+Tm0zpq+B1iUQ3QJ1bQmMSGusWBrohpNNKbbwG7Vu4qg== X-Received: by 2002:a17:902:b788:: with SMTP id e8-v6mr6757070pls.263.1526591764126; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:03 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:20 -0700 Message-Id: <1526591733-4450-29-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 28/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 Signed-off-by: Greg Rose --- lib/dpif-netlink-rtnl.c | 4 +++- lib/dpif-netlink.c | 7 +++++-- lib/netdev-native-tnl.c | 5 ++++- lib/netdev-vport.c | 4 ++++ lib/odp-util.c | 9 +++++++-- lib/tnl-ports.c | 2 +- 6 files changed, 24 insertions(+), 7 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 7152f3e..fe36ea9 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -513,7 +513,10 @@ 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; } 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 ed11c22..29b5fb8 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; @@ -1561,7 +1562,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 Thu May 17 21:15: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: 915806 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="oRvh6oyf"; 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 40n4Dt5B4qz9s37 for ; Fri, 18 May 2018 07:29:02 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 692D1F81; Thu, 17 May 2018 21:16: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 E9E38EE3 for ; Thu, 17 May 2018 21:16: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 990E3E5 for ; Thu, 17 May 2018 21:16:05 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id p9-v6so2345161pgc.9 for ; Thu, 17 May 2018 14:16: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=U7zGUpDFrWahNlw0S+2lHwGiCjAVFwTC7l/9axYEemk=; b=oRvh6oyfOKEfIsfKeA5A+uLD6hefMc2rRLpork0i/dlOTfKrE5PQ5miEr5lQeDeMlH 59ymKYeD4gOAkJKGzadon1LYQV/zy9R2tPESRLtzD/GFxyv5UarQQJlZfWaAgvcSpWx8 torc9fPdcATTSbAe8S3A/DAIV9Y6mnjJRvgtYl3hfa4sIU+qXpEziQzPcKc5PGPoPpHT sWOAlzxmDQ+cAgl68oMjJkZ9fdo/9vZhiTOBGOZ2+DbGVIvhAru2fh2KP1AR4j7Q97E3 X/D62eI5FKOcaAux8gEOiQ+pA0mUX4lAIHMnPef93YHUYtU6Gge13hfhXFtyeHcsdLV1 2ReA== 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=U7zGUpDFrWahNlw0S+2lHwGiCjAVFwTC7l/9axYEemk=; b=X+1/AaZhABL5O1e4NJJwCCv0J5YHaE+FLyjcO4oU9w0SgF94dyyT/X5a5+5oJBwksu Je9M13qrij2H3xQtBZFDm+LLN62hJrkIa/Pjs7HgHhNvMSDigCUmuF6KjL7j96lqMXjL XSPBxs/1HS97v/87hWvY5V51XEYWaXce+NrF153+0sir8TwMhvEo7syq4Q7VcxahG/aw Ny3M2/LwiXAOM5zmJWau5FiPMKTAwsusHyK+RJXOcOo278Od30kO0yKe4lri47v9Alqy aJSOPGQRQeax3qtFqj/gFLS5g2HqrGvdnrSdSXZcclOGNKJHaMuiLBlqWV8GaJA8eqfW O4SA== X-Gm-Message-State: ALKqPwfna7yvkXzzWwgIiclNB0nZPFm6qR49hah+8ldTMYgBUIln6/XE DVRDdmMO7Us8VOBIR75Hs+HUzw== X-Google-Smtp-Source: AB8JxZoeZEenc/A9Tsrwk1np8ZlE4bnARVoGwuOhYvcK/qity4FQ4iSolGS9RwPn8RPmhhOCM2UqNQ== X-Received: by 2002:a63:7314:: with SMTP id o20-v6mr396029pgc.156.1526591764945; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:04 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:21 -0700 Message-Id: <1526591733-4450-30-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 29/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. Signed-off-by: Greg Rose --- 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..a3c5381 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 (strstr(type, "gre")) { + return OVS_VPORT_TYPE_GRE; } else { return OVS_VPORT_TYPE_UNSPEC; } From patchwork Thu May 17 21:15: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: 915810 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="dmrd+mzR"; 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 40n4HC75S3z9s33 for ; Fri, 18 May 2018 07:31:03 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CA5DDF15; Thu, 17 May 2018 21:16: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 83D66E8C for ; Thu, 17 May 2018 21:16:08 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f170.google.com (mail-pf0-f170.google.com [209.85.192.170]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 194BD6A3 for ; Thu, 17 May 2018 21:16:07 +0000 (UTC) Received: by mail-pf0-f170.google.com with SMTP id v63-v6so2676606pfk.8 for ; Thu, 17 May 2018 14:16: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=DoI1dyU287N+dO2iDX+ssvzjb331ZjkwCGAl/GjvEpo=; b=dmrd+mzR9wtSQWFTNbJ/0/AdhMyqy/z0C66d6Fvpz7gWS6fZ5dWto5/OK0w06/ClIh 2nJbTrziqijrNNeFNE5Ib6DcqNUnv6GdqPgPKtEQIFn0+f5cdB4qri78cqFpLWINZjqX ngXAl/04/efsAmxJ7fV+SX/lK8/v5fWNh4GNvt5313yBJGGQIpXWkZhhi+H7Rh+DvWuR e9lZgOPp42aNTaMjbVsIhk4DscAc9LcoJbpVrgsqAF2N8wSz2cluyr3MX9wEighTBKuG rlnPvGxTTXLqa6APckB+K6t9mNhDETsKguu/yVBTr+zaw/o2OaaScqJz9d/A9+nYCeta b2Ug== 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=DoI1dyU287N+dO2iDX+ssvzjb331ZjkwCGAl/GjvEpo=; b=RXvszsr1yaGD7T2PPHRBzhurY+CP0j4yREIzVATb0PmIh9QgA6ZDCBtQ4CwiuxRjLM KF5e5Mo8eqpdmGb9esyJy+tNTKBWQhGdWYwwVySqGx7R+sQLugeYO7zNCVUbLIcJ0F4T CCk7OJY0S3hJYRq33WKYNBCgBPcbn2RuFmvukTCS2ZeOacTOj68BWX422knBMkJWk3BW ct28wkuIZAHeY23xCKdP7VYB1KnC5TRqCVdEe/t38sZdh6CoOOhW8MEoPMI/NDk69wpM 8do2o+fm/QQlt96J3wVGkzGCINUkLIgjCwBKthfvqm19E1UD7hnkxpRMKnChEM15FxG+ +lcw== X-Gm-Message-State: ALKqPwdUZgTveUoU7f44JU1cNeT2xHng5UugR9z+AkpUReIzbJxqJZWF OP9P4zwrjmMVEKySfzfX0ufG8Q== X-Google-Smtp-Source: AB8JxZq5OmsMek5O6fR715Hh1jvLhCR1ds2X5aJAkQt6jykj7ca4ZE5bDjcguXNC3/Q5YgR7yMp+Rw== X-Received: by 2002:a65:4043:: with SMTP id h3-v6mr4105802pgp.333.1526591766103; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:05 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:22 -0700 Message-Id: <1526591733-4450-31-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 30/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 From: William Tu 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 --- lib/match.c | 8 ++-- lib/netdev-native-tnl.c | 32 +++++++++++-- lib/netdev-vport.c | 120 +++++++++++++++++++++++++++++++++-------------- lib/netdev.h | 5 ++ ofproto/tunnel.c | 11 +++-- tests/tunnel-push-pop.at | 35 +++++++++++++- tests/tunnel.at | 68 +++++++++++++++++++++++---- 7 files changed, 221 insertions(+), 58 deletions(-) diff --git a/lib/match.c b/lib/match.c index f1b450c..5305dbd 100644 --- a/lib/match.c +++ b/lib/match.c @@ -1288,16 +1288,16 @@ format_flow_tunnel(struct ds *s, const struct match *match) ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl); } if (wc->masks.tunnel.erspan_ver) { - ds_put_format(s, "erspan_ver=%"PRIu8",", tnl->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, "erspan_idx=%#"PRIx32",", tnl->erspan_idx); + 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, "erspan_dir=%"PRIu8",", tnl->erspan_dir); + 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, "erspan_hwid=%#"PRIx8",", tnl->erspan_hwid); + 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, diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index fe36ea9..4966cd3 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -630,6 +630,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. */ @@ -647,7 +648,13 @@ 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); @@ -656,10 +663,15 @@ netdev_erspan_build_header(const struct netdev *netdev, set_sid(ersh, sid); index = (ovs_be32 *)(ersh + 1); - *index = htonl(tnl_cfg->erspan_idx); + + 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; greh->protocol = htons(ETH_TYPE_ERSPAN2); @@ -671,8 +683,18 @@ netdev_erspan_build_header(const struct netdev *netdev, md2->sgt = 0; /* security group tag */ md2->gra = 0; 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 Thu May 17 21:15: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: 915809 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="Fh6m9SjP"; 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 40n4Gg0Y7Pz9s33 for ; Fri, 18 May 2018 07:30:35 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 5D7ABF72; Thu, 17 May 2018 21:16: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 B1A74EEE for ; Thu, 17 May 2018 21:16:07 +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 72AEC6CF for ; Thu, 17 May 2018 21:16:07 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id e1-v6so2351975pga.6 for ; Thu, 17 May 2018 14:16: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=GP8FqGHdE3aF3L8gBfeh6nbyzBN/9ZiEryEZFj0RakI=; b=Fh6m9SjPo1O3ZseROifR/N3S0N/h6ITJZ0FczJKXTBg0freDrPeij9dZCpwMUW8zEv ClApOtnxJWewsZ8a63C283oQw2gO9NkV9knMKjbnAMJLYR3SLEyRQsess5RRH1js/glO hAotVhSuY63DEsUZklW49PyFSEK3iC4tBla28tBkAb+gI+kUuL5+T/xpYM/IuV9fAUCP 3qJhBlr/5KYgcKOFBe+dBv2LYOaSQ46U4+h0b1pPRry0E+gjnW0UxE6oWaOwJARt59xU LXGRKdo6w/z8xyaf1S3PLB+aUJQ6ShewsOoYGXL4u2VkN8G3g38IO+lQRDvnaC7+9njk I0jQ== 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=GP8FqGHdE3aF3L8gBfeh6nbyzBN/9ZiEryEZFj0RakI=; b=LNLswt6ZMpd7YuzgBSvONyP9DStinaU0akDzr33KFnqaJGOH3sYgpLLHJNnbkn1NC0 Tw9fgQoPJgBxbrm7Qat1QKSG+hCe346d44c+8SeRauUaX1xXEoEZ061pJIQ1SaVHDBHf 6kBEKYTGJ4A3mHEHuZi/aS5FQrcyeRcLLw472zPkj36wLvWf5vUCWC9RnxkDnoAgb5oH SY4MMjYpb2hJ5zaPKB5QJO1/gPmaCBH5jEALi8sxwMJHByRwOrtY5kYGGRIba2GOQzc/ sTcFnwYCBTc2crNpV765ROsNipeAlP5ergCHQbnMQTnZJSAOe6EzrAdgcYq1BEltiAeL ERhA== X-Gm-Message-State: ALKqPwdIxqlEGYvmhnTUiqmAskQgK1Ou3apzGmvleZupWvtfBLVnjeAR 7ym94LLoCivMrybL7i70fCDD4Q== X-Google-Smtp-Source: AB8JxZr+Rp1JHgDmzUk7FwqSjQ5AYCsqZDptnGfC7zsj9fQmhm2RbkfHHgWgyb0vMm6zZgP2B2WG/w== X-Received: by 2002:a65:46c1:: with SMTP id n1-v6mr5309880pgr.62.1526591766819; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:06 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:23 -0700 Message-Id: <1526591733-4450-32-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 31/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 da14ca1..3f5f13f 100644 --- a/datapath/linux/compat/ip6_gre.c +++ b/datapath/linux/compat/ip6_gre.c @@ -2330,6 +2330,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 @@ -2346,6 +2347,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 Thu May 17 21:15: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: 915811 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="Pks+7048"; 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 40n4Hn6WP8z9s33 for ; Fri, 18 May 2018 07:31:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 57A37FA6; Thu, 17 May 2018 21:16:35 +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 ADC02EEA for ; Thu, 17 May 2018 21:16:08 +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 6DB4D6DC for ; Thu, 17 May 2018 21:16:08 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id v63-v6so2676632pfk.8 for ; Thu, 17 May 2018 14:16: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=MSe7jzN6EEFDmYkud5nYlRfKVt+GYgdFsElfbZ1gaOU=; b=Pks+70487nPUOH981kvyVMajxIluLr9k5eZfTWubw88w0W6QgLXoKUHRaPCtV+bHpF FBidcqeyva8bwsrMD/DnVRjVmD3jhGYQkCu3yzRJAyVHugtOUw8HaEE6r5deXW4V619N vCjpHGieXQ8i5G3D+CVBD+rqHOpmBzDcWrEoQjyyOaNDCn9Gz2NtZnLZOjuTyJJMtfUt ySSN8M60xzB69VywU4qhwL+00ihdv3U7+7NrHxeF26kkftlQ/vKbRdG5VRaKTqu0TP3u 3es0ZFTmn+Jzp6BswT3TuaiQVnNKm7X+MUfpD3yz5nE8gnHSxnPJqGGotF4Rg0rEa8PI eodA== 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=MSe7jzN6EEFDmYkud5nYlRfKVt+GYgdFsElfbZ1gaOU=; b=fYq4IM6M5yHYqQ3FApJfdwprPNQxqnDCtnyQowDU4w7arM1Tpk5pxDfms0xCWX/c7V SzRgi4C6GoYYy9mcVQjOwiNbj5uhsF8DZq7gdkWZ0d125lHNVgwlPtGzT1N1PYi0pfUE UNoiFGxa4FWYmIw53sSFZQ1MGu9GwMiBJRDJKT7mlhb+GncuVb/wz17YpyaffHiRMDAf sHBzbdjksNMOwLfn3B/wpE1LN87Tg6/WOSnlyJCwzNey5HlGJI+oRmxe8DoNQrjPOfEE 2xBHJK7c5IwkHAq5iHZGNfpB8LwPiINPNjIMQufA/oOVTlCNNcjBQdFfm7NThXGIO30o suIg== X-Gm-Message-State: ALKqPwd5G+dQtvhopgnoHpR9rTpdDHjd0D59JiLIVaHQtVdXcWboI2Wp iRRGpuH4pkejXQRtKw831vVqyw== X-Google-Smtp-Source: AB8JxZojy/+NEeBNQ0gnMnWpn9vXfJmdHwl9IgtMYNMOtQIgyzD/diAZuwT31SgkGYCir6gEbHoTjg== X-Received: by 2002:a63:9205:: with SMTP id o5-v6mr5249846pgd.233.1526591767784; Thu, 17 May 2018 14:16: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 r68-v6sm12410581pfi.174.2018.05.17.14.16.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:07 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:24 -0700 Message-Id: <1526591733-4450-33-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 32/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 3f5f13f..e0246d1 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 Thu May 17 21:15: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: 915812 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="BeXxjzf+"; 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 40n4JJ431Bz9s33 for ; Fri, 18 May 2018 07:32:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 09837FB1; Thu, 17 May 2018 21:16: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 D390EE6D for ; Thu, 17 May 2018 21:16:09 +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 6595F6A3 for ; Thu, 17 May 2018 21:16:09 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id w4-v6so2348164pgq.8 for ; Thu, 17 May 2018 14:16:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UU1RXYZ2uh97/O9sN4ItEWlkcFT7J3HGaVr9SSa3hu4=; b=BeXxjzf+w28qsg8H8zbHwTwLMTXJCSOk5evckR8GXPzBK9AkWLMv/9QUieYk4Kbl3Z 3Y7fd8gEmBWs/DRw05aNM/hI6kir4+tcAvW/Zr4Res2OyMMkHqwOXjuyManFF8u9INoR H/b2xeGKM0+WMGScjVv1hUrwy8YTPy6GLRd4FgNffakCYsr0NnFwxMIEsMUeVmuFMUCw jc5YHEJW/4HLXzH5fufleT0yxQ/A8ZbFyIp47G7qmB+e83fokKbkERT/jSt+Wuajvpoa Ytfkp9927snVCfjiaewXczdpUE3grovaHrMzCq9uXIqAwdFUra8AfgasvE9nMLQYUSNp mddg== 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=iibQXvTiIyCpjinxfjM6L9Fg7jAjWgwv7h3KiPEtUgThG9GPDBHeoOevBeZ/rCHNyU kYGEUFy3ZlGjiIMnhHq7ixAkMIbm3NZVMXuPbUtQ8tmqweX5G+OjfAObAkR5fX0KFK2P DSWwUSMfxLhv6poFboMllfHDUVyONeTo83yXXOJ/YQYuHQajr55Uk8FeYKdSC3wyusTv iJWHms32wGqq8vtNtOe9Q3j3StqvLDL6/92Mkynjis5UePuMVKU8Zhccejxo0FfoC3WP thbA2Jzvd46qRgIJwXRZoQGQyPsQh8cVPrHBGu/x0XC+xI6Csu/mq9mZsvb/FzOKgOot 1SJg== X-Gm-Message-State: ALKqPwfvLYlhgqIS2bIZqP9JF7hwctOYzYMkhOS0PhdI5XdfRXB6VUdX 5onlJEeWeTcZUy2DpN7DQ8xC9Q== X-Google-Smtp-Source: AB8JxZr8NBIpkKqW/vrF3WDt53BWVut0Ap1hSjUzopZb8A2tZGI1vKU/Vs/8EcUYNISK6Me8+V1P+g== X-Received: by 2002:a63:8348:: with SMTP id h69-v6mr5172503pge.378.1526591768730; Thu, 17 May 2018 14:16:08 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:08 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:25 -0700 Message-Id: <1526591733-4450-34-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915813 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="U3UmGcQ0"; 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 40n4Jv3Mgfz9s37 for ; Fri, 18 May 2018 07:32:31 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 9C1E9FB4; Thu, 17 May 2018 21:16: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 E787EE8E for ; Thu, 17 May 2018 21:16:10 +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 98F046CF for ; Thu, 17 May 2018 21:16:10 +0000 (UTC) Received: by mail-pl0-f66.google.com with SMTP id bi12-v6so3258177plb.12 for ; Thu, 17 May 2018 14:16:10 -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=U3UmGcQ08X/4+JzeHWoscfYP2T9OKbC+3c9ewPIOVwHz7pdFAb9nBaqwOPfeAuzhC6 ULWqqACFQgMHdvDxSiO0jdNRUaMqKRc2sXH7OdqfoRdVOhQNlu5AYpKsUTGAa6nAE7YF drDr1h/GPX65ch8Tk47ZyMtXJ9LYxceImANbZCfrFlXSWOL6RiQIip9fCFpBFiCGZ4ru j1EHIvJLwM2msjcjL+3fSRYxFfRZyH/WvbQC8na4l7a3ePTl9Gfg1mLy/q/J4Qox5QuB pyJke9ZB8rlG1MuVLhpKx9LbFofp/cwuwwuLRZh4SU8D5+gAmhxFns/xpRWPKzRSlDXH rnBQ== 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=J+79TYL+U8VbUz+XRE2ULh8M0T0NMefmHSzE/Wx8Th+TaUsRgqNLy5NzuUNUJ6oS98 S5inaF9jBuXDzn8rPwCNXY8xPRUGkzpNaNkMdC+40o5h4mFuLx82Zk4y2Yfteq009YsL BYQ5kwMecE8rT41mRnQRumuQFITPrto9KMr9F4CbSdFTDMeQMF73xCJ9ub+odeE3F334 UpJ4G3ZmaIBUOJnk8jxTnLE58bW1shqcdZ5rszH78amHwjmn4iagud3s2KWdKDGJ1EQ2 8hHwOsnXoOybWBnPTY3/VfOmv0M2jkzh9SDoewFPV9dOtOfydyk9ioVBEx9V59yVRtoI 4Vzw== X-Gm-Message-State: ALKqPwf4XdG751FOSMtBOcvMtevOC4VRrb7YbrtL9KT4WNnn6L5jndvi s8e5pEU2wS10ndwHwFnNWywRsw== X-Google-Smtp-Source: AB8JxZrkVv2G16xYS0cd86sutvMcfeEoteCZ04vUVpG2N+dYx9nHC3a7buzAieschk84AS+ptwr4Kg== X-Received: by 2002:a17:902:a582:: with SMTP id az2-v6mr6567840plb.98.1526591769959; Thu, 17 May 2018 14:16:09 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:09 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:26 -0700 Message-Id: <1526591733-4450-35-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915814 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="MJ+VFjSR"; 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 40n4Kd20Rzz9s37 for ; Fri, 18 May 2018 07:33:09 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id ECFC8EFE; Thu, 17 May 2018 21:16:39 +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 C4A37E6D for ; Thu, 17 May 2018 21:16:11 +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 909F76A3 for ; Thu, 17 May 2018 21:16:11 +0000 (UTC) Received: by mail-pg0-f67.google.com with SMTP id p9-v6so2345266pgc.9 for ; Thu, 17 May 2018 14:16:11 -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=MJ+VFjSRgxdXrBhnpOqGuXEFigSS+UZO8IdpojENLKZxcFfhyfIsHU0DY5z+pqBHkU O1Ws0uKr2RI9rQHh7cd4MTqrC0jfKfdlAwfK2KD6oqxJ/hra8LrPGnmqorp+tF6JTehe lLL2Lr1jYFGHEQ1M2LOoTEEguWtXHxf9ObcWGaQcWxyVeK7MCv5/W/btMMr9F/53kRa5 yX4yQ1YjsT8NH7SsmG4wvqExpV4Wz0iiHkXMOCT7JTgygsUo+TqhYHgkQsvRXvJ2IbcO 0d2wVJHDDMyvillOCja0YIiCxNB+l0C3yHzy1z/5yDJDPb+yn36Jw6sM/UE7iO7Hs5Ik Xkww== 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=kgtaCjARibo2z+FXPmN5ovtq1AuWI5CbVge45xu57WQU5kxhTiplZfOukcKM4k8ETE XVGqr+Vh1IStU0Oz1OfiPsjsPhAHT+0Bfe23LXCH2kZE8V+gp0+13XfqHMaia2qUMmSX UtVKh0h4m0oikJt3s4ti3OjJ+M3wGTjb/Us0npJXbCieG+i+Jg/yZY8VxVLddIDaYrZg kBCHbBZT9zZZMQltmkV8p4xYYwWGY0/IR+Lq2RPFQvE1WFz/RfxyLKo0M/g3cXSmSc2r a+rjCI3+RsJa1AOW6nOVlIn3pbksQ8Z9jT6h/Dp9C0f8dMBnnAI1Nn96uFOnewCHw745 uJ7A== X-Gm-Message-State: ALKqPwe8t/jzxGDZK1biOInbeSvf/RdDVi0K08xAlI718TCdMr6JZ8RJ 0u7qzxVjjcGxu2Ed3f/QHJ4l3Q== X-Google-Smtp-Source: AB8JxZroG6NiqJY/HSHW7IvY+afnGYUNfBDSVWUYOJzYl9RUXD+uF4Us0CTHMHN9qTXlexxAto0Jpg== X-Received: by 2002:a63:6706:: with SMTP id b6-v6mr5242965pgc.214.1526591770901; Thu, 17 May 2018 14:16:10 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:10 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:27 -0700 Message-Id: <1526591733-4450-36-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915815 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="htGGp611"; 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 40n4LB0c7Mz9s28 for ; Fri, 18 May 2018 07:33:38 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8FB11FC8; Thu, 17 May 2018 21:16: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 1B2B6F08 for ; Thu, 17 May 2018 21:16:13 +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 BC4F56A2 for ; Thu, 17 May 2018 21:16:12 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id v7-v6so2374257pgs.0 for ; Thu, 17 May 2018 14:16:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4Jw8prR/6YlZpqCSVnDahtCXtFXLy8O9zvllDmNkO7c=; b=htGGp611pC2/2iUqRiCCX5bzEvchOnVGT1dkQe8xy11EalWsNky/vlDgGnwKRK+GGD u5pnf1oNEna9ITJMECNAYNiC1EogT155Wy3yVnmYpsrudS4TbYHpXm5hvvOMloPNJVKR 1QBQOq5/KKaTjL9Xkxh6AiFAzJtoqtRRbNoJImQD1ZdvivGzzXGpLoRHFNnBFL5/+Rft yDcd9ZnRyNFUzzGTG4ECwKH48eLCFQ6jeVakV6mKfv3bXNBA9IDlymUzyMJjmu+CHMMC vlfgaSEFJiRqilw6+mdiLUGafzSJmViZ+dITUhCNBDCsw1IytdVpPeV3nHXjAVUe0PoW +DoA== 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=IQDoCAihk75lTCTSHGAxWyvNgBBt1gqyar1BKLT6u4UeeD6XAOPTXtmPc09yd6KrJj 9w5hRRzX4y+Q7h+SXLVi+FvzMIg3KRhFngqU/WrG2ewKHC0UnpaAHBxsNXfu6OvvE8SP 1C5h6Lkl8IbyeUG+H5RgPVectS3KEU8XkzSm7vbX7mQBVxLEf4kNq5LZ/SNR1w9I7UeN tEnbMlZA/X7UnstzAxhGoTGzoUR88Ciq3UFpt9zSLims6MR1gSR8Q6Q5o061DCw8opAN ygUfiT3lNZOkw41JUW80Vq+ezK5OcgVa+USkN2Q1w/Bg7znHtotTnSKYkQUGMcObFsYj c2aQ== X-Gm-Message-State: ALKqPwcpNKJpb4yWwxlWUXDvKBRfk6MdCw5y5iNgl8ZnIzL+nPFKXMq0 m4J/iImvUSb9PuWtE2H6MnP3+w== X-Google-Smtp-Source: AB8JxZouBWoRHbnW9wOeCq6OPUqgad6T2kv5jESlZioYTdUh13Q2VLPjC5T/t33R+rA4V04OkktzRA== X-Received: by 2002:a63:7804:: with SMTP id t4-v6mr5357192pgc.323.1526591772049; Thu, 17 May 2018 14:16:12 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:11 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:28 -0700 Message-Id: <1526591733-4450-37-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915816 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="I83PUHpR"; 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 40n4Lk18jTz9s37 for ; Fri, 18 May 2018 07:34:06 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 9AED9FD0; Thu, 17 May 2018 21:16: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 C862DED2 for ; Thu, 17 May 2018 21:16:13 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 813C06DA for ; Thu, 17 May 2018 21:16:13 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id o76-v6so2684728pfi.5 for ; Thu, 17 May 2018 14:16:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uo9suIz8j3U5mzDWGfjg7845xUPK37Kcwx6xBEG/u5Q=; b=I83PUHpRKy7hv7XOBuAOeb6WcmXhmZ6/1WMIsUOhWnFZEe2uXRx4jGija8xHfqtiJe GJcHBMJYiJ+yUH7N00u/lypLowjtLPHb8BSUwrrtQUa53mZrvJatyQf1FCB3CVB+oX7V rRu1fvAPWqHuYFgZDEgmWjC78bC6YMRclGQzUj0slTBkRbyy5+Sz4LeaAsh9OkJis905 5ZQZTc+QMTV0BpT6Wmu03yYg+GJwYO3Pd810SxhNeLvhmIhX/wYnNbz+xO7FIibERChj Bdv4gEM+e/1t0jUH3aBXb8ICBB+I48GbEs10gM5tl/Dubu+qaoweNDVIbhge2yPflfeA c4BA== 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=fU3oiLrpD5X/gVmWjVmmDjGa8YxDsPZiZ6x1toBZn3Av8ReFALQ2EwXuyQlKRSM2in 1H30o9cOSu7MyBQsQ9PeuIgtnv1w/ChzWE1jp9JrcTpiRcrxmP8Vh6yYkiTmHO/n51q/ qN43PbJJmw2k1QstwINWJRpC23dinMfdZ+Mix7QsCBFPs36/yfAG7Lqn5cdzCBCDzhxd 4/aY7vwr4ojVAAC89Ta9UuooihWdaprdUz+L3t909/ODibu3HQDnXQFee1ZMs0XaUx0x GtSuaP81OZUMBHhhkoFbg6f/HJyqq+wn5uvSCMHktdschxEW+rlAGEdzjND0tABSWlQN msVg== X-Gm-Message-State: ALKqPwcjiRJcU+JyZ9wpqtwM1x9LwtxStEctx+HA5jf8C7KCCAAG1YgM EtDk/FsOGz0ZqWfQ2RAoLifWMQ== X-Google-Smtp-Source: AB8JxZrosKymzVZQgmxLEIB0sv5qcdxAKWxcRjrQBRJlxKxb8qeqAAylRq9PXOa1tz1GTaKzbmBA5g== X-Received: by 2002:a65:5bcc:: with SMTP id o12-v6mr5194653pgr.449.1526591772877; Thu, 17 May 2018 14:16:12 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:12 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:29 -0700 Message-Id: <1526591733-4450-38-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915817 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="aphAnUWU"; 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 40n4MG6f4dz9s37 for ; Fri, 18 May 2018 07:34:34 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 2F1B2FCB; Thu, 17 May 2018 21:16:44 +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 853E7F21 for ; Thu, 17 May 2018 21:16:14 +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 5B74EE5 for ; Thu, 17 May 2018 21:16:14 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id u8-v6so2343240pgp.13 for ; Thu, 17 May 2018 14:16:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iKVwVzQJtjvLr4HvCNIxobDiu4f1VIn5ghU4rjx0Uy0=; b=aphAnUWUj4tGEc3SJZw4jIj/JYKO1cPeEZWuOzCovgx1UC/wLsjiTKYdfw58wKvTx7 76j+EbP4xDfrZPjNHZPMbcjTwzl47YJ05ht5xihX7nEUvWbr/C9ODjiv8a1hb+rZliIV WkDtxPpz9HXpyTXg1a7T4GvBsurxxPubWgKc3EocTneJanWnDYxqyqXtkdx81TZOQ34V iG0cvAzGDazyUcSlkUYjDumCRnpjkr96Osjccg3/fiUh5D1hF4NmBVmIh1rvYVBIwABG aInn7V9jWoyREDJI2H3XKYnyCB2m+VVmd29EVi13p1fujpJbusknjxWc9wZ4Ewed9D++ NhYA== 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=iKVwVzQJtjvLr4HvCNIxobDiu4f1VIn5ghU4rjx0Uy0=; b=Ukdq47qhDW00+3TcDWtGdPYd96vPZLbDlB0ICGY/YJ0L1F2cmjLHaKg/EGv7dgluCE dcHjeVQEZhufIUsfrNOSl0K7lgZkg3YkJfLElkEBWmL6gYscTT/pBOgGQRFouA+xq6Ef PxngiUPquwFvfCZq0e3T/B7HYhR6FSyAfjDcwUj7/pe2pxBlnvMo5Jwq364wuDRCQov/ FYEJvQxW8BYjRR8j9wcpgJ5jfPWT4rpPtRpPCPmUE66ii7+vi993O8UTm4svvrOsNNCY 0/qAX9jeL3FPWr96+oAPy1hZ9l4cUxJdJ7ppPgOY0mOxcSSCSt+uQJDMNHSWSdjsWX7c QeIA== X-Gm-Message-State: ALKqPwcDWP90gHL5GLh28aVCbp3VAQoz8jIoVV2CkS5cjH2EhYC1l1Pq +aWxhnGMmAbJkeG3a6pSewtIuQ== X-Google-Smtp-Source: AB8JxZozTPRkHaX3S2tj7JvwT3vH2FBuuCE6Axu4lSL2MoJSJE9AuBJzOMaSA7wDje8Ez3Acw2B9BA== X-Received: by 2002:a65:5b8a:: with SMTP id i10-v6mr956132pgr.352.1526591773762; Thu, 17 May 2018 14:16:13 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:13 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:30 -0700 Message-Id: <1526591733-4450-39-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 --- 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 29b5fb8..acc1586 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -2885,7 +2885,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 Thu May 17 21:15: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: 915818 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="LvOcoA1Z"; 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 40n4Mr3pWpz9s37 for ; Fri, 18 May 2018 07:35:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 08756FD8; Thu, 17 May 2018 21:16:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B3E64ED2 for ; Thu, 17 May 2018 21:16:15 +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 60FECE5 for ; Thu, 17 May 2018 21:16:15 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id c19-v6so3274047pls.6 for ; Thu, 17 May 2018 14:16:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=s4xT+Maj0ypq5XAqKLn9VglV89jRmLAcLKT4xq80cms=; b=LvOcoA1Z+fEb5WFW5MnEoWQ7HyQJ1ySCH/WMi+sBxMG2EEtql+ghhf/OK+r6RCnNkZ 2XdStK/bjtF9W4sPBWatFK830WduGM5bNlyFcaOvzQ4a96KifFDYE4iFgswJ4DW4Q/sr Q3ghwJd0c6JTjuAyInGZsDpx8FYVrpwYhFkec9VGbmXsYrf9jygHp4bKU/kV3fNcHjjS MZGrnGlUDYgYW4h9QJUFHNXXSmFq0isGD7+rDqgfRDKOnsV9OL+erKlmTOd4InaPGnUT 1hBiox60pOujxtZV2d5WViCo2MwWYlxj5tuzxUTfEGKt4ZUNKJb0ZWVhvYO1F3w0zAt7 kmZA== 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=HCXEVqsDhKhhpunw+asN9EH7FLx5dDG/EEeGA8xg/yV2gdJhC8vKBm3wnTdDTEWC6t F267cyuCmvdvbUsdklw5DRnBXx8g4UhWTl4ODp9AtynBw9pxLaiWt35qv7oS4zq5f3wd LKbuUgnViFSno8Qmdxoj9EK2jeo8HPB72DzKFKSaayxMIlm/AqQi4jrwvC9EwmyfKB6i M7htBusl0LFnWALInzsGdyhgg75x/W9OG7vpxf86KHeD19iBW9ub7SherP1mVvMyDttD zI+Xni3OLqfHAWryM+eNr2OMQx4lB+l3SiHv478Gtf+38xTE6eAoi88ewq64Rdz+yoAK gSLA== X-Gm-Message-State: ALKqPwdB0/gN8ehn3HRz+yHmid/JuTAtOUpwQ9/zZDMN9Zhq4ZbPHbmi KnRfIf2/2Mbcr/URN6zEwUBfrA== X-Google-Smtp-Source: AB8JxZoxX2WiMldTUR2WBZkudcz2ttjGJ56Hyj35BvNPmwMFz6d94TwIpZQvpZKMH3hNuO3bAUIqBg== X-Received: by 2002:a17:902:8f8b:: with SMTP id z11-v6mr6616794plo.203.1526591774660; Thu, 17 May 2018 14:16:14 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:14 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:31 -0700 Message-Id: <1526591733-4450-40-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915820 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="JrX62F/d"; 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 40n4Nz62S1z9s1w for ; Fri, 18 May 2018 07:36:03 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 283781011; Thu, 17 May 2018 21:16:55 +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 24688F14 for ; Thu, 17 May 2018 21:16:17 +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 79C1B6CF for ; Thu, 17 May 2018 21:16:16 +0000 (UTC) Received: by mail-pl0-f67.google.com with SMTP id n10-v6so3273069plp.0 for ; Thu, 17 May 2018 14:16:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ialQS4bWXLbkKIzfK2jAH9gDaWxY8I6EZlbVhIAhz5E=; b=JrX62F/dR7OK0AxdbIVmkMZO1R2Voa4Lf7mOmXZ7B9mOaGRE579pkvjAyvBjNKT7k6 U17ckTpVKNIclZBd22Kl7AfBij+7ZJ6aqBNdZEtqWqU+SlOklQOMXgOIXHTzCU7c/mn8 jJVD23yvqJ/9kVYZgnHlnZR2gOhapTOS5a4EeBv3aA6pAD0A9EBTHdLpw7Rjno9FlCbp fnvc1xMhJwK+oZhoHt/LlN3B2kYAB756dT4PdZxIf5avXSh8YIxbfNPs+HzqMTkzW/l0 uJ3XAGlwv3TnlhMQJSBxPb1kXRgRZL03GD/v/TWtJREnF9JWvCg2aQfGrpN1dO6L6hWH +bgg== 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=rxB7VfEc08IA5C+w/ypSaM+pXp44uL2l+e6euelY/ENWMSQt9j3AFqD8hw1RJGBA8Q hleKwpy/CkQ6s43qx9MgXebgbZeynQgFBn93IM8Ry1I3sY5QkKQYqdQQJU7Pr8y0GloX A6ms4d7s5JptxzYK+I+WSXFCK0Gy2TYtYKbdCOjmxGwDkp6VLtaKB7aI4i0u4XNLdBJP nwReaCv3nWtYuuF+xxtEmHJlNmpp1XA6pAl1W0BN0rCRq+CmdsrW5ge0IHb48VSNQMP1 Qb/UR5/LOGl9kLmo5S0FBYdH9ftxTfOYrO+nhkhHu/tNJz+Q+hoh0p83NwjdPELV5TBS QQtQ== X-Gm-Message-State: ALKqPwejoRBqTBoT+bRbeVLh/lolauXGw7BUbVugFOvOHfLGLdCpBoGS os9a/NjZ6z3DsmnD93Srer0DEg== X-Google-Smtp-Source: AB8JxZqNJ2Tk8d0uBrBudo0hdpxdjJSle/shgrCe0r4IckQsjU0SLg4+VKt3HVt2R8vnjuk3fXQXSQ== X-Received: by 2002:a17:902:c5:: with SMTP id a63-v6mr6721135pla.149.1526591775653; Thu, 17 May 2018 14:16:15 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:15 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:32 -0700 Message-Id: <1526591733-4450-41-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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 Thu May 17 21:15: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: 915819 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="OPvPtDmF"; 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 40n4NN1wWrz9s33 for ; Fri, 18 May 2018 07:35:32 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 13EA5FF7; Thu, 17 May 2018 21:16: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 E7F4AF14 for ; Thu, 17 May 2018 21:16:17 +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 848F76CF for ; Thu, 17 May 2018 21:16:17 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id u6-v6so3271010pls.9 for ; Thu, 17 May 2018 14:16:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+7npVpruVivgEdzdzlmzo2EG9C5oiUgfnBhOyaLQpTc=; b=OPvPtDmFvhApbKK41kWZtvMxIn9hAU49aQgXXUjaV/R1W4JSvjS8H6xL6Qv3lv7YYR AwLn5106sXpJlZvr/Duj6+Lz9WBV+cANitaRuOzoRwVbYbE9plN9Mk+WZc3nTBhEYSyr Z/lo7kD0f6VdLl75vXGCHsFJomr37ASBbu1vyHiTrRHRrnT2x8HBWFYyDsuLhr5aWWg6 pSseWXyyAQREU7tbgRySi7p6Qrf2yrKPwW+NfDTJODm3CSDLQCd2tcWxzhR84MGAfiiT 5BgOfRo0oDdX5tDfw4g9MN49H5IWNj/WSl/pzWulW/k+9+/7WMFeJsPWW7D6BBtgMs6N xY0g== 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=BhEgXkqme24QBiTRY2vEbyJH8osJ5gesub3a3CFss2x6WAZtvFsAburnqlEKE2Ypaw uDwRsaF7SDfeLx90ry0lfxs9f4TN49asY05gyiucK3bGB31j8pK8F2L7d2tfHWOakzyQ EPex7IkJMz1+axG/ZI05DY4D97HApMhJQVKYVg8Rpq0w7xuY7lJVW18/19r3oqo9m7rx emFHDjDWySO+5j0Wb99+LMYJqlKqq6rIohvL5lJ1FwG7RGO4I1DoZffXML2NslK5bUk0 ABNV0+9rl9tfKZxZSYiLKGVV3g0pB8/027J+piA1El+dbH7Pleoq0u8acKgSpLXQy+YP LgoA== X-Gm-Message-State: ALKqPwednjQSI2GtlPmdB9Qt8LQ7z5HUBJ5w/kOCONZ8JV+wIT+XoRBt zAAs823ZntUCapqzMTbjtXMXWg== X-Google-Smtp-Source: AB8JxZr2ZA5F1WniSZ4tux4iNQC29lPDmqDvhf9dETgB16i+8wmAnzCjp8Fl/F7d8R9m30aAOnm8PA== X-Received: by 2002:a17:902:9304:: with SMTP id bc4-v6mr6696302plb.189.1526591776891; Thu, 17 May 2018 14:16:16 -0700 (PDT) Received: from gizo.domain (97-115-125-157.ptld.qwest.net. [97.115.125.157]) by smtp.gmail.com with ESMTPSA id r68-v6sm12410581pfi.174.2018.05.17.14.16.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 May 2018 14:16:15 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Thu, 17 May 2018 14:15:33 -0700 Message-Id: <1526591733-4450-42-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1526591733-4450-1-git-send-email-gvrose8192@gmail.com> References: <1526591733-4450-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 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));