+
static const struct nl_policy rtlink_policy[] = {
[IFLA_LINKINFO] = { .type = NL_A_NESTED },
};
@@ -81,6 +93,10 @@ static const struct nl_policy geneve_policy[] = {
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NL_A_U8 },
[IFLA_GENEVE_PORT] = { .type = NL_A_U16 },
};
+static const struct nl_policy bareudp_policy[] = {
+ [IFLA_BAREUDP_PORT] = { .type = NL_A_U16 },
+ [IFLA_BAREUDP_ETHERTYPE] = { .type = NL_A_U16 },
+};
static const char *
vport_type_to_kind(enum ovs_vport_type type,
@@ -113,6 +129,8 @@ vport_type_to_kind(enum ovs_vport_type type,
}
case OVS_VPORT_TYPE_GTPU:
return NULL;
+ case OVS_VPORT_TYPE_BAREUDP:
+ return "bareudp";
case OVS_VPORT_TYPE_NETDEV:
case OVS_VPORT_TYPE_INTERNAL:
case OVS_VPORT_TYPE_LISP:
@@ -243,6 +261,24 @@ dpif_netlink_rtnl_geneve_verify(const struct
netdev_tunnel_config *tnl_cfg,
return err;
}
+static int
+dpif_netlink_rtnl_bareudp_verify(const struct netdev_tunnel_config
*tnl_cfg,
+ const char *kind, struct ofpbuf
*reply)
+{
+ struct nlattr *bareudp[ARRAY_SIZE(bareudp_policy)];
+ int err;
+
+ err = rtnl_policy_parse(kind, reply, bareudp_policy, bareudp,
+ ARRAY_SIZE(bareudp_policy));
+ if (!err) {
+ if ((tnl_cfg->dst_port !=
nl_attr_get_be16(bareudp[IFLA_BAREUDP_PORT]))
+ || (tnl_cfg->payload_ethertype
+ !=
nl_attr_get_be16(bareudp[IFLA_BAREUDP_ETHERTYPE])))
{
+ err = EINVAL;
+ }
+ }
+ return err;
+}
static int
dpif_netlink_rtnl_verify(const struct netdev_tunnel_config
*tnl_cfg,
@@ -275,6 +311,9 @@ dpif_netlink_rtnl_verify(const struct
netdev_tunnel_config *tnl_cfg,
case OVS_VPORT_TYPE_GENEVE:
err = dpif_netlink_rtnl_geneve_verify(tnl_cfg, kind,
reply);
break;
+ case OVS_VPORT_TYPE_BAREUDP:
+ err = dpif_netlink_rtnl_bareudp_verify(tnl_cfg, kind,
reply);
+ break;
case OVS_VPORT_TYPE_NETDEV:
case OVS_VPORT_TYPE_INTERNAL:
case OVS_VPORT_TYPE_LISP:
@@ -357,6 +396,16 @@ dpif_netlink_rtnl_create(const struct
netdev_tunnel_config *tnl_cfg,
nl_msg_put_u8(&request, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, 1);
nl_msg_put_be16(&request, IFLA_GENEVE_PORT,
tnl_cfg->dst_port);
break;
+ case OVS_VPORT_TYPE_BAREUDP:
+ nl_msg_put_be16(&request, IFLA_BAREUDP_ETHERTYPE,
+ tnl_cfg->payload_ethertype);
+ nl_msg_put_u16(&request, IFLA_BAREUDP_SRCPORT_MIN,
+ BAREUDP_EPHEMERAL_SRCPORT_MIN);
+ nl_msg_put_be16(&request, IFLA_BAREUDP_PORT,
tnl_cfg->dst_port);
+ if (tnl_cfg->exts & (1 << OVS_BAREUDP_EXT_MULTIPROTO_MODE))
{
+ nl_msg_put_flag(&request,
IFLA_BAREUDP_MULTIPROTO_MODE);
+ }
+ break;
case OVS_VPORT_TYPE_NETDEV:
case OVS_VPORT_TYPE_INTERNAL:
case OVS_VPORT_TYPE_LISP:
@@ -470,6 +519,7 @@ dpif_netlink_rtnl_port_destroy(const char *name,
const char *type)
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
+ case OVS_VPORT_TYPE_BAREUDP:
return dpif_netlink_rtnl_destroy(name);
case OVS_VPORT_TYPE_NETDEV:
case OVS_VPORT_TYPE_INTERNAL:
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 6858ba612..d1a1cc723 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -752,6 +752,9 @@ get_vport_type(const struct dpif_netlink_vport
*vport)
case OVS_VPORT_TYPE_GTPU:
return "gtpu";
+ case OVS_VPORT_TYPE_BAREUDP:
+ return "bareudp";
+
case OVS_VPORT_TYPE_UNSPEC:
case __OVS_VPORT_TYPE_MAX:
break;
@@ -787,6 +790,8 @@ netdev_to_ovs_vport_type(const char *type)
return OVS_VPORT_TYPE_GRE;
} else if (!strcmp(type, "gtpu")) {
return OVS_VPORT_TYPE_GTPU;
+ } else if (!strcmp(type, "bareudp")) {
+ return OVS_VPORT_TYPE_BAREUDP;
} else {
return OVS_VPORT_TYPE_UNSPEC;
}
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 0252b61de..15567e524 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -47,6 +47,7 @@
#include "unaligned.h"
#include "unixctl.h"
#include "openvswitch/vlog.h"
+#include "openvswitch/ofp-parse.h"
#ifdef __linux__
#include "netdev-linux.h"
#endif
@@ -112,7 +113,7 @@ netdev_vport_needs_dst_port(const struct netdev
*dev)
return (class->get_config == get_tunnel_config &&
(!strcmp("geneve", type) || !strcmp("vxlan", type) ||
!strcmp("lisp", type) || !strcmp("stt", type) ||
- !strcmp("gtpu", type)));
+ !strcmp("gtpu", type) || !strcmp("bareudp",type)));
}
const char *
@@ -219,6 +220,8 @@ netdev_vport_construct(struct netdev *netdev_)
dev->tnl_cfg.dst_port = port ? htons(port) :
htons(STT_DST_PORT);
} else if (!strcmp(type, "gtpu")) {
dev->tnl_cfg.dst_port = port ? htons(port) :
htons(GTPU_DST_PORT);
+ } else if (!strcmp(type, "bareudp")) {
+ dev->tnl_cfg.dst_port = htons(port);
}
dev->tnl_cfg.dont_fragment = true;
@@ -438,6 +441,8 @@ tunnel_supported_layers(const char *type,
return TNL_L2 | TNL_L3;
} else if (!strcmp(type, "gtpu")) {
return TNL_L3;
+ } else if (!strcmp(type, "bareudp")) {
+ return TNL_L3;
} else {
return TNL_L2;
}
@@ -745,6 +750,23 @@ set_tunnel_config(struct netdev *dev_, const
struct
smap *args, char **errp)
goto out;
}
}
+ } else if (!strcmp(node->key, "payload_type")) {
+ if (!strcmp(node->value, "mpls")) {
+ tnl_cfg.payload_ethertype = htons(ETH_TYPE_MPLS);
+ tnl_cfg.exts |= (1 <<
OVS_BAREUDP_EXT_MULTIPROTO_MODE);
+ } else if (!strcmp(node->value, "ip")) {
+ tnl_cfg.payload_ethertype = htons(ETH_TYPE_IP);
+ tnl_cfg.exts |= (1 <<
OVS_BAREUDP_EXT_MULTIPROTO_MODE);
+ } else {
+ uint16_t payload_ethertype;
+
+ if (str_to_u16(node->value, "payload_type",
+ &payload_ethertype)) {
+ err = EINVAL;
+ goto out;
+ }
+ tnl_cfg.payload_ethertype =
htons(payload_ethertype);
+ }
} else {
ds_put_format(&errors, "%s: unknown %s argument
'%s'\n",
name,
type, node->key);
@@ -917,7 +939,8 @@ get_tunnel_config(const struct netdev *dev,
struct
smap *args)
(!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT)
||
(!strcmp("lisp", type) && dst_port != LISP_DST_PORT) ||
(!strcmp("stt", type) && dst_port != STT_DST_PORT) ||
- (!strcmp("gtpu", type) && dst_port != GTPU_DST_PORT)) {
+ (!strcmp("gtpu", type) && dst_port != GTPU_DST_PORT) ||
+ !strcmp("bareudp", type)) {
smap_add_format(args, "dst_port", "%d", dst_port);
}
}
@@ -1243,6 +1266,14 @@ netdev_vport_tunnel_register(void)
},
{{NULL, NULL, 0, 0}}
},
+ { "udp_sys",
+ {
+ TUNNEL_FUNCTIONS_COMMON,
+ .type = "bareudp",
+ .get_ifindex = NETDEV_VPORT_GET_IFINDEX,
+ },
+ {{NULL, NULL, 0, 0}}
+ },
};
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
diff --git a/lib/netdev.h b/lib/netdev.h
index fb5073056..b705a9e56 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -107,6 +107,7 @@ struct netdev_tunnel_config {
bool out_key_flow;
ovs_be64 out_key;
+ ovs_be16 payload_ethertype;
ovs_be16 dst_port;
bool ip_src_flow;
diff --git a/ofproto/ofproto-dpif-xlate.c
b/ofproto/ofproto-dpif-xlate.c
index 11aa20754..7eeff14f6 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3573,6 +3573,7 @@ propagate_tunnel_data_to_flow(struct xlate_ctx
*ctx, struct eth_addr dmac,
case OVS_VPORT_TYPE_VXLAN:
case OVS_VPORT_TYPE_GENEVE:
case OVS_VPORT_TYPE_GTPU:
+ case OVS_VPORT_TYPE_BAREUDP:
nw_proto = IPPROTO_UDP;
break;
case OVS_VPORT_TYPE_LISP:
diff --git a/tests/system-layer3-tunnels.at
b/tests/system-layer3-tunnels.at
index 1232964bb..d21fd777d 100644
--- a/tests/system-layer3-tunnels.at
+++ b/tests/system-layer3-tunnels.at
@@ -152,3 +152,99 @@ AT_CHECK([tail -1 stdout], [0],
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([layer3 - ping over MPLS Bareudp])
+OVS_CHECK_MIN_KERNEL(5, 7)
+OVS_TRAFFIC_VSWITCHD_START([_ADD_BR([br1])])
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "36:b1:ee:7c:01:01")
+ADD_VETH(p1, at_ns1, br1, "10.1.1.2/24", "36:b1:ee:7c:01:02")
+
+ADD_OVS_TUNNEL([bareudp], [br0], [at_bareudp0], [8.1.1.3],
[8.1.1.2/24],
+ [ options:local_ip=8.1.1.2
options:packet_type="legacy_l3" options:payload_type=mpls
options:dst_port=6635])
+
+ADD_OVS_TUNNEL([bareudp], [br1], [at_bareudp1], [8.1.1.2],
[8.1.1.3/24],
+ [options:local_ip=8.1.1.3
options:packet_type="legacy_l3" options:payload_type=mpls
options:dst_port=6635])
+
+AT_DATA([flows0.txt], [dnl
+table=0,priority=100,dl_type=0x0800
actions=push_mpls:0x8847,set_mpls_label:3,output:at_bareudp0
+table=0,priority=100,dl_type=0x8847 in_port=at_bareudp0
actions=pop_mpls:0x0800,set_field:36:b1:ee:7c:01:01->dl_dst,set_field:36:b1:ee:7c:01:02->dl_src,output:ovs-p0
+table=0,priority=10 actions=normal
+])
+
+AT_DATA([flows1.txt], [dnl
+table=0,priority=100,dl_type=0x0800
actions=push_mpls:0x8847,set_mpls_label:3,output:at_bareudp1
+table=0,priority=100,dl_type=0x8847 in_port=at_bareudp1
actions=pop_mpls:0x0800,set_field:36:b1:ee:7c:01:02->dl_dst,set_field:36:b1:ee:7c:01:01->dl_src,output:ovs-p1
+table=0,priority=10 actions=normal
+])
+
+AT_CHECK([ip link add patch0 type veth peer name patch1])
+on_exit 'ip link del patch0'
+
+AT_CHECK([ip link set dev patch0 up])
+AT_CHECK([ip link set dev patch1 up])
+AT_CHECK([ovs-vsctl add-port br0 patch0])
+AT_CHECK([ovs-vsctl add-port br1 patch1])
+
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows0.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br1 flows1.txt])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 |
FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 10.1.1.1 |
FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([layer3 - ping over Bareudp])
+OVS_CHECK_MIN_KERNEL(5, 7)
+OVS_TRAFFIC_VSWITCHD_START([_ADD_BR([br1])])
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "36:b1:ee:7c:01:01")
+ADD_VETH(p1, at_ns1, br1, "10.1.1.2/24", "36:b1:ee:7c:01:02")
+
+ADD_OVS_TUNNEL([bareudp], [br0], [at_bareudp0], [8.1.1.3],
[8.1.1.2/24],
+ [ options:local_ip=8.1.1.2
options:packet_type="legacy_l3" options:payload_type=ip
options:dst_port=6636])
+
+ADD_OVS_TUNNEL([bareudp], [br1], [at_bareudp1], [8.1.1.2],
[8.1.1.3/24],
+ [options:local_ip=8.1.1.3
options:packet_type="legacy_l3" options:payload_type=ip
options:dst_port=6636])
+
+AT_DATA([flows0.txt], [dnl
+table=0,priority=100,dl_type=0x0800 in_port=ovs-p0,
actions=output:at_bareudp0
+table=0,priority=100,dl_type=0x0800 in_port=at_bareudp0
actions=set_field:36:b1:ee:7c:01:01->dl_dst,set_field:36:b1:ee:7c:01:02->dl_src,output:ovs-p0
+table=0,priority=10 actions=normal
+])
+
+AT_DATA([flows1.txt], [dnl
+table=0,priority=100,dl_type=0x0800 in_port=ovs-p1
actions=output:at_bareudp1
+table=0,priority=100,dl_type=0x0800 in_port=at_bareudp1
actions=set_field:36:b1:ee:7c:01:02->dl_dst,set_field:36:b1:ee:7c:01:01->dl_src,output:ovs-p1
+table=0,priority=10 actions=normal
+])
+
+AT_CHECK([ip link add patch0 type veth peer name patch1])
+on_exit 'ip link del patch0'
+
+AT_CHECK([ip link set dev patch0 up])
+AT_CHECK([ip link set dev patch1 up])
+AT_CHECK([ovs-vsctl add-port br0 patch0])
+AT_CHECK([ovs-vsctl add-port br1 patch1])
+
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br0 flows0.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flows br1 flows1.txt])
+
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.2 |
FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+NS_CHECK_EXEC([at_ns1], [ping -q -c 3 -i 0.3 -w 2 10.1.1.1 |
FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 89a876796..75cc4263a 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2694,6 +2694,15 @@
</p>
</dd>
+ <dt><code>Bareudp</code></dt>
+ <dd>
+ <p>
+ The Bareudp tunnel provides a generic L3 encapsulation
support for
+ tunnelling different L3 protocols like MPLS, IP, NSH
etc.
inside a
+ UDP tunnel.
+ </p>
+ </dd>
+
</dl>
</column>
</group>
@@ -3092,6 +3101,17 @@
</column>
</group>
+ <group title="Tunnel Options: Bareudp only">
+ <column name="options" key="payload_type">
+ <p>
+ Specifies the ethertype of the l3 protocol the bareudp
+ device is tunnelling. For the tunnels which supports
multiple
+ ethertypes of a l3 protocol (IP, MPLS) this field
specifies
the
+ protocol name as a string.
+ </p>
+ </column>
+ </group>
+
<group title="Patch Options">
<p>
These options apply only to <dfn>patch ports</dfn>, that
is,
interfaces