[ovs-dev] [PATCH] vxlan: Make vxlan tunnel work in IP_TUNNEL_INFO_BRIDGE mode
wenxu at ucloud.cn
wenxu at ucloud.cn
Sat Mar 30 05:28:23 UTC 2019
From: wenxu <wenxu at ucloud.cn>
There is currently no support for the multicast/broadcast aspects
of VXLAN in ovs. In the datapath flow the tun_dst must specific.
But in the IP_TUNNEL_INFO_BRIDGE mode the tun_dst can not be specific.
And the packet can forward through the fdb table of vxlan devcice. In
this mode the broadcast/multicast packet can be sent through the
following ways in ovs.
It adds an options allow_info_bridge for vxlan tunnel interface to
permit to enable this mode for this vxlan tunnel.
ovs-vsctl add-port br0 vxlan -- set in vxlan type=vxlan \
options:key=1000 options:remote_ip=flow
ovs-vsctl set in vxlan options:allow_info_bridge=true
ovs-ofctl add-flow br0 in_port=LOCAL,dl_dst=ff:ff:ff:ff:ff:ff, \
action=output:vxlan
bridge fdb append ff:ff:ff:ff:ff:ff dev vxlan_sys_4789 dst 172.168.0.1 \
src_vni 1000 vni 1000 self
bridge fdb append ff:ff:ff:ff:ff:ff dev vxlan_sys_4789 dst 172.168.0.2 \
src_vni 1000 vni 1000 self
Signed-off-by: wenxu <wenxu at ucloud.cn>
---
datapath/linux/compat/include/linux/openvswitch.h | 1 +
include/openvswitch/packets.h | 3 ++-
lib/netdev-vport.c | 20 +++++++++++++++++++-
lib/netdev.h | 2 ++
lib/odp-util.c | 19 ++++++++++++++++---
lib/packets.h | 6 ++++++
ofproto/ofproto-dpif-xlate.c | 3 ++-
ofproto/tunnel.c | 5 +++++
vswitchd/vswitch.xml | 9 +++++++++
9 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
index d5aa09d..3b23590 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -400,6 +400,7 @@ enum ovs_tunnel_key_attr {
OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */
OVS_TUNNEL_KEY_ATTR_PAD,
OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */
+ OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE, /* No argument.ipv4 info bridge mode */
__OVS_TUNNEL_KEY_ATTR_MAX
};
diff --git a/include/openvswitch/packets.h b/include/openvswitch/packets.h
index 925844e..bad5618 100644
--- a/include/openvswitch/packets.h
+++ b/include/openvswitch/packets.h
@@ -43,7 +43,8 @@ struct flow_tnl {
uint32_t erspan_idx;
uint8_t erspan_dir;
uint8_t erspan_hwid;
- uint8_t pad1[6]; /* Pad to 64 bits. */
+ uint8_t ipv4_info_bridge;
+ uint8_t pad1[5]; /* Pad to 64 bits. */
struct tun_metadata metadata;
};
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 808a43f..43ca503 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -553,6 +553,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
bool needs_dst_port, has_csum, has_seq;
uint16_t dst_proto = 0, src_proto = 0;
struct netdev_tunnel_config tnl_cfg;
+ bool allow_info_bridge = false;
struct smap_node *node;
int err;
@@ -725,12 +726,25 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
goto out;
}
}
+ } else if (!strcmp(node->key, "allow_info_bridge")) {
+ if (!strcmp(node->value, "true")) {
+ allow_info_bridge = true;
+ }
} else {
ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name,
type, node->key);
}
}
+ if (allow_info_bridge) {
+ if (!strcmp(type, "vxlan") && tnl_cfg.ip_dst_flow) {
+ tnl_cfg.allow_info_bridge = true;
+ } else {
+ ds_put_format(&errors, "%s: only work for vxlan in remote_ip=flow"
+ " mode\n", node->key);
+ }
+ }
+
enum tunnel_layers layers = tunnel_supported_layers(type, &tnl_cfg);
const char *full_type = (strcmp(type, "vxlan") ? type
: (tnl_cfg.exts & (1 << OVS_VXLAN_EXT_GPE)
@@ -962,9 +976,13 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
}
}
+ if (!strcmp("vxlan", type) && tnl_cfg.allow_info_bridge) {
+ smap_add(args, "allow_info_bridge", "true");
+ }
+
return 0;
}
-
+
/* Code specific to patch ports. */
/* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d
diff --git a/lib/netdev.h b/lib/netdev.h
index d94817f..1fcee9c 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -139,6 +139,8 @@ struct netdev_tunnel_config {
bool erspan_idx_flow;
bool erspan_dir_flow;
bool erspan_hwid_flow;
+
+ bool allow_info_bridge;
};
void netdev_run(void);
diff --git a/lib/odp-util.c b/lib/odp-util.c
index b6552c5..e3ad8ee 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2480,6 +2480,7 @@ static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_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 },
+ [OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE] = { .len = 0 },
};
const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = {
@@ -2871,6 +2872,8 @@ odp_tun_key_from_attr__(const struct nlattr *attr, bool is_mask,
}
break;
}
+ case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE:
+ tun->ipv4_info_bridge = 1;
default:
/* Allow this to show up as unexpected, if there are unknown
@@ -2918,6 +2921,11 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
if (tun_key->tun_id || tun_key->flags & FLOW_TNL_F_KEY) {
nl_msg_put_be64(a, OVS_TUNNEL_KEY_ATTR_ID, tun_key->tun_id);
}
+ if (tnl_type && !strcmp(tnl_type, "vxlan") &&
+ tun_key->ipv4_info_bridge) {
+ nl_msg_put_flag(a, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE);
+ goto out;
+ }
if (tun_key->ip_src) {
nl_msg_put_be32(a, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tun_key->ip_src);
}
@@ -2985,6 +2993,7 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
&opts, sizeof(opts));
}
+out:
nl_msg_end_nested(a, tun_key_ofs);
}
@@ -3733,6 +3742,9 @@ format_odp_tun_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
format_odp_tun_erspan_opt(a, ma, ds, verbose);
ds_put_cstr(ds, "),");
break;
+ case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE:
+ ds_put_cstr(ds, "ipv4_info_bridge,");
+ break;
case __OVS_TUNNEL_KEY_ATTR_MAX:
default:
format_unknown_key(ds, a, ma);
@@ -7351,9 +7363,10 @@ void
commit_odp_tunnel_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions, const char *tnl_type)
{
- /* A valid IPV4_TUNNEL must have non-zero ip_dst; a valid IPv6 tunnel
- * must have non-zero ipv6_dst. */
- if (flow_tnl_dst_is_set(&flow->tunnel)) {
+ /* A valid IPV4_TUNNEL must have non-zero ip_dst or ipv4 info bridge mode;
+ * a valid IPv6 tunnel must have non-zero ipv6_dst. */
+ if (flow_tnl_dst_is_set(&flow->tunnel) ||
+ flow_tnl_ipv4_info_bridge(&flow->tunnel)) {
if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
return;
}
diff --git a/lib/packets.h b/lib/packets.h
index d293b35..9b86be2 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -51,6 +51,12 @@ flow_tnl_dst_is_set(const struct flow_tnl *tnl)
return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst);
}
+static inline bool
+flow_tnl_ipv4_info_bridge(const struct flow_tnl *tnl)
+{
+ return tnl->ipv4_info_bridge;
+}
+
struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl);
struct in6_addr flow_tnl_src(const struct flow_tnl *tnl);
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index c4014d7..63eaaa1 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -4076,7 +4076,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
goto out; /* restore flow_nw_tos */
}
dst = flow_tnl_dst(&flow->tunnel);
- if (ipv6_addr_equals(&dst, &ctx->orig_tunnel_ipv6_dst)) {
+ if (!flow_tnl_ipv4_info_bridge(&flow->tunnel) &&
+ ipv6_addr_equals(&dst, &ctx->orig_tunnel_ipv6_dst)) {
xlate_report(ctx, OFT_WARN, "Not tunneling to our own address");
goto out; /* restore flow_nw_tos */
}
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index 03f0ab7..86204d3 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -490,6 +490,11 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
flow->tunnel.erspan_hwid = cfg->erspan_hwid;
}
+ if (cfg->allow_info_bridge && !flow_tnl_dst_is_set(&flow->tunnel) &&
+ !flow->tunnel.gbp_flags && !flow->tunnel.gbp_id) {
+ flow->tunnel.ipv4_info_bridge = 1;
+ }
+
if (pre_flow_str) {
char *post_flow_str = flow_to_string(flow, NULL);
char *tnl_str = tnl_port_to_string(tnl_port);
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 08001db..5c5728c 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2848,6 +2848,15 @@
</li>
</ul>
</column>
+
+ <column name="options" key="allow_info_bridge"
+ type='{"type": "boolean"}'>
+ Optional. Only in reomte_ip=flow mode can be enabled. If enabled,
+ the tunnel dst is not set in flow. It will ignore all other
+ parameters except VNI. It makes the packet forward through the fdb
+ of vxlan_sys_x device. Default is disable; set to <code>true</code>
+ to enable.
+ </column>
</group>
<group title="Tunnel Options: gre only">
--
1.8.3.1
More information about the dev
mailing list