mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 22:35:15 +00:00
erspan: add kernel datapath support
pass check, check-kernel (4.16-rc4), check-system-userspace Signed-off-by: William Tu <u9012063@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -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:
|
||||
|
@@ -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 "";
|
||||
|
||||
|
152
lib/odp-util.c
152
lib/odp-util.c
@@ -2451,6 +2451,7 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX +
|
||||
.next_max = OVS_VXLAN_EXT_MAX},
|
||||
[OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = 16 },
|
||||
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = 16 },
|
||||
[OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = ATTR_LEN_VARIABLE },
|
||||
};
|
||||
|
||||
const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = {
|
||||
@@ -2774,6 +2775,23 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask,
|
||||
case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
|
||||
tun_metadata_from_geneve_nlattr(a, is_mask, tun);
|
||||
break;
|
||||
case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: {
|
||||
int attr_len = nl_attr_get_size(a);
|
||||
struct erspan_metadata opts;
|
||||
|
||||
memcpy(&opts, nl_attr_get(a), attr_len);
|
||||
|
||||
tun->erspan_ver = opts.version;
|
||||
if (tun->erspan_ver == 1) {
|
||||
tun->erspan_idx = ntohl(opts.u.index);
|
||||
} else if (tun->erspan_ver == 2) {
|
||||
tun->erspan_dir = opts.u.md2.dir;
|
||||
tun->erspan_hwid = get_hwid(&opts.u.md2);
|
||||
} else {
|
||||
VLOG_WARN("%s invalid erspan version\n", __func__);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Allow this to show up as unexpected, if there are unknown
|
||||
@@ -2863,6 +2881,22 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
|
||||
tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a);
|
||||
}
|
||||
|
||||
if ((!tnl_type || !strcmp(tnl_type, "erspan") ||
|
||||
!strcmp(tnl_type, "ip6erspan")) &&
|
||||
(tun_key->erspan_ver == 1 || tun_key->erspan_ver == 2)) {
|
||||
struct erspan_metadata opts;
|
||||
|
||||
opts.version = tun_key->erspan_ver;
|
||||
if (opts.version == 1) {
|
||||
opts.u.index = htonl(tun_key->erspan_idx);
|
||||
} else {
|
||||
opts.u.md2.dir = tun_key->erspan_dir;
|
||||
set_hwid(&opts.u.md2, tun_key->erspan_hwid);
|
||||
}
|
||||
nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
|
||||
&opts, sizeof(opts));
|
||||
}
|
||||
|
||||
nl_msg_end_nested(a, tun_key_ofs);
|
||||
}
|
||||
|
||||
@@ -3318,6 +3352,46 @@ format_odp_tun_vxlan_opt(const struct nlattr *attr,
|
||||
ofpbuf_uninit(&ofp);
|
||||
}
|
||||
|
||||
static void
|
||||
format_odp_tun_erspan_opt(const struct nlattr *attr,
|
||||
const struct nlattr *mask_attr, struct ds *ds,
|
||||
bool verbose)
|
||||
{
|
||||
const struct erspan_metadata *opts, *mask;
|
||||
uint8_t ver, ver_ma, dir, dir_ma, hwid, hwid_ma;
|
||||
|
||||
opts = nl_attr_get(attr);
|
||||
mask = mask_attr ? nl_attr_get(mask_attr) : NULL;
|
||||
|
||||
ver = (uint8_t)opts->version;
|
||||
if (mask) {
|
||||
ver_ma = (uint8_t)mask->version;
|
||||
}
|
||||
|
||||
format_u8u(ds, "ver", ver, mask ? &ver_ma : NULL, verbose);
|
||||
|
||||
if (opts->version == 1) {
|
||||
if (mask) {
|
||||
ds_put_format(ds, "idx=%#"PRIx32"/%#"PRIx32",",
|
||||
ntohl(opts->u.index),
|
||||
ntohl(mask->u.index));
|
||||
} else {
|
||||
ds_put_format(ds, "idx=%#"PRIx32",", ntohl(opts->u.index));
|
||||
}
|
||||
} else if (opts->version == 2) {
|
||||
dir = opts->u.md2.dir;
|
||||
hwid = opts->u.md2.hwid;
|
||||
if (mask) {
|
||||
dir_ma = mask->u.md2.dir;
|
||||
hwid_ma = mask->u.md2.hwid;
|
||||
}
|
||||
|
||||
format_u8u(ds, "dir", dir, mask ? &dir_ma : NULL, verbose);
|
||||
format_u8x(ds, "hwid", hwid, mask ? &hwid_ma : NULL, verbose);
|
||||
}
|
||||
ds_chomp(ds, ',');
|
||||
}
|
||||
|
||||
#define MASK(PTR, FIELD) PTR ? &PTR->FIELD : NULL
|
||||
|
||||
static void
|
||||
@@ -3566,6 +3640,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:
|
||||
@@ -4750,6 +4827,70 @@ scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -4885,6 +5026,15 @@ geneve_to_attr(struct ofpbuf *a, const void *data_)
|
||||
geneve->len);
|
||||
}
|
||||
|
||||
static void
|
||||
erspan_to_attr(struct ofpbuf *a, const void *data_)
|
||||
{
|
||||
const struct erspan_metadata *md = data_;
|
||||
|
||||
nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, md,
|
||||
sizeof *md);
|
||||
}
|
||||
|
||||
#define SCAN_PUT_ATTR(BUF, ATTR, DATA, FUNC) \
|
||||
{ \
|
||||
unsigned long call_fn = (unsigned long)FUNC; \
|
||||
@@ -5253,6 +5403,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);
|
||||
|
25
tests/odp.at
25
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`
|
||||
|
@@ -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])
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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 \
|
||||
|
Reference in New Issue
Block a user