From patchwork Thu Dec 14 00:38:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Tu X-Patchwork-Id: 848330 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="WtCc64AF"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxvp03Dzxz9sRg for ; Thu, 14 Dec 2017 11:39:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751459AbdLNAjS (ORCPT ); Wed, 13 Dec 2017 19:39:18 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:32812 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750751AbdLNAjO (ORCPT ); Wed, 13 Dec 2017 19:39:14 -0500 Received: by mail-pf0-f196.google.com with SMTP id y89so2411222pfk.0 for ; Wed, 13 Dec 2017 16:39:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=VigiVnBf6XFeVHhlrWRBKZCkfVsLAE5rA8gj+aEsjg4=; b=WtCc64AFKnG1t7NQgajiYSn/xamgZRoicvHih0WTv7Pn6cjX0JyFoG0nb8Vf770q3o LO08LA1Xi8IlmCeMfjHEkbNZA3C+UgyjHg41OMl6H3SlN52xlg0n2Ia2inE2yNsKzw2M TSOXU0JQjxipHN2C0FbBDHGRyR7i5XKVLCFcuSsucSK4YyomIw1Ffl4xsxpm9l4WBaz0 +kWC9ERzPwaljHV+dDSzkJEMahDPUn2KAHNjTT1Z9vQs/l2XKYZ42MdjsxpoL0WN/Qd8 xz0kvLf9Qlxu57dgLU45RJaPxzRm+mxtsks71qil+BD+QLzshie/9JqZeiasffn/NrWT k2ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=VigiVnBf6XFeVHhlrWRBKZCkfVsLAE5rA8gj+aEsjg4=; b=WMXcGMTYgwRokFJHSNMGljpNoW2IrgMat/I8aZ9UaB0fgq2tmqXIcm+E0X6uYnRdDR 2r5m6eNa2jDEx56tJUXbXrdQ/UvKLSwbokpOqsYuvV4nPLWKfXmXhV5gbaqosLn/3aRm ruXuwvzVcHsd64gNRlrUhDhMFhpO8uDVwUZMCvE4N+DJ6tUFDci+vMMF9WNBWBz8MSNb iB/LAXfpxyc4TWq3DIg8o56GJ78HDyPOwHWSoIDInllastgkRYswlL7F42AYWJWFC3ke ePgjixTFN8sODsKxRoSxpQl6BwNYdT5ybTORpO/JSbcSSNImSvrsg26Rdb345JAAX1jg 8htg== X-Gm-Message-State: AKGB3mLHB72UwUU1lZnqz4mUDH9KAPDeZv2mjX9Tm1K52oPArHdXVx0k wt8I1H+TeAxG6qiAlW+r83dfuJYO X-Google-Smtp-Source: ACJfBovDLxR8l+tVtLTPocEkHx2U8UIw3xha2/29o/qXutrfeVObu9dRGJRJmapz1UgXSwb/Pa1QCA== X-Received: by 10.99.99.3 with SMTP id x3mr6813223pgb.414.1513211953359; Wed, 13 Dec 2017 16:39:13 -0800 (PST) Received: from sc9-mailhost3.vmware.com ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id e7sm5349938pfj.44.2017.12.13.16.39.12 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Dec 2017 16:39:12 -0800 (PST) From: William Tu To: netdev@vger.kernel.org Subject: [PATCH net-next 1/4] net: erspan: refactor existing erspan code Date: Wed, 13 Dec 2017 16:38:55 -0800 Message-Id: <1513211938-8749-2-git-send-email-u9012063@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com> References: <1513211938-8749-1-git-send-email-u9012063@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- include/net/erspan.h | 34 ++++++++++++++++++++++++---------- net/ipv4/ip_gre.c | 27 +++++++++++++++++---------- net/ipv6/ip6_gre.c | 25 ++++++++++++++++--------- net/openvswitch/flow_netlink.c | 8 ++++---- 4 files changed, 61 insertions(+), 33 deletions(-) diff --git a/include/net/erspan.h b/include/net/erspan.h index 6e758d08c9ee..70c40c7c75b2 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -15,7 +15,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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -27,7 +27,7 @@ * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ -#define ERSPAN_VERSION 0x1 +#define ERSPAN_VERSION 0x1 /* ERSPAN type II */ #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff @@ -44,20 +44,29 @@ enum erspan_encap_type { ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ }; +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 struct erspan_metadata { - __be32 index; /* type II */ + union { + __be32 index; /* Version 1 (type II)*/ + } u; }; -struct erspanhdr { +struct erspan_base_hdr { __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; }; +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; @@ -73,7 +82,8 @@ static inline void erspan_build_header(struct sk_buff *skb, { struct ethhdr *eth = eth_hdr(skb); enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; + struct erspan_base_hdr *ershdr; + struct erspan_metadata *ersmd; struct qtag_prefix { __be16 eth_type; __be16 tci; @@ -96,17 +106,21 @@ 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)); + 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_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); + + /* Build metadata */ + ersmd = (struct erspan_metadata *)(ershdr + 1); + ersmd->u.index = htonl(index & INDEX_MASK); } #endif diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d828821d88d7..3e37402147f3 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -256,34 +256,41 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, { struct net *net = dev_net(skb->dev); 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); 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. */ tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK); - index = ershdr->md.index; + pkt_md = (struct erspan_metadata *)(ershdr + 1); tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags | TUNNEL_KEY, iph->saddr, iph->daddr, tpi->key); 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; @@ -307,12 +314,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, if (!md) return PACKET_REJECT; - md->index = index; + memcpy(md, pkt_md, sizeof(*md)); info = &tun_dst->u.tun_info; info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); } else { - tunnel->index = ntohl(index); + tunnel->index = ntohl(pkt_md->u.index); } skb_reset_mac_header(skb); @@ -571,7 +578,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, key = &tun_info->key; /* ERSPAN has fixed 8 byte GRE header */ - tunnel_hlen = 8 + sizeof(struct erspanhdr); + tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); if (!rt) @@ -590,7 +597,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, goto err_free_rt; erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), - ntohl(md->index), truncate, true); + ntohl(md->u.index), truncate, true); gre_build_header(skb, 8, TUNNEL_SEQ, htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++)); @@ -1238,7 +1245,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; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 4562579797d1..1303d0c44c36 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -501,25 +501,32 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) 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 erspanhdr *ershdr; struct ip6_tnl *tunnel; - __be32 index; + u8 ver; ipv6h = ipv6_hdr(skb); - ershdr = (struct erspanhdr *)skb->data; + ershdr = (struct erspan_base_hdr *)skb->data; if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) return PACKET_REJECT; + ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK); - index = ershdr->md.index; + pkt_md = (struct erspan_metadata *)(ershdr + 1); tunnel = ip6gre_tunnel_lookup(skb->dev, &ipv6h->saddr, &ipv6h->daddr, tpi->key, tpi->proto); if (tunnel) { - if (__iptunnel_pull_header(skb, sizeof(*ershdr), + int len = erspan_hdr_len(ver); + + if (unlikely(!pskb_may_pull(skb, len))) + return -ENOMEM; + + if (__iptunnel_pull_header(skb, len, htons(ETH_P_TEB), false, false) < 0) return PACKET_REJECT; @@ -545,14 +552,14 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, if (!md) return PACKET_REJECT; - md->index = index; + memcpy(md, pkt_md, sizeof(*md)); info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); } else { - tunnel->parms.index = ntohl(index); + tunnel->parms.index = ntohl(pkt_md->u.index); ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error); } @@ -921,7 +928,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, goto tx_err; erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), - ntohl(md->index), truncate, false); + ntohl(md->u.index), truncate, false); } else { switch (skb->protocol) { @@ -1657,7 +1664,7 @@ static int ip6erspan_tap_init(struct net_device *dev) tunnel->tun_hlen = 8; 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 ipv6hdr); dev->hard_header_len = LL_MAX_HEADER + t_hlen; diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 624ea74353dd..bce1f78b0de5 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -644,12 +644,12 @@ static int erspan_tun_opt_from_nlattr(const struct nlattr *attr, BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts)); memset(&opts, 0, sizeof(opts)); - opts.index = nla_get_be32(attr); + opts.u.index = nla_get_be32(attr); /* Index has only 20-bit */ - if (ntohl(opts.index) & ~INDEX_MASK) { + if (ntohl(opts.u.index) & ~INDEX_MASK) { OVS_NLERR(log, "ERSPAN index number %x too large.", - ntohl(opts.index)); + ntohl(opts.u.index)); return -EINVAL; } @@ -907,7 +907,7 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, return -EMSGSIZE; else if (output->tun_flags & TUNNEL_ERSPAN_OPT && nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, - ((struct erspan_metadata *)tun_opts)->index)) + ((struct erspan_metadata *)tun_opts)->u.index)) return -EMSGSIZE; } From patchwork Thu Dec 14 00:38:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Tu X-Patchwork-Id: 848333 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QlFIg6pO"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxvpG139nz9sRg for ; Thu, 14 Dec 2017 11:39:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751730AbdLNAjc (ORCPT ); Wed, 13 Dec 2017 19:39:32 -0500 Received: from mail-pg0-f67.google.com ([74.125.83.67]:46143 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751084AbdLNAjP (ORCPT ); Wed, 13 Dec 2017 19:39:15 -0500 Received: by mail-pg0-f67.google.com with SMTP id b11so2241485pgu.13 for ; Wed, 13 Dec 2017 16:39:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=OIMXS3VloeguBxSumzkvxgE8u5YkUV7c9cFPkYbNF8s=; b=QlFIg6pOsw/8qK75/B53RfRV+Ji1uFU8N2Q0dQ6JQoD+J1Xw0KcDQSvI48kTQw7mk5 WghoBRy7JV9gK3mZLhCxNxXYlw3+s82vDJyBKio7bB1nSYmoZ8iKrMCja95VJjvKqoZV 5BJURx97U70oBvXI3c1ptRXm+h3up8n2HHYOUcrJaRzqEoS4feMmfgLXk1MFdkDqvCqh mafy5BtCVmX26f1bYy5P0Oz7Z1TI/HMBFWp2cgWxm2r1LBej3UQ2HSpINCtCej5CVMkq GKxw3tMj9wODYt+zQLILmZio7uOi0PVFPJtKUq8rvj7Pwu30tzHJ2kOWiafEnlc8A5KN cE6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=OIMXS3VloeguBxSumzkvxgE8u5YkUV7c9cFPkYbNF8s=; b=hkzTzbqNyPoe5eEz/WgVZJRMqOPsu09gr2rfnQ9yaWpe3CQ4XJWA1dNAz8+f78QBe3 if5H1+tpr/bquuR4x3W9+XZEbYiC69svHb1KBDoYTLrmKP47cRkyK8Fy7PekUGCduQ5d nfJhtCJDwsPrAIypRHkvhfETINBgWgFnlsMFOCIhWQ8m5HW08ELg4VkRZ9gu7NcZaukW 4DOwUfnDl4vpGztJehmSXZp3CkbHRC/ftnr6mrzGX8SuB7Z5D9eM4UGqup8ckWTJJtIe gqyVc0ba4bv7sCugmd9bYauoP4Dg7Il0ipbWtn0q//UjQcLRQPPMR0CQnGMoI8SA+epF FP2g== X-Gm-Message-State: AKGB3mJWRcyLUw+LZ0Fqeu0W9htawyoTAq8SJr314RsKBLFHSbVaNDuS zFys04lnPFiVBdSkqgTs1ywcdJe2 X-Google-Smtp-Source: ACJfBouvV3lRnDdielMys8g+F2fmYdHIFBRocCi3ppSOI3/Ktzt2yHqHhtAe2aiZJzdIscpIgpp/CQ== X-Received: by 10.99.45.4 with SMTP id t4mr6911067pgt.254.1513211954671; Wed, 13 Dec 2017 16:39:14 -0800 (PST) Received: from sc9-mailhost3.vmware.com ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id e7sm5349938pfj.44.2017.12.13.16.39.13 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Dec 2017 16:39:13 -0800 (PST) From: William Tu To: netdev@vger.kernel.org Subject: [PATCH net-next 2/4] net: erspan: introduce erspan v2 for ip_gre Date: Wed, 13 Dec 2017 16:38:56 -0800 Message-Id: <1513211938-8749-3-git-send-email-u9012063@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com> References: <1513211938-8749-1-git-send-email-u9012063@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- include/net/erspan.h | 120 ++++++++++++++++++++++++++++++++++++++++- include/net/ip_tunnels.h | 5 +- include/uapi/linux/if_ether.h | 1 + include/uapi/linux/if_tunnel.h | 3 ++ net/ipv4/ip_gre.c | 105 ++++++++++++++++++++++++++++++------ 5 files changed, 216 insertions(+), 18 deletions(-) diff --git a/include/net/erspan.h b/include/net/erspan.h index 70c40c7c75b2..acdf6843095d 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -24,11 +24,29 @@ * | 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 /* ERSPAN type II */ - #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff #define COS_MASK 0xe000 @@ -37,6 +55,28 @@ #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 + +/* ERSPAN version 2 metadata header */ +struct erspan_md2 { + __be32 timestamp; + __be16 sgt; /* security group tag */ + __be16 flags; +#define P_OFFSET 15 +#define FT_OFFSET 10 +#define HWID_OFFSET 4 +#define DIR_OFFSET 3 +#define GRA_OFFSET 1 +}; + enum erspan_encap_type { ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ @@ -48,8 +88,10 @@ enum erspan_encap_type { #define ERSPAN_V2_MDSIZE 8 struct erspan_metadata { union { - __be32 index; /* Version 1 (type II)*/ + __be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ } u; + int version; }; struct erspan_base_hdr { @@ -58,6 +100,7 @@ struct erspan_base_hdr { __be16 session_id; #define COS_OFFSET 13 #define EN_OFFSET 11 +#define BSO_OFFSET EN_OFFSET #define T_OFFSET 10 }; @@ -123,4 +166,77 @@ static inline void erspan_build_header(struct sk_buff *skb, ersmd->u.index = 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, + __be32 id, u8 direction, u16 hwid, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = eth_hdr(skb); + struct erspan_base_hdr *ershdr; + struct erspan_metadata *md; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u16 session_id; + 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_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION2 << VER_OFFSET)); + session_id = (u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | + (bso << BSO_OFFSET & BSO_MASK) | + ((truncate << T_OFFSET) & T_MASK); + ershdr->session_id = htons(session_id); + + /* Build metadata */ + md = (struct erspan_metadata *)(ershdr + 1); + md->u.md2.timestamp = erspan_get_timestamp(); + md->u.md2.sgt = htons(sgt); + md->u.md2.flags = htons(((1 << P_OFFSET) & P_MASK) | + ((hwid << HWID_OFFSET) & HWID_MASK) | + ((direction << DIR_OFFSET) & DIR_MASK) | + ((gra << GRA_OFFSET) & GRA_MASK)); +} + #endif diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 24628f6b09bf..1f16773cfd76 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -116,8 +116,11 @@ struct ip_tunnel { u32 o_seqno; /* The last output seqno */ int tun_hlen; /* Precalculated header length */ - /* This field used only by ERSPAN */ + /* 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; diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 3ee3bf7c8526..87b7529fcdfe 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -47,6 +47,7 @@ #define ETH_P_PUP 0x0200 /* Xerox PUP packet */ #define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ #define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */ +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_X25 0x0805 /* CCITT X.25 */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h index e68dadbd6d45..1b3d148c4560 100644 --- a/include/uapi/linux/if_tunnel.h +++ b/include/uapi/linux/if_tunnel.h @@ -137,6 +137,9 @@ enum { IFLA_GRE_IGNORE_DF, IFLA_GRE_FWMARK, IFLA_GRE_ERSPAN_INDEX, + IFLA_GRE_ERSPAN_VER, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, __IFLA_GRE_MAX, }; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 3e37402147f3..004800b923c6 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -315,11 +315,26 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, return PACKET_REJECT; memcpy(md, pkt_md, sizeof(*md)); + md->version = ver; + info = &tun_dst->u.tun_info; info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); } else { - tunnel->index = ntohl(pkt_md->u.index); + tunnel->erspan_ver = ver; + if (ver == 1) { + tunnel->index = ntohl(pkt_md->u.index); + } else { + u16 md2_flags; + u16 dir, hwid; + + md2_flags = ntohs(pkt_md->u.md2.flags); + dir = (md2_flags & DIR_MASK) >> DIR_OFFSET; + hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; + tunnel->dir = dir; + tunnel->hwid = hwid; + } + } skb_reset_mac_header(skb); @@ -413,7 +428,8 @@ static int gre_rcv(struct sk_buff *skb) 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; } @@ -568,6 +584,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, bool truncate = false; struct flowi4 fl; int tunnel_hlen; + int version; __be16 df; tun_info = skb_tunnel_info(skb); @@ -576,9 +593,13 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, 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 */ - tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; + version = md->version; + tunnel_hlen = 8 + erspan_hdr_len(version); rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); if (!rt) @@ -592,12 +613,23 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, truncate = true; } - md = ip_tunnel_info_opts(tun_info); - if (!md) - goto err_free_rt; + if (version == 1) { + erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), + ntohl(md->u.index), truncate, true); + } else if (version == 2) { + u16 md2_flags; + u8 direction; + u16 hwid; - erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), - ntohl(md->u.index), truncate, true); + md2_flags = ntohs(md->u.md2.flags); + direction = (md2_flags & DIR_MASK) >> DIR_OFFSET; + hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; + + erspan_build_header_v2(skb, tunnel_id_to_key32(key->tun_id), + direction, hwid, truncate, true); + } else { + goto err_free_rt; + } gre_build_header(skb, 8, TUNNEL_SEQ, htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++)); @@ -699,8 +731,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; @@ -1172,13 +1210,32 @@ static int ipgre_netlink_parms(struct net_device *dev, if (data[IFLA_GRE_FWMARK]) *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); - if (data[IFLA_GRE_ERSPAN_INDEX]) { - t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + if (data[IFLA_GRE_ERSPAN_VER]) { + t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); - if (t->index & ~INDEX_MASK) + if (t->erspan_ver != 1 && t->erspan_ver != 2) return -EINVAL; } + if (t->erspan_ver == 1) { + if (data[IFLA_GRE_ERSPAN_INDEX]) { + t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); + if (t->index & ~INDEX_MASK) + return -EINVAL; + } + } else if (t->erspan_ver == 2) { + if (data[IFLA_GRE_ERSPAN_DIR]) { + t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); + if (t->dir & ~(DIR_MASK >> DIR_OFFSET)) + return -EINVAL; + } + if (data[IFLA_GRE_ERSPAN_HWID]) { + t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); + if (t->hwid & ~(HWID_MASK >> HWID_OFFSET)) + return -EINVAL; + } + } + return 0; } @@ -1245,7 +1302,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; @@ -1375,6 +1432,12 @@ static size_t ipgre_get_size(const struct net_device *dev) nla_total_size(4) + /* 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; } @@ -1417,9 +1480,18 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) goto nla_put_failure; } - if (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; @@ -1455,6 +1527,9 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, [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 struct rtnl_link_ops ipgre_link_ops __read_mostly = { From patchwork Thu Dec 14 00:38:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Tu X-Patchwork-Id: 848332 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="qc5C75+P"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxvp71dcfz9sRg for ; Thu, 14 Dec 2017 11:39:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751577AbdLNAjZ (ORCPT ); Wed, 13 Dec 2017 19:39:25 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:38743 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751101AbdLNAjR (ORCPT ); Wed, 13 Dec 2017 19:39:17 -0500 Received: by mail-pf0-f195.google.com with SMTP id u25so2399630pfg.5 for ; Wed, 13 Dec 2017 16:39:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=JG0C5XBK3bIEEP92SDOBKRLHHdwOjO5byIGqEZTZaBw=; b=qc5C75+PkoQo7vKg13LRcZ/Drf4f3h4L23FO49R+yl5/9uj0UmBYk2TRP9U3MSSkFA LoEjXidk7fSepGysMtDoEc3b7KZ8rVUhsTB9YSTujaMcketFYlz7igEwWCD6PKkdDjH2 kw3dKOAS2xBIArHkX3uYfkrvdW+0uS3nIUlHSyH1UFgtnlX89/cnrqmgpnUPiBl9f/2j 2ftUakhUU2nD7a5dQjw7mP06V+/hUO6euN5OxtQC0UFROlA2Iw7VkNa1EiCqYIHplOfO BP9IwecAZXMa66Jz02gFOrNS3onPavNxg7sRMtXw2kuX4k2KMH2yO9gMukzfeM0iWEBR L2OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=JG0C5XBK3bIEEP92SDOBKRLHHdwOjO5byIGqEZTZaBw=; b=q7qexU6FkQxcQzml4afCyvNLEnUrpkgJWj8JIV0n07SmWUsi0nxn9zvggcMdpnsWhx ISOh8pRlDeYHE0r+7geUakfbTO7D1bIJOpMVEtoiuvteQbjiEfJnODLofDafUDSEHqL8 nTaWc3EUXVaDfeKhUoRTWxNFfLtf5hZp6QP2w0pIwCEwmR1a/vBPUf+uCMnBLCCCsJn5 Q1lTLQu8bHTO0KR6a0OypEUnWuWo+Yz2KhjmilsJ5wMV4o7/wUcywwH9mMnmcM6Cphed izV12tEHIo1ZwR6cKJeYk1nLUpUcoP8m8fYISRfAtm/ss9P/OrZwKQCAEjqwNmDvtxvz RTiw== X-Gm-Message-State: AKGB3mLCopM4AhSZJWXjhjsIchZA4XO3SJFBgpHhuzE9t0GAXEn/0e7E NyvfRj1getyOLYMyIxvHStaYPxlw X-Google-Smtp-Source: ACJfBouaDLDkqiJVTb3ydWAiqGFOIzJDQvty9G9iieZTGY+CU1JUKCn+INu99DS67jA8kD+qoz85WA== X-Received: by 10.99.165.75 with SMTP id r11mr6900914pgu.331.1513211956311; Wed, 13 Dec 2017 16:39:16 -0800 (PST) Received: from sc9-mailhost3.vmware.com ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id e7sm5349938pfj.44.2017.12.13.16.39.14 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Dec 2017 16:39:14 -0800 (PST) From: William Tu To: netdev@vger.kernel.org Subject: [PATCH net-next 3/4] ip6_gre: add erspan v2 support Date: Wed, 13 Dec 2017 16:38:57 -0800 Message-Id: <1513211938-8749-4-git-send-email-u9012063@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com> References: <1513211938-8749-1-git-send-email-u9012063@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Similar to support for ipv4 erspan, this patch adds erspan v2 to ip6erspan tunnel. Signed-off-by: William Tu --- include/net/ip6_tunnel.h | 3 ++ net/ipv6/ip6_gre.c | 120 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 107 insertions(+), 16 deletions(-) diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index 109a5a8877ef..236e40ba06bf 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -37,6 +37,9 @@ struct __ip6_tnl_parm { __u32 fwmark; __u32 index; /* ERSPAN type II index */ + __u8 erspan_ver; /* ERSPAN version */ + __u8 dir; /* direction */ + __u16 hwid; /* hwid */ }; /* IPv6 tunnel */ diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 1303d0c44c36..5c9c65f1d5c2 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -553,13 +553,28 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, return PACKET_REJECT; memcpy(md, pkt_md, sizeof(*md)); + md->version = ver; info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); } else { - tunnel->parms.index = ntohl(pkt_md->u.index); + tunnel->parms.erspan_ver = ver; + + if (ver == 1) { + tunnel->parms.index = ntohl(pkt_md->u.index); + } else { + u16 md2_flags; + u16 dir, hwid; + + md2_flags = ntohs(pkt_md->u.md2.flags); + dir = (md2_flags & DIR_MASK) >> DIR_OFFSET; + hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; + tunnel->parms.dir = dir; + tunnel->parms.hwid = hwid; + } + ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error); } @@ -582,7 +597,8 @@ static int gre_rcv(struct sk_buff *skb) if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) 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 (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD) return 0; goto drop; @@ -927,9 +943,24 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, if (!md) goto tx_err; - erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), - ntohl(md->u.index), truncate, false); - + if (md->version == 1) { + erspan_build_header(skb, + tunnel_id_to_key32(key->tun_id), + ntohl(md->u.index), truncate, + false); + } else if (md->version == 2) { + u16 md2_flags; + u16 dir, hwid; + + md2_flags = ntohs(md->u.md2.flags); + dir = (md2_flags & DIR_MASK) >> DIR_OFFSET; + hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; + + erspan_build_header_v2(skb, + tunnel_id_to_key32(key->tun_id), + dir, hwid, truncate, + false); + } } else { switch (skb->protocol) { case htons(ETH_P_IP): @@ -949,8 +980,15 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, break; } - erspan_build_header(skb, t->parms.o_key, t->parms.index, - truncate, false); + if (t->parms.erspan_ver == 1) + erspan_build_header(skb, t->parms.o_key, + t->parms.index, + truncate, false); + else + erspan_build_header_v2(skb, t->parms.o_key, + t->parms.dir, + t->parms.hwid, + truncate, false); fl6.daddr = t->parms.raddr; } @@ -1514,7 +1552,7 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { __be16 flags = 0; - int ret; + int ret, ver = 0; if (!data) return 0; @@ -1543,12 +1581,35 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[], (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) return -EINVAL; - if (data[IFLA_GRE_ERSPAN_INDEX]) { - u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); - - if (index & ~INDEX_MASK) + 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; } @@ -1598,11 +1659,21 @@ static void ip6gre_netlink_parms(struct nlattr *data[], if (data[IFLA_GRE_FWMARK]) parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); - if (data[IFLA_GRE_ERSPAN_INDEX]) - parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); - 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) @@ -1664,7 +1735,7 @@ static int ip6erspan_tap_init(struct net_device *dev) tunnel->tun_hlen = 8; tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + - sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE; + erspan_hdr_len(tunnel->parms.erspan_ver); t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); dev->hard_header_len = LL_MAX_HEADER + t_hlen; @@ -1932,6 +2003,19 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) 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: @@ -1957,6 +2041,9 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = { [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) @@ -2078,4 +2165,5 @@ MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); MODULE_ALIAS_RTNL_LINK("ip6gre"); MODULE_ALIAS_RTNL_LINK("ip6gretap"); +MODULE_ALIAS_RTNL_LINK("ip6erspan"); MODULE_ALIAS_NETDEV("ip6gre0"); From patchwork Thu Dec 14 00:38:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Tu X-Patchwork-Id: 848331 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="oCz3bEGB"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxvp173kTz9t3r for ; Thu, 14 Dec 2017 11:39:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751508AbdLNAjT (ORCPT ); Wed, 13 Dec 2017 19:39:19 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:44604 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751438AbdLNAjS (ORCPT ); Wed, 13 Dec 2017 19:39:18 -0500 Received: by mail-pf0-f194.google.com with SMTP id m26so2390286pfj.11 for ; Wed, 13 Dec 2017 16:39:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=I6OEf/vvji+7JXXtMhtRnAmAtJrFKTIp966V7b4tpFw=; b=oCz3bEGBkKljCc54ZY20mHzgCOC4+dLRLfxkG88rgQPGdzTQC4njdqj1JEoPkyme44 QFcEtMDA8ET+5drssIq0DAVOTm3FZYQFni1kT7sCzFuGCqHLEoq0Wl3obBi46MnCqFdg o2VdKHBZMOXjA6evu0lrKvlVZUZLWcr2Rv36uobUKLt/p7wP5hYc/sJ8XoMD+r7FwMyx xefZAFN4JfkdqDiwlDvVXLdnJfVsicsg3UfVFgn2oYRTn7eRrZxDS2WMf7+jb0UhHzP2 WWlOgTGe+LlZ18e52/zYs6fvOUapcjh7jZIiWIXTjlt8oZsCPh3/E3FQzZ3djfkJFz27 ZHMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=I6OEf/vvji+7JXXtMhtRnAmAtJrFKTIp966V7b4tpFw=; b=auWhcUfy98SncOZ+8HI/TZ6AFtEruUSBVfnZWsnjS/JkAFGKVrrC5o0UXwunormwOE I7vvCXl5pTMgeHYbSvZ6a0AwUy4E+xyMkwnxG5Y9ynhpm9Rx/CWmwgy1ZQOedDyY6Qes ZcQr6kyUjhZo81LNp/BSy0l7Cp/6kl2VxgqM4TwgPjySH23v8MuCjJt7xtK/6Pn1Nn4D +wL+JNKjh7qea17iIUxeIgTFpoiMZx7Hwj6EvB98O7ytbSeGej9P1hofjdVidxhf7pKW l7sFE4PezlnZgzLSnkFetcaDnwJ2C3l5aey0Ruw1G4ZbxVb+DZd3qzslmxf9A2U2pErK tmCw== X-Gm-Message-State: AKGB3mLJEZIDFm/xEbUgUQnA6cf+Kr+RZaHtFqN3A8nG0E8e/+g/9txQ TgX3Rp38YtUPxC0b8Fi0gMnOBePW X-Google-Smtp-Source: ACJfBovKwqtRLC7P0Tvbi92EgbRP3KJZ4vtU94olnLZZxw8WRdIH8vnWRjzZoCO+d3OMGD+oAJxH8Q== X-Received: by 10.99.137.194 with SMTP id v185mr6830460pgd.160.1513211957413; Wed, 13 Dec 2017 16:39:17 -0800 (PST) Received: from sc9-mailhost3.vmware.com ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id e7sm5349938pfj.44.2017.12.13.16.39.16 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Dec 2017 16:39:16 -0800 (PST) From: William Tu To: netdev@vger.kernel.org Subject: [PATCH net-next 4/4] samples/bpf: add erspan v2 sample code Date: Wed, 13 Dec 2017 16:38:58 -0800 Message-Id: <1513211938-8749-5-git-send-email-u9012063@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com> References: <1513211938-8749-1-git-send-email-u9012063@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Extend the existing tests for ipv4 ipv6 erspan version 2. Signed-off-by: William Tu --- samples/bpf/tcbpf2_kern.c | 77 +++++++++++++++++++++++++++++++++++++----- samples/bpf/test_tunnel_bpf.sh | 38 +++++++++++++++------ 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/samples/bpf/tcbpf2_kern.c b/samples/bpf/tcbpf2_kern.c index 79ad061079dd..f6bbf8f50da3 100644 --- a/samples/bpf/tcbpf2_kern.c +++ b/samples/bpf/tcbpf2_kern.c @@ -35,12 +35,22 @@ struct geneve_opt { u8 opt_data[8]; /* hard-coded to 8 byte */ }; +struct erspan_md2 { + __be32 timestamp; + __be16 sgt; + __be16 flags; +}; + struct vxlan_metadata { u32 gbp; }; struct erspan_metadata { - __be32 index; + union { + __be32 index; + struct erspan_md2 md2; + } u; + int version; }; SEC("gre_set_tunnel") @@ -143,7 +153,18 @@ int _erspan_set_tunnel(struct __sk_buff *skb) return TC_ACT_SHOT; } - md.index = htonl(123); + __builtin_memset(&md, 0, sizeof(md)); +#ifdef ERSPAN_V1 + md.version = 1; + md.u.index = htonl(123); +#else + u8 direction = 1; + u16 hwid = 7; + + md.version = 2; + md.u.md2.flags = htons((direction << 3) | (hwid << 4)); +#endif + ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); if (ret < 0) { ERROR(ret); @@ -156,7 +177,7 @@ int _erspan_set_tunnel(struct __sk_buff *skb) SEC("erspan_get_tunnel") int _erspan_get_tunnel(struct __sk_buff *skb) { - char fmt[] = "key %d remote ip 0x%x erspan index 0x%x\n"; + char fmt[] = "key %d remote ip 0x%x erspan version %d\n"; struct bpf_tunnel_key key; struct erspan_metadata md; u32 index; @@ -174,9 +195,22 @@ int _erspan_get_tunnel(struct __sk_buff *skb) return TC_ACT_SHOT; } - index = bpf_ntohl(md.index); bpf_trace_printk(fmt, sizeof(fmt), - key.tunnel_id, key.remote_ipv4, index); + key.tunnel_id, key.remote_ipv4, md.version); + +#ifdef ERSPAN_V1 + char fmt2[] = "\tindex %x\n"; + + index = bpf_ntohl(md.u.index); + bpf_trace_printk(fmt2, sizeof(fmt2), index); +#else + char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; + + bpf_trace_printk(fmt2, sizeof(fmt2), + (ntohs(md.u.md2.flags) >> 3) & 0x1, + (ntohs(md.u.md2.flags) >> 4) & 0x3f, + bpf_ntohl(md.u.md2.timestamp)); +#endif return TC_ACT_OK; } @@ -201,7 +235,19 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) return TC_ACT_SHOT; } - md.index = htonl(123); + __builtin_memset(&md, 0, sizeof(md)); + +#ifdef ERSPAN_V1 + md.u.index = htonl(123); + md.version = 1; +#else + u8 direction = 0; + u16 hwid = 17; + + md.version = 2; + md.u.md2.flags = htons((direction << 3) | (hwid << 4)); +#endif + ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); if (ret < 0) { ERROR(ret); @@ -214,7 +260,7 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) SEC("ip4ip6erspan_get_tunnel") int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) { - char fmt[] = "key %d remote ip6 ::%x erspan index 0x%x\n"; + char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n"; struct bpf_tunnel_key key; struct erspan_metadata md; u32 index; @@ -232,9 +278,22 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) return TC_ACT_SHOT; } - index = bpf_ntohl(md.index); bpf_trace_printk(fmt, sizeof(fmt), - key.tunnel_id, key.remote_ipv6[0], index); + key.tunnel_id, key.remote_ipv4, md.version); + +#ifdef ERSPAN_V1 + char fmt2[] = "\tindex %x\n"; + + index = bpf_ntohl(md.u.index); + bpf_trace_printk(fmt2, sizeof(fmt2), index); +#else + char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; + + bpf_trace_printk(fmt2, sizeof(fmt2), + (ntohs(md.u.md2.flags) >> 3) & 0x1, + (ntohs(md.u.md2.flags) >> 4) & 0x3f, + bpf_ntohl(md.u.md2.timestamp)); +#endif return TC_ACT_OK; } diff --git a/samples/bpf/test_tunnel_bpf.sh b/samples/bpf/test_tunnel_bpf.sh index f53efb62f699..ae7f7c38309b 100755 --- a/samples/bpf/test_tunnel_bpf.sh +++ b/samples/bpf/test_tunnel_bpf.sh @@ -59,8 +59,17 @@ function add_ip6gretap_tunnel { function add_erspan_tunnel { # in namespace - ip netns exec at_ns0 \ - ip link add dev $DEV_NS type $TYPE seq key 2 local 172.16.1.100 remote 172.16.1.200 erspan 123 + if [ "$1" == "v1" ]; then + ip netns exec at_ns0 \ + ip link add dev $DEV_NS type $TYPE seq key 2 \ + local 172.16.1.100 remote 172.16.1.200 \ + erspan_ver 1 erspan 123 + else + ip netns exec at_ns0 \ + ip link add dev $DEV_NS type $TYPE seq key 2 \ + local 172.16.1.100 remote 172.16.1.200 \ + erspan_ver 2 erspan_dir 1 erspan_hwid 3 + fi ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 @@ -79,10 +88,17 @@ function add_ip6erspan_tunnel { ip link set dev veth1 up # in namespace - ip netns exec at_ns0 \ - ip link add dev $DEV_NS type $TYPE seq key 2 erspan 123 \ - local ::11 remote ::22 - + if [ "$1" == "v1" ]; then + ip netns exec at_ns0 \ + ip link add dev $DEV_NS type $TYPE seq key 2 \ + local ::11 remote ::22 \ + erspan_ver 1 erspan 123 + else + ip netns exec at_ns0 \ + ip link add dev $DEV_NS type $TYPE seq key 2 \ + local ::11 remote ::22 \ + erspan_ver 2 erspan_dir 1 erspan_hwid 7 + fi ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip link set dev $DEV_NS up @@ -199,7 +215,7 @@ function test_erspan { DEV_NS=erspan00 DEV=erspan11 config_device - add_erspan_tunnel + add_erspan_tunnel $1 attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel ping -c 1 10.1.1.100 ip netns exec at_ns0 ping -c 1 10.1.1.200 @@ -211,7 +227,7 @@ function test_ip6erspan { DEV_NS=ip6erspan00 DEV=ip6erspan11 config_device - add_ip6erspan_tunnel + add_ip6erspan_tunnel $1 attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel ping6 -c 3 ::11 ip netns exec at_ns0 ping -c 1 10.1.1.200 @@ -288,9 +304,11 @@ test_ip6gre echo "Testing IP6GRETAP tunnel..." test_ip6gretap echo "Testing ERSPAN tunnel..." -test_erspan +test_erspan v1 +test_erspan v2 echo "Testing IP6ERSPAN tunnel..." -test_ip6erspan +test_ip6erspan v1 +test_ip6erspan v2 echo "Testing VXLAN tunnel..." test_vxlan echo "Testing GENEVE tunnel..."