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 \