Hi,
I'd like to propose the following patch to OVN.
The objective here is to copy the external_ids k,v pairs from logical
switch ports with type localnet to the patch ports created between the
br-int and the provider bridge.
This would allow me to implement a custom Openflow pipeline in the
provider bridge for a tenant assigned localnet port.
@Numan Siddique Can you review this and provide some guidance?
(cd "$(git rev-parse --show-toplevel)" && git apply --3way <<'EOF'
diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
index
5007f5f80ad1ae6ae66ddc42ffa89830487df83c..422eb2cf7b976977372e1aedbc5eaa1319ef5340
100644
--- a/controller/ovn-controller.8.xml
+++ b/controller/ovn-controller.8.xml
@@ -532,50 +532,55 @@
port or gateway router's zone key. The value for this key
identifies the zone used for this port.
</dd>
<dt>
<code>external_ids:ovn-localnet-port</code> in the <code>Port</code>
table
</dt>
<dd>
<p>
The presence of this key identifies a patch port as one created by
<code>ovn-controller</code> to connect the integration bridge and
another bridge to implement a <code>localnet</code> logical port.
Its value is the name of the logical port with <code>type</code>
set to <code>localnet</code> that the port implements. See
<code>external_ids:ovn-bridge-mappings</code>, above, for more
information.
</p>
<p>
Each <code>localnet</code> logical port is implemented as a pair of
patch ports, one in the integration bridge, one in a different
bridge, with the same <code>external_ids:ovn-localnet-port</code>
value.
</p>
+ <p>
+ When a <code>localnet</code> port has additional values in its
+ <code>external_ids</code> column, these key-value pairs are copied to
+ the corresponding patch ports.
+ </p>
</dd>
<dt>
<code>external_ids:ovn-l2gateway-port</code> in the <code>Port</code>
table
</dt>
<dd>
<p>
The presence of this key identifies a patch port as one created by
<code>ovn-controller</code> to connect the integration bridge and
another bridge to implement a <code>l2gateway</code> logical port.
Its value is the name of the logical port with <code>type</code>
set to <code>l2gateway</code> that the port implements. See
<code>external_ids:ovn-bridge-mappings</code>, above, for more
information.
</p>
<p>
Each <code>l2gateway</code> logical port is implemented as a pair
of patch ports, one in the integration bridge, one in a different
bridge, with the same <code>external_ids:ovn-l2gateway-port</code>
value.
</p>
</dd>
diff --git a/controller/patch.c b/controller/patch.c
index
4fed6e375daf5a1a989d2f9a93aab939eac3d6f4..b83c281624661279a7e2f9f1d4d6e0b9fc400950
100644
--- a/controller/patch.c
+++ b/controller/patch.c
@@ -57,68 +57,76 @@ static bool
match_patch_port(const struct ovsrec_port *port, const char *peer)
{
for (size_t i = 0; i < port->n_interfaces; i++) {
struct ovsrec_interface *iface = port->interfaces[i];
if (strcmp(iface->type, "patch")) {
continue;
}
const char *iface_peer = smap_get(&iface->options, "peer");
if (iface_peer && !strcmp(iface_peer, peer)) {
return true;
}
}
return false;
}
/* Creates a patch port in bridge 'src' named 'src_name', whose peer is
* 'dst_name' in bridge 'dst'. Initializes the patch port's external-ids:'key'
* to 'key'.
*
* If such a patch port already exists, removes it from 'existing_ports'. */
static void
create_patch_port(struct ovsdb_idl_txn *ovs_idl_txn,
const char *key, const char *value,
const struct ovsrec_bridge *src, const char *src_name,
const struct ovsrec_bridge *dst, const char *dst_name,
- struct shash *existing_ports)
+ struct shash *existing_ports,
+ const struct smap *extra_ids)
{
for (size_t i = 0; i < src->n_ports; i++) {
if (match_patch_port(src->ports[i], dst_name)) {
/* Patch port already exists on 'src'. */
shash_find_and_delete(existing_ports, src->ports[i]->name);
return;
}
}
ovsdb_idl_txn_add_comment(ovs_idl_txn,
"ovn-controller: creating patch port '%s' from '%s' to '%s'",
src_name, src->name, dst->name);
const struct smap if_options = SMAP_CONST1(&if_options, "peer", dst_name);
- const struct smap port_ids = SMAP_CONST1(&port_ids, key, value);
+
+ struct smap port_ids = SMAP_INITIALIZER(&port_ids);
+ if (extra_ids) {
+ smap_clone(&port_ids, extra_ids);
+ }
+ smap_replace(&port_ids, key, value);
+
ovsport_create(ovs_idl_txn, src, src_name, "patch", &port_ids, NULL,
&if_options, 0);
+ smap_destroy(&port_ids);
}
static void
remove_port(const struct ovsrec_bridge_table *bridge_table,
const struct ovsrec_port *port)
{
const struct ovsrec_bridge *bridge;
/* We know the port we want to delete, but we have to find the bridge its
* on to do so. Note this only runs on a config change that should be
* pretty rare. */
OVSREC_BRIDGE_TABLE_FOR_EACH (bridge, bridge_table) {
size_t i;
for (i = 0; i < bridge->n_ports; i++) {
if (bridge->ports[i] != port) {
continue;
}
ovsport_remove(bridge, port);
return;
}
}
}
void
add_ovs_bridge_mappings(const struct ovsrec_open_vswitch_table *ovs_table,
@@ -201,56 +209,61 @@ add_bridge_mappings_by_type(struct ovsdb_idl_txn
*ovs_idl_txn,
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
VLOG_ERR_RL(&rl, "%s port '%s' has no network name.",
binding->type, binding->logical_port);
continue;
}
char *msg_key = xasprintf("%s;%s", binding->logical_port, network);
struct ovsrec_bridge *br_ln =
shash_find_data(bridge_mappings, network);
if (!br_ln) {
if (log_missing_bridge) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
VLOG_ERR_RL(&rl, "bridge not found for %s port '%s' "
"with network name '%s'",
binding->type, binding->logical_port, network);
} else if (!sset_contains(&missed_bridges, msg_key)) {
VLOG_INFO("bridge not found for %s port '%s' with "
"network name '%s'; skipping",
binding->type, binding->logical_port, network);
sset_add(&missed_bridges, msg_key);
}
free(msg_key);
continue;
}
sset_find_and_delete(&missed_bridges, msg_key);
free(msg_key);
+ const struct smap *extra_ids =
+ !strcmp(pb_type, "localnet") ? &binding->external_ids : NULL;
+
char *name1 = patch_port_name(br_int->name, binding->logical_port);
char *name2 = patch_port_name(binding->logical_port, br_int->name);
create_patch_port(ovs_idl_txn, patch_port_id, binding->logical_port,
- br_int, name1, br_ln, name2, existing_ports);
+ br_int, name1, br_ln, name2, existing_ports,
+ extra_ids);
create_patch_port(ovs_idl_txn, patch_port_id, binding->logical_port,
- br_ln, name2, br_int, name1, existing_ports);
+ br_ln, name2, br_int, name1, existing_ports,
+ extra_ids);
free(name1);
free(name2);
}
sbrec_port_binding_index_destroy_row(target);
}
/* Obtains external-ids:ovn-bridge-mappings from OVSDB and adds patch ports for
* the local bridge mappings. Removes any patch ports for bridge mappings that
* already existed from 'existing_ports'. */
static void
add_bridge_mappings(struct ovsdb_idl_txn *ovs_idl_txn,
struct ovsdb_idl_index *sbrec_port_binding_by_type,
const struct ovsrec_bridge_table *bridge_table,
const struct ovsrec_open_vswitch_table *ovs_table,
const struct ovsrec_bridge *br_int,
struct shash *existing_ports,
const struct sbrec_chassis *chassis,
const struct hmap *local_datapaths)
{
/* Get ovn-bridge-mappings. */
struct shash bridge_mappings = SHASH_INITIALIZER(&bridge_mappings);
add_ovs_bridge_mappings(ovs_table, bridge_table, &bridge_mappings);
add_bridge_mappings_by_type(ovs_idl_txn, sbrec_port_binding_by_type,
EOF
)
Regards
Gav
_______________________________________________
discuss mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss