Message ID | 20190417145038.10224-1-lmartins@redhat.com |
---|---|
State | Superseded |
Headers | show |
Series | [ovs-dev,v4] OVN: Add support for Transport Zones | expand |
On Wed, Apr 17, 2019 at 8:21 PM <lmartins@redhat.com> wrote: > From: Lucas Alvares Gomes <lucasagomes@gmail.com> > > This patch is adding support for Transport Zones. Transport zones (a.k.a > TZs) is way to enable users of OVN to separate Chassis into different > logical groups that will only form tunnels between members of the same > groups. Each Chassis can belong to one or more Transport Zones. If > not set, the Chassis will be considered part of a default group. > > Configuring Transport Zones is done by creating a key called > "ovn-transport-zones" in the external_ids column of the Open_vSwitch > table from the local OVS instance. The value is a string with the name > of the Transport Zone that this instance is part of. Multiple TZs can > be specified with a comma-separated list. For example: > > $ sudo ovs-vsctl set open . external-ids:ovn-transport-zones=tz1 > > or > > $ sudo ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2,tz3 > > This configuration is also exposed in the Chassis table of the OVN > Southbound Database in a new column called "transport_zones". > > The use for Transport Zones includes but are not limited to: > > * Edge computing: As a way to preventing edge sites from trying to create > tunnels with every node on every other edge site while still allowing > these sites to create tunnels with the central node. > > * Extra security layer: Where users wants to create "trust zones" > and prevent computes in a more secure zone to communicate with a less > secure zone. > > This patch is also backward compatible so the upgrade guide for OVN [0] > is still valid and the ovn-controller service can be upgraded before the > OVSDBs. > > [0] http://docs.openvswitch.org/en/latest/intro/install/ovn-upgrades/ > > Reported-by: Daniel Alvarez Sanchez <dalvarez@redhat.com> > Reported-at: > https://mail.openvswitch.org/pipermail/ovs-discuss/2019-February/048255.html > Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com> > --- > v3 -> v4 > * Stopped using the "external_ids" column of the Chassis table and > instead added a new column called "transport_zones" to hold the set of > transport zones that the Chassis is part of. > > v2 -> v3 > * Enhanced the test to include two more Chassis and assert the case > where Chassis with no TZs set will have tunnels formed between them. > * Rebased the patch on top of the latest master branch. > > v1 -> v2 > > * Rename the function check_chassis_tzones to chassis_tzones_overlap. > * Fix a memory leak in chassis_tzones_overlap. > * Pass the transport_zones to encaps_run() as a "const char *" > instead of "struct sbrec_chassis". With this we can also avoid not > running the function in case the Chassis entry is not yet created. > > NEWS | 3 + > ovn/controller/chassis.c | 26 ++++- > ovn/controller/chassis.h | 4 +- > ovn/controller/encaps.c | 35 ++++++- > ovn/controller/encaps.h | 4 +- > ovn/controller/ovn-controller.8.xml | 9 ++ > ovn/controller/ovn-controller.c | 19 +++- > ovn/ovn-sb.ovsschema | 7 +- > ovn/ovn-sb.xml | 8 ++ > tests/ovn.at | 151 ++++++++++++++++++++++++++++ > 10 files changed, 257 insertions(+), 9 deletions(-) > > diff --git a/NEWS b/NEWS > index c7440b476..e09f59d64 100644 > --- a/NEWS > +++ b/NEWS > @@ -33,6 +33,9 @@ Post-v2.11.0 > * Added Policy-based routing(PBR) support to create > permit/deny/reroute > policies on the logical router. New table(Logical_Router_Policy) > added in > OVN-NB schema. New "ovn-nbctl" commands to add/delete/list PBR > policies. > + * Support for Transport Zones, a way to separate chassis into > + logical groups which results in tunnels only been formed between > + members of the same transport zone(s). > - New QoS type "linux-netem" on Linux. > - Added support for TLS Server Name Indication (SNI). > > diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c > index 58d5d49d5..0f537f1f7 100644 > --- a/ovn/controller/chassis.c > +++ b/ovn/controller/chassis.c > @@ -19,6 +19,7 @@ > #include "chassis.h" > > #include "lib/smap.h" > +#include "lib/sset.h" > #include "lib/vswitch-idl.h" > #include "openvswitch/dynamic-string.h" > #include "openvswitch/vlog.h" > @@ -73,13 +74,34 @@ get_cms_options(const struct smap *ext_ids) > return smap_get_def(ext_ids, "ovn-cms-options", ""); > } > > +static void > +update_chassis_transport_zones(const struct sset *transport_zones, > + const struct sbrec_chassis *chassis_rec) > +{ > + struct sset chassis_tzones_set = > SSET_INITIALIZER(&chassis_tzones_set); > + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { > + sset_add(&chassis_tzones_set, chassis_rec->transport_zones[i]); > + } > + > + /* Only update the transport zones if something changed */ > + if (!sset_equals(transport_zones, &chassis_tzones_set)) { > + const char **ls_arr = sset_array(transport_zones); > + sbrec_chassis_set_transport_zones(chassis_rec, ls_arr, > + sset_count(transport_zones)); > + free(ls_arr); > + } > + > + sset_destroy(&chassis_tzones_set); > +} > + > /* Returns this chassis's Chassis record, if it is available. */ > const struct sbrec_chassis * > chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > struct ovsdb_idl_index *sbrec_chassis_by_name, > const struct ovsrec_open_vswitch_table *ovs_table, > const char *chassis_id, > - const struct ovsrec_bridge *br_int) > + const struct ovsrec_bridge *br_int, > + const struct sset *transport_zones) > { > const struct sbrec_chassis *chassis_rec > = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); > @@ -157,6 +179,8 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > sbrec_chassis_set_hostname(chassis_rec, hostname); > } > > + update_chassis_transport_zones(transport_zones, chassis_rec); > + > /* Determine new values for Chassis external-ids. */ > const char *chassis_bridge_mappings > = get_bridge_mappings(&chassis_rec->external_ids); > diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h > index 6b1c357d2..9847e19f6 100644 > --- a/ovn/controller/chassis.h > +++ b/ovn/controller/chassis.h > @@ -25,13 +25,15 @@ struct ovsrec_bridge; > struct ovsrec_open_vswitch_table; > struct sbrec_chassis; > struct sbrec_chassis_table; > +struct sset; > > void chassis_register_ovs_idl(struct ovsdb_idl *); > const struct sbrec_chassis *chassis_run( > struct ovsdb_idl_txn *ovnsb_idl_txn, > struct ovsdb_idl_index *sbrec_chassis_by_name, > const struct ovsrec_open_vswitch_table *, > - const char *chassis_id, const struct ovsrec_bridge *br_int); > + const char *chassis_id, const struct ovsrec_bridge *br_int, > + const struct sset *transport_zones); > bool chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, > const struct sbrec_chassis *); > > diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c > index 610b833de..dcf78108d 100644 > --- a/ovn/controller/encaps.c > +++ b/ovn/controller/encaps.c > @@ -195,13 +195,36 @@ chassis_tunnel_add(const struct sbrec_chassis > *chassis_rec, const struct sbrec_s > return tuncnt; > } > > +/* > +* Returns true if transport_zones and chassis_rec->transport_zones > +* have at least one common transport zone. > +*/ > +static bool > +chassis_tzones_overlap(const struct sset *transport_zones, > + const struct sbrec_chassis *chassis_rec) > +{ > + /* If neither Chassis belongs to any transport zones, return true to > + * form a tunnel between them */ > + if (!chassis_rec->n_transport_zones && > sset_is_empty(transport_zones)) { > + return true; > + } > + > + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { > + if (sset_contains(transport_zones, > chassis_rec->transport_zones[i])) { > + return true; > + } > + } > + return false; > +} > + > void > encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > const struct ovsrec_bridge_table *bridge_table, > const struct ovsrec_bridge *br_int, > const struct sbrec_chassis_table *chassis_table, > const char *chassis_id, > - const struct sbrec_sb_global *sbg) > + const struct sbrec_sb_global *sbg, > + const struct sset *transport_zones) > { > if (!ovs_idl_txn || !br_int) { > return; > @@ -251,7 +274,15 @@ encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > > SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) { > if (strcmp(chassis_rec->name, chassis_id)) { > - /* Create tunnels to the other chassis. */ > + /* Create tunnels to the other Chassis belonging to the > + * same transport zone */ > + if (!chassis_tzones_overlap(transport_zones, chassis_rec)) { > + VLOG_DBG("Skipping encap creation for Chassis '%s' > because " > + "it belongs to different transport zones", > + chassis_rec->name); > + continue; > + } > + > if (chassis_tunnel_add(chassis_rec, sbg, &tc) == 0) { > VLOG_INFO("Creating encap for '%s' failed", > chassis_rec->name); > continue; > diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h > index 3e0e110ef..7ed3e0939 100644 > --- a/ovn/controller/encaps.h > +++ b/ovn/controller/encaps.h > @@ -25,6 +25,7 @@ struct ovsrec_bridge_table; > struct sbrec_chassis_table; > struct sbrec_sb_global; > struct ovsrec_open_vswitch_table; > +struct sset; > > void encaps_register_ovs_idl(struct ovsdb_idl *); > void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > @@ -32,7 +33,8 @@ void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > const struct ovsrec_bridge *br_int, > const struct sbrec_chassis_table *, > const char *chassis_id, > - const struct sbrec_sb_global *); > + const struct sbrec_sb_global *, > + const struct sset *transport_zones); > > bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn, > const struct ovsrec_bridge *br_int); > diff --git a/ovn/controller/ovn-controller.8.xml > b/ovn/controller/ovn-controller.8.xml > index fd2e10a7a..072ec5820 100644 > --- a/ovn/controller/ovn-controller.8.xml > +++ b/ovn/controller/ovn-controller.8.xml > @@ -167,6 +167,15 @@ > specific to this particular chassis. An example would be: > <code>cms_option1,cms_option2:foo</code>. > </dd> > + > + <dt><code>external_ids:ovn-transport-zones</code></dt> > + <dd> > + The transport zone(s) that this chassis belongs to. Transport > + zones is a way to group different chassis so that tunnels are only > + formed between members of the same group(s). Multiple transport > + zones may be specified with a comma-separated list. For example: > + tz1,tz2,tz3. > + </dd> > </dl> > > <p> > diff --git a/ovn/controller/ovn-controller.c > b/ovn/controller/ovn-controller.c > index cf4907db3..69eeee5dc 100644 > --- a/ovn/controller/ovn-controller.c > +++ b/ovn/controller/ovn-controller.c > @@ -512,6 +512,14 @@ get_nb_cfg(const struct sbrec_sb_global_table > *sb_global_table) > return sb ? sb->nb_cfg : 0; > } > > +static const char * > +get_transport_zones(const struct ovsrec_open_vswitch_table *ovs_table) > +{ > + const struct ovsrec_open_vswitch *cfg > + = ovsrec_open_vswitch_table_first(ovs_table); > + return smap_get_def(&cfg->external_ids, "ovn-transport-zones", ""); > +} > + > static void > ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > { > @@ -679,6 +687,11 @@ main(int argc, char *argv[]) > * <datapath-tunnel-key>_<port-tunnel-key> */ > struct sset local_lport_ids = > SSET_INITIALIZER(&local_lport_ids); > struct sset active_tunnels = > SSET_INITIALIZER(&active_tunnels); > + /* Contains the transport zones that this Chassis belongs to > */ > + struct sset transport_zones = > SSET_INITIALIZER(&transport_zones); > + sset_from_delimited_string(&transport_zones, > + get_transport_zones(ovsrec_open_vswitch_table_get( > + ovs_idl_loop.idl)), ","); > > const struct ovsrec_bridge *br_int > = get_br_int(ovs_idl_txn, > @@ -693,12 +706,13 @@ main(int argc, char *argv[]) > chassis = chassis_run( > ovnsb_idl_txn, sbrec_chassis_by_name, > ovsrec_open_vswitch_table_get(ovs_idl_loop.idl), > - chassis_id, br_int); > + chassis_id, br_int, &transport_zones); > encaps_run( > ovs_idl_txn, > ovsrec_bridge_table_get(ovs_idl_loop.idl), br_int, > sbrec_chassis_table_get(ovnsb_idl_loop.idl), > chassis_id, > - sbrec_sb_global_first(ovnsb_idl_loop.idl)); > + sbrec_sb_global_first(ovnsb_idl_loop.idl), > + &transport_zones); > > if (ofctrl_is_connected()) { > /* Calculate the active tunnels only if have an an > active > @@ -848,6 +862,7 @@ main(int argc, char *argv[]) > sset_destroy(&local_lports); > sset_destroy(&local_lport_ids); > sset_destroy(&active_tunnels); > + sset_destroy(&transport_zones); > > struct local_datapath *cur_node, *next_node; > HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, > diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema > index d87a02e7b..98007cb6e 100644 > --- a/ovn/ovn-sb.ovsschema > +++ b/ovn/ovn-sb.ovsschema > @@ -1,7 +1,7 @@ > { > "name": "OVN_Southbound", > "version": "2.2.0", > Since you are adding a new column, can you please bump the version to "2.2.1" ? With this change Acked-by: Numan Siddique <nusiddiq@redhat.com> Thanks Numan - "cksum": "2100715070 17222", > + "cksum": "4060521526 17409", > "tables": { > "SB_Global": { > "columns": { > @@ -37,7 +37,10 @@ > "nb_cfg": {"type": {"key": "integer"}}, > "external_ids": { > "type": {"key": "string", "value": "string", > - "min": 0, "max": "unlimited"}}}, > + "min": 0, "max": "unlimited"}}, > + "transport_zones" : {"type": {"key": "string", > + "min": 0, > + "max": "unlimited"}}}, > "isRoot": true, > "indexes": [["name"]]}, > "Encap": { > diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml > index 5c4a852a5..e4ac59f1c 100644 > --- a/ovn/ovn-sb.xml > +++ b/ovn/ovn-sb.xml > @@ -293,6 +293,14 @@ > See <code>ovn-controller</code>(8) for more information. > </column> > > + <column name="transport_zones"> > + <code>ovn-controller</code> populates this key with the transport > + zones configured in the <ref table="Open_vSwitch" > + column="external_ids:ovn-transport-zones"/> column of the > Open_vSwitch > + database's <ref table="Open_vSwitch" db="Open_vSwitch"/> table. > + See <code>ovn-controller</code>(8) for more information. > + </column> > + > <group title="Common Columns"> > The overall purpose of these columns is described under <code>Common > Columns</code> at the beginning of this document. > diff --git a/tests/ovn.at b/tests/ovn.at > index b3500e8c9..ad4d23caa 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -13652,3 +13652,154 @@ ovn-nbctl list logical_switch_port > ovn-nbctl list logical_router_port > > AT_CLEANUP > + > +AT_SETUP([ovn -- test transport zones]) > +ovn_start > + > +net_add n1 > +for i in 1 2 3 4 5; do > + sim_add hv$i > + as hv$i > + ovs-vsctl add-br br-phys > + ovn_attach n1 br-phys 192.168.$i.1 > +done > + > +dnl Assert that each Chassis has a tunnel formed to every other Chassis > +as hv1 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv2 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv3-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv3 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv4 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv5-0 > +]]) > + > +as hv5 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv4-0 > +]]) > + > +dnl Let's now add some Chassis to different transport zones > +dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it > +dnl should have tunnels formed between the other two Chassis (hv2 and > hv3) > +dnl > +dnl * hv2: Will be part of one transport zone: tz1. It should have a > tunnel > +dnl to hv1 but not to hv3 > +dnl > +dnl * hv3: Will be part of one transport zone: tz2. It should have a > tunnel > +dnl to hv1 but not to hv2 > +dnl > +dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels > +dnl between themselves and remove the tunnels to other Chassis which now > +dnl belongs to some TZs > +dnl > +as hv1 > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2 > + > +as hv2 > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1 > + > +as hv3 > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz2 > + > +as hv1 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv2-0 > +ovn-hv3-0 > +]]) > + > +as hv2 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +]]) > + > +as hv3 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +]]) > + > +as hv4 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv5-0 > +]]) > + > +as hv5 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv4-0 > +]]) > + > +dnl Removing the transport zones should make all Chassis to create > +dnl tunnels between every other Chassis again > +for i in 1 2 3; do > + as hv$i > + ovs-vsctl remove open . external-ids ovn-transport-zones > +done > + > +as hv1 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv2 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv3-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv3 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv4-0 > +ovn-hv5-0 > +]]) > + > +as hv4 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv5-0 > +]]) > + > +as hv5 > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > awk NF | sort], [0], > +[[ovn-hv1-0 > +ovn-hv2-0 > +ovn-hv3-0 > +ovn-hv4-0 > +]]) > + > +OVN_CLEANUP([hv1], [hv2], [hv3]) > +AT_CLEANUP > -- > 2.21.0 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On Wed, Apr 17, 2019 at 4:46 PM Numan Siddique <nusiddiq@redhat.com> wrote: > > On Wed, Apr 17, 2019 at 8:21 PM <lmartins@redhat.com> wrote: > > > From: Lucas Alvares Gomes <lucasagomes@gmail.com> > > > > This patch is adding support for Transport Zones. Transport zones (a.k.a > > TZs) is way to enable users of OVN to separate Chassis into different > > logical groups that will only form tunnels between members of the same > > groups. Each Chassis can belong to one or more Transport Zones. If > > not set, the Chassis will be considered part of a default group. > > > > Configuring Transport Zones is done by creating a key called > > "ovn-transport-zones" in the external_ids column of the Open_vSwitch > > table from the local OVS instance. The value is a string with the name > > of the Transport Zone that this instance is part of. Multiple TZs can > > be specified with a comma-separated list. For example: > > > > $ sudo ovs-vsctl set open . external-ids:ovn-transport-zones=tz1 > > > > or > > > > $ sudo ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2,tz3 > > > > This configuration is also exposed in the Chassis table of the OVN > > Southbound Database in a new column called "transport_zones". > > > > The use for Transport Zones includes but are not limited to: > > > > * Edge computing: As a way to preventing edge sites from trying to create > > tunnels with every node on every other edge site while still allowing > > these sites to create tunnels with the central node. > > > > * Extra security layer: Where users wants to create "trust zones" > > and prevent computes in a more secure zone to communicate with a less > > secure zone. > > > > This patch is also backward compatible so the upgrade guide for OVN [0] > > is still valid and the ovn-controller service can be upgraded before the > > OVSDBs. > > > > [0] http://docs.openvswitch.org/en/latest/intro/install/ovn-upgrades/ > > > > Reported-by: Daniel Alvarez Sanchez <dalvarez@redhat.com> > > Reported-at: > > https://mail.openvswitch.org/pipermail/ovs-discuss/2019-February/048255.html > > Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com> > > --- > > v3 -> v4 > > * Stopped using the "external_ids" column of the Chassis table and > > instead added a new column called "transport_zones" to hold the set of > > transport zones that the Chassis is part of. > > > > v2 -> v3 > > * Enhanced the test to include two more Chassis and assert the case > > where Chassis with no TZs set will have tunnels formed between them. > > * Rebased the patch on top of the latest master branch. > > > > v1 -> v2 > > > > * Rename the function check_chassis_tzones to chassis_tzones_overlap. > > * Fix a memory leak in chassis_tzones_overlap. > > * Pass the transport_zones to encaps_run() as a "const char *" > > instead of "struct sbrec_chassis". With this we can also avoid not > > running the function in case the Chassis entry is not yet created. > > > > NEWS | 3 + > > ovn/controller/chassis.c | 26 ++++- > > ovn/controller/chassis.h | 4 +- > > ovn/controller/encaps.c | 35 ++++++- > > ovn/controller/encaps.h | 4 +- > > ovn/controller/ovn-controller.8.xml | 9 ++ > > ovn/controller/ovn-controller.c | 19 +++- > > ovn/ovn-sb.ovsschema | 7 +- > > ovn/ovn-sb.xml | 8 ++ > > tests/ovn.at | 151 ++++++++++++++++++++++++++++ > > 10 files changed, 257 insertions(+), 9 deletions(-) > > > > diff --git a/NEWS b/NEWS > > index c7440b476..e09f59d64 100644 > > --- a/NEWS > > +++ b/NEWS > > @@ -33,6 +33,9 @@ Post-v2.11.0 > > * Added Policy-based routing(PBR) support to create > > permit/deny/reroute > > policies on the logical router. New table(Logical_Router_Policy) > > added in > > OVN-NB schema. New "ovn-nbctl" commands to add/delete/list PBR > > policies. > > + * Support for Transport Zones, a way to separate chassis into > > + logical groups which results in tunnels only been formed between > > + members of the same transport zone(s). > > - New QoS type "linux-netem" on Linux. > > - Added support for TLS Server Name Indication (SNI). > > > > diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c > > index 58d5d49d5..0f537f1f7 100644 > > --- a/ovn/controller/chassis.c > > +++ b/ovn/controller/chassis.c > > @@ -19,6 +19,7 @@ > > #include "chassis.h" > > > > #include "lib/smap.h" > > +#include "lib/sset.h" > > #include "lib/vswitch-idl.h" > > #include "openvswitch/dynamic-string.h" > > #include "openvswitch/vlog.h" > > @@ -73,13 +74,34 @@ get_cms_options(const struct smap *ext_ids) > > return smap_get_def(ext_ids, "ovn-cms-options", ""); > > } > > > > +static void > > +update_chassis_transport_zones(const struct sset *transport_zones, > > + const struct sbrec_chassis *chassis_rec) > > +{ > > + struct sset chassis_tzones_set = > > SSET_INITIALIZER(&chassis_tzones_set); > > + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { > > + sset_add(&chassis_tzones_set, chassis_rec->transport_zones[i]); > > + } > > + > > + /* Only update the transport zones if something changed */ > > + if (!sset_equals(transport_zones, &chassis_tzones_set)) { > > + const char **ls_arr = sset_array(transport_zones); > > + sbrec_chassis_set_transport_zones(chassis_rec, ls_arr, > > + sset_count(transport_zones)); > > + free(ls_arr); > > + } > > + > > + sset_destroy(&chassis_tzones_set); > > +} > > + > > /* Returns this chassis's Chassis record, if it is available. */ > > const struct sbrec_chassis * > > chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > const struct ovsrec_open_vswitch_table *ovs_table, > > const char *chassis_id, > > - const struct ovsrec_bridge *br_int) > > + const struct ovsrec_bridge *br_int, > > + const struct sset *transport_zones) > > { > > const struct sbrec_chassis *chassis_rec > > = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); > > @@ -157,6 +179,8 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > > sbrec_chassis_set_hostname(chassis_rec, hostname); > > } > > > > + update_chassis_transport_zones(transport_zones, chassis_rec); > > + > > /* Determine new values for Chassis external-ids. */ > > const char *chassis_bridge_mappings > > = get_bridge_mappings(&chassis_rec->external_ids); > > diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h > > index 6b1c357d2..9847e19f6 100644 > > --- a/ovn/controller/chassis.h > > +++ b/ovn/controller/chassis.h > > @@ -25,13 +25,15 @@ struct ovsrec_bridge; > > struct ovsrec_open_vswitch_table; > > struct sbrec_chassis; > > struct sbrec_chassis_table; > > +struct sset; > > > > void chassis_register_ovs_idl(struct ovsdb_idl *); > > const struct sbrec_chassis *chassis_run( > > struct ovsdb_idl_txn *ovnsb_idl_txn, > > struct ovsdb_idl_index *sbrec_chassis_by_name, > > const struct ovsrec_open_vswitch_table *, > > - const char *chassis_id, const struct ovsrec_bridge *br_int); > > + const char *chassis_id, const struct ovsrec_bridge *br_int, > > + const struct sset *transport_zones); > > bool chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, > > const struct sbrec_chassis *); > > > > diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c > > index 610b833de..dcf78108d 100644 > > --- a/ovn/controller/encaps.c > > +++ b/ovn/controller/encaps.c > > @@ -195,13 +195,36 @@ chassis_tunnel_add(const struct sbrec_chassis > > *chassis_rec, const struct sbrec_s > > return tuncnt; > > } > > > > +/* > > +* Returns true if transport_zones and chassis_rec->transport_zones > > +* have at least one common transport zone. > > +*/ > > +static bool > > +chassis_tzones_overlap(const struct sset *transport_zones, > > + const struct sbrec_chassis *chassis_rec) > > +{ > > + /* If neither Chassis belongs to any transport zones, return true to > > + * form a tunnel between them */ > > + if (!chassis_rec->n_transport_zones && > > sset_is_empty(transport_zones)) { > > + return true; > > + } > > + > > + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { > > + if (sset_contains(transport_zones, > > chassis_rec->transport_zones[i])) { > > + return true; > > + } > > + } > > + return false; > > +} > > + > > void > > encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > > const struct ovsrec_bridge_table *bridge_table, > > const struct ovsrec_bridge *br_int, > > const struct sbrec_chassis_table *chassis_table, > > const char *chassis_id, > > - const struct sbrec_sb_global *sbg) > > + const struct sbrec_sb_global *sbg, > > + const struct sset *transport_zones) > > { > > if (!ovs_idl_txn || !br_int) { > > return; > > @@ -251,7 +274,15 @@ encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > > > > SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) { > > if (strcmp(chassis_rec->name, chassis_id)) { > > - /* Create tunnels to the other chassis. */ > > + /* Create tunnels to the other Chassis belonging to the > > + * same transport zone */ > > + if (!chassis_tzones_overlap(transport_zones, chassis_rec)) { > > + VLOG_DBG("Skipping encap creation for Chassis '%s' > > because " > > + "it belongs to different transport zones", > > + chassis_rec->name); > > + continue; > > + } > > + > > if (chassis_tunnel_add(chassis_rec, sbg, &tc) == 0) { > > VLOG_INFO("Creating encap for '%s' failed", > > chassis_rec->name); > > continue; > > diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h > > index 3e0e110ef..7ed3e0939 100644 > > --- a/ovn/controller/encaps.h > > +++ b/ovn/controller/encaps.h > > @@ -25,6 +25,7 @@ struct ovsrec_bridge_table; > > struct sbrec_chassis_table; > > struct sbrec_sb_global; > > struct ovsrec_open_vswitch_table; > > +struct sset; > > > > void encaps_register_ovs_idl(struct ovsdb_idl *); > > void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > > @@ -32,7 +33,8 @@ void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, > > const struct ovsrec_bridge *br_int, > > const struct sbrec_chassis_table *, > > const char *chassis_id, > > - const struct sbrec_sb_global *); > > + const struct sbrec_sb_global *, > > + const struct sset *transport_zones); > > > > bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn, > > const struct ovsrec_bridge *br_int); > > diff --git a/ovn/controller/ovn-controller.8.xml > > b/ovn/controller/ovn-controller.8.xml > > index fd2e10a7a..072ec5820 100644 > > --- a/ovn/controller/ovn-controller.8.xml > > +++ b/ovn/controller/ovn-controller.8.xml > > @@ -167,6 +167,15 @@ > > specific to this particular chassis. An example would be: > > <code>cms_option1,cms_option2:foo</code>. > > </dd> > > + > > + <dt><code>external_ids:ovn-transport-zones</code></dt> > > + <dd> > > + The transport zone(s) that this chassis belongs to. Transport > > + zones is a way to group different chassis so that tunnels are only > > + formed between members of the same group(s). Multiple transport > > + zones may be specified with a comma-separated list. For example: > > + tz1,tz2,tz3. > > + </dd> > > </dl> > > > > <p> > > diff --git a/ovn/controller/ovn-controller.c > > b/ovn/controller/ovn-controller.c > > index cf4907db3..69eeee5dc 100644 > > --- a/ovn/controller/ovn-controller.c > > +++ b/ovn/controller/ovn-controller.c > > @@ -512,6 +512,14 @@ get_nb_cfg(const struct sbrec_sb_global_table > > *sb_global_table) > > return sb ? sb->nb_cfg : 0; > > } > > > > +static const char * > > +get_transport_zones(const struct ovsrec_open_vswitch_table *ovs_table) > > +{ > > + const struct ovsrec_open_vswitch *cfg > > + = ovsrec_open_vswitch_table_first(ovs_table); > > + return smap_get_def(&cfg->external_ids, "ovn-transport-zones", ""); > > +} > > + > > static void > > ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > > { > > @@ -679,6 +687,11 @@ main(int argc, char *argv[]) > > * <datapath-tunnel-key>_<port-tunnel-key> */ > > struct sset local_lport_ids = > > SSET_INITIALIZER(&local_lport_ids); > > struct sset active_tunnels = > > SSET_INITIALIZER(&active_tunnels); > > + /* Contains the transport zones that this Chassis belongs to > > */ > > + struct sset transport_zones = > > SSET_INITIALIZER(&transport_zones); > > + sset_from_delimited_string(&transport_zones, > > + get_transport_zones(ovsrec_open_vswitch_table_get( > > + ovs_idl_loop.idl)), ","); > > > > const struct ovsrec_bridge *br_int > > = get_br_int(ovs_idl_txn, > > @@ -693,12 +706,13 @@ main(int argc, char *argv[]) > > chassis = chassis_run( > > ovnsb_idl_txn, sbrec_chassis_by_name, > > ovsrec_open_vswitch_table_get(ovs_idl_loop.idl), > > - chassis_id, br_int); > > + chassis_id, br_int, &transport_zones); > > encaps_run( > > ovs_idl_txn, > > ovsrec_bridge_table_get(ovs_idl_loop.idl), br_int, > > sbrec_chassis_table_get(ovnsb_idl_loop.idl), > > chassis_id, > > - sbrec_sb_global_first(ovnsb_idl_loop.idl)); > > + sbrec_sb_global_first(ovnsb_idl_loop.idl), > > + &transport_zones); > > > > if (ofctrl_is_connected()) { > > /* Calculate the active tunnels only if have an an > > active > > @@ -848,6 +862,7 @@ main(int argc, char *argv[]) > > sset_destroy(&local_lports); > > sset_destroy(&local_lport_ids); > > sset_destroy(&active_tunnels); > > + sset_destroy(&transport_zones); > > > > struct local_datapath *cur_node, *next_node; > > HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, > > diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema > > index d87a02e7b..98007cb6e 100644 > > --- a/ovn/ovn-sb.ovsschema > > +++ b/ovn/ovn-sb.ovsschema > > @@ -1,7 +1,7 @@ > > { > > "name": "OVN_Southbound", > > "version": "2.2.0", > > > > Since you are adding a new column, can you please bump the version to > "2.2.1" ? > Ah bummer, I missed it! Thanks for the review, I will update the version. > With this change > Acked-by: Numan Siddique <nusiddiq@redhat.com> > > Thanks > Numan > > - "cksum": "2100715070 17222", > > + "cksum": "4060521526 17409", > > "tables": { > > "SB_Global": { > > "columns": { > > @@ -37,7 +37,10 @@ > > "nb_cfg": {"type": {"key": "integer"}}, > > "external_ids": { > > "type": {"key": "string", "value": "string", > > - "min": 0, "max": "unlimited"}}}, > > + "min": 0, "max": "unlimited"}}, > > + "transport_zones" : {"type": {"key": "string", > > + "min": 0, > > + "max": "unlimited"}}}, > > "isRoot": true, > > "indexes": [["name"]]}, > > "Encap": { > > diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml > > index 5c4a852a5..e4ac59f1c 100644 > > --- a/ovn/ovn-sb.xml > > +++ b/ovn/ovn-sb.xml > > @@ -293,6 +293,14 @@ > > See <code>ovn-controller</code>(8) for more information. > > </column> > > > > + <column name="transport_zones"> > > + <code>ovn-controller</code> populates this key with the transport > > + zones configured in the <ref table="Open_vSwitch" > > + column="external_ids:ovn-transport-zones"/> column of the > > Open_vSwitch > > + database's <ref table="Open_vSwitch" db="Open_vSwitch"/> table. > > + See <code>ovn-controller</code>(8) for more information. > > + </column> > > + > > <group title="Common Columns"> > > The overall purpose of these columns is described under <code>Common > > Columns</code> at the beginning of this document. > > diff --git a/tests/ovn.at b/tests/ovn.at > > index b3500e8c9..ad4d23caa 100644 > > --- a/tests/ovn.at > > +++ b/tests/ovn.at > > @@ -13652,3 +13652,154 @@ ovn-nbctl list logical_switch_port > > ovn-nbctl list logical_router_port > > > > AT_CLEANUP > > + > > +AT_SETUP([ovn -- test transport zones]) > > +ovn_start > > + > > +net_add n1 > > +for i in 1 2 3 4 5; do > > + sim_add hv$i > > + as hv$i > > + ovs-vsctl add-br br-phys > > + ovn_attach n1 br-phys 192.168.$i.1 > > +done > > + > > +dnl Assert that each Chassis has a tunnel formed to every other Chassis > > +as hv1 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv2 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv3 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv4 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv5 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +]]) > > + > > +dnl Let's now add some Chassis to different transport zones > > +dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it > > +dnl should have tunnels formed between the other two Chassis (hv2 and > > hv3) > > +dnl > > +dnl * hv2: Will be part of one transport zone: tz1. It should have a > > tunnel > > +dnl to hv1 but not to hv3 > > +dnl > > +dnl * hv3: Will be part of one transport zone: tz2. It should have a > > tunnel > > +dnl to hv1 but not to hv2 > > +dnl > > +dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels > > +dnl between themselves and remove the tunnels to other Chassis which now > > +dnl belongs to some TZs > > +dnl > > +as hv1 > > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2 > > + > > +as hv2 > > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1 > > + > > +as hv3 > > +ovs-vsctl set open . external-ids:ovn-transport-zones=tz2 > > + > > +as hv1 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv2-0 > > +ovn-hv3-0 > > +]]) > > + > > +as hv2 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +]]) > > + > > +as hv3 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +]]) > > + > > +as hv4 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv5-0 > > +]]) > > + > > +as hv5 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv4-0 > > +]]) > > + > > +dnl Removing the transport zones should make all Chassis to create > > +dnl tunnels between every other Chassis again > > +for i in 1 2 3; do > > + as hv$i > > + ovs-vsctl remove open . external-ids ovn-transport-zones > > +done > > + > > +as hv1 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv2 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv3 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv4-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv4 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv5-0 > > +]]) > > + > > +as hv5 > > +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | > > awk NF | sort], [0], > > +[[ovn-hv1-0 > > +ovn-hv2-0 > > +ovn-hv3-0 > > +ovn-hv4-0 > > +]]) > > + > > +OVN_CLEANUP([hv1], [hv2], [hv3]) > > +AT_CLEANUP > > -- > > 2.21.0 > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
On Wed, Apr 17, 2019 at 09:15:33PM +0530, Numan Siddique wrote: > On Wed, Apr 17, 2019 at 8:21 PM <lmartins@redhat.com> wrote: > > diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema > > index d87a02e7b..98007cb6e 100644 > > --- a/ovn/ovn-sb.ovsschema > > +++ b/ovn/ovn-sb.ovsschema > > @@ -1,7 +1,7 @@ > > { > > "name": "OVN_Southbound", > > "version": "2.2.0", > > > > Since you are adding a new column, can you please bump the version to > "2.2.1" ? > > With this change > Acked-by: Numan Siddique <nusiddiq@redhat.com> New columns should bump the middle digit, e.g. 2.2.0 -> 2.3.0.
diff --git a/NEWS b/NEWS index c7440b476..e09f59d64 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,9 @@ Post-v2.11.0 * Added Policy-based routing(PBR) support to create permit/deny/reroute policies on the logical router. New table(Logical_Router_Policy) added in OVN-NB schema. New "ovn-nbctl" commands to add/delete/list PBR policies. + * Support for Transport Zones, a way to separate chassis into + logical groups which results in tunnels only been formed between + members of the same transport zone(s). - New QoS type "linux-netem" on Linux. - Added support for TLS Server Name Indication (SNI). diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c index 58d5d49d5..0f537f1f7 100644 --- a/ovn/controller/chassis.c +++ b/ovn/controller/chassis.c @@ -19,6 +19,7 @@ #include "chassis.h" #include "lib/smap.h" +#include "lib/sset.h" #include "lib/vswitch-idl.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" @@ -73,13 +74,34 @@ get_cms_options(const struct smap *ext_ids) return smap_get_def(ext_ids, "ovn-cms-options", ""); } +static void +update_chassis_transport_zones(const struct sset *transport_zones, + const struct sbrec_chassis *chassis_rec) +{ + struct sset chassis_tzones_set = SSET_INITIALIZER(&chassis_tzones_set); + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { + sset_add(&chassis_tzones_set, chassis_rec->transport_zones[i]); + } + + /* Only update the transport zones if something changed */ + if (!sset_equals(transport_zones, &chassis_tzones_set)) { + const char **ls_arr = sset_array(transport_zones); + sbrec_chassis_set_transport_zones(chassis_rec, ls_arr, + sset_count(transport_zones)); + free(ls_arr); + } + + sset_destroy(&chassis_tzones_set); +} + /* Returns this chassis's Chassis record, if it is available. */ const struct sbrec_chassis * chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_chassis_by_name, const struct ovsrec_open_vswitch_table *ovs_table, const char *chassis_id, - const struct ovsrec_bridge *br_int) + const struct ovsrec_bridge *br_int, + const struct sset *transport_zones) { const struct sbrec_chassis *chassis_rec = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); @@ -157,6 +179,8 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_chassis_set_hostname(chassis_rec, hostname); } + update_chassis_transport_zones(transport_zones, chassis_rec); + /* Determine new values for Chassis external-ids. */ const char *chassis_bridge_mappings = get_bridge_mappings(&chassis_rec->external_ids); diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h index 6b1c357d2..9847e19f6 100644 --- a/ovn/controller/chassis.h +++ b/ovn/controller/chassis.h @@ -25,13 +25,15 @@ struct ovsrec_bridge; struct ovsrec_open_vswitch_table; struct sbrec_chassis; struct sbrec_chassis_table; +struct sset; void chassis_register_ovs_idl(struct ovsdb_idl *); const struct sbrec_chassis *chassis_run( struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_chassis_by_name, const struct ovsrec_open_vswitch_table *, - const char *chassis_id, const struct ovsrec_bridge *br_int); + const char *chassis_id, const struct ovsrec_bridge *br_int, + const struct sset *transport_zones); bool chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_chassis *); diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c index 610b833de..dcf78108d 100644 --- a/ovn/controller/encaps.c +++ b/ovn/controller/encaps.c @@ -195,13 +195,36 @@ chassis_tunnel_add(const struct sbrec_chassis *chassis_rec, const struct sbrec_s return tuncnt; } +/* +* Returns true if transport_zones and chassis_rec->transport_zones +* have at least one common transport zone. +*/ +static bool +chassis_tzones_overlap(const struct sset *transport_zones, + const struct sbrec_chassis *chassis_rec) +{ + /* If neither Chassis belongs to any transport zones, return true to + * form a tunnel between them */ + if (!chassis_rec->n_transport_zones && sset_is_empty(transport_zones)) { + return true; + } + + for (int i = 0; i < chassis_rec->n_transport_zones; i++) { + if (sset_contains(transport_zones, chassis_rec->transport_zones[i])) { + return true; + } + } + return false; +} + void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, const struct ovsrec_bridge_table *bridge_table, const struct ovsrec_bridge *br_int, const struct sbrec_chassis_table *chassis_table, const char *chassis_id, - const struct sbrec_sb_global *sbg) + const struct sbrec_sb_global *sbg, + const struct sset *transport_zones) { if (!ovs_idl_txn || !br_int) { return; @@ -251,7 +274,15 @@ encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) { if (strcmp(chassis_rec->name, chassis_id)) { - /* Create tunnels to the other chassis. */ + /* Create tunnels to the other Chassis belonging to the + * same transport zone */ + if (!chassis_tzones_overlap(transport_zones, chassis_rec)) { + VLOG_DBG("Skipping encap creation for Chassis '%s' because " + "it belongs to different transport zones", + chassis_rec->name); + continue; + } + if (chassis_tunnel_add(chassis_rec, sbg, &tc) == 0) { VLOG_INFO("Creating encap for '%s' failed", chassis_rec->name); continue; diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h index 3e0e110ef..7ed3e0939 100644 --- a/ovn/controller/encaps.h +++ b/ovn/controller/encaps.h @@ -25,6 +25,7 @@ struct ovsrec_bridge_table; struct sbrec_chassis_table; struct sbrec_sb_global; struct ovsrec_open_vswitch_table; +struct sset; void encaps_register_ovs_idl(struct ovsdb_idl *); void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, @@ -32,7 +33,8 @@ void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn, const struct ovsrec_bridge *br_int, const struct sbrec_chassis_table *, const char *chassis_id, - const struct sbrec_sb_global *); + const struct sbrec_sb_global *, + const struct sset *transport_zones); bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn, const struct ovsrec_bridge *br_int); diff --git a/ovn/controller/ovn-controller.8.xml b/ovn/controller/ovn-controller.8.xml index fd2e10a7a..072ec5820 100644 --- a/ovn/controller/ovn-controller.8.xml +++ b/ovn/controller/ovn-controller.8.xml @@ -167,6 +167,15 @@ specific to this particular chassis. An example would be: <code>cms_option1,cms_option2:foo</code>. </dd> + + <dt><code>external_ids:ovn-transport-zones</code></dt> + <dd> + The transport zone(s) that this chassis belongs to. Transport + zones is a way to group different chassis so that tunnels are only + formed between members of the same group(s). Multiple transport + zones may be specified with a comma-separated list. For example: + tz1,tz2,tz3. + </dd> </dl> <p> diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index cf4907db3..69eeee5dc 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -512,6 +512,14 @@ get_nb_cfg(const struct sbrec_sb_global_table *sb_global_table) return sb ? sb->nb_cfg : 0; } +static const char * +get_transport_zones(const struct ovsrec_open_vswitch_table *ovs_table) +{ + const struct ovsrec_open_vswitch *cfg + = ovsrec_open_vswitch_table_first(ovs_table); + return smap_get_def(&cfg->external_ids, "ovn-transport-zones", ""); +} + static void ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) { @@ -679,6 +687,11 @@ main(int argc, char *argv[]) * <datapath-tunnel-key>_<port-tunnel-key> */ struct sset local_lport_ids = SSET_INITIALIZER(&local_lport_ids); struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels); + /* Contains the transport zones that this Chassis belongs to */ + struct sset transport_zones = SSET_INITIALIZER(&transport_zones); + sset_from_delimited_string(&transport_zones, + get_transport_zones(ovsrec_open_vswitch_table_get( + ovs_idl_loop.idl)), ","); const struct ovsrec_bridge *br_int = get_br_int(ovs_idl_txn, @@ -693,12 +706,13 @@ main(int argc, char *argv[]) chassis = chassis_run( ovnsb_idl_txn, sbrec_chassis_by_name, ovsrec_open_vswitch_table_get(ovs_idl_loop.idl), - chassis_id, br_int); + chassis_id, br_int, &transport_zones); encaps_run( ovs_idl_txn, ovsrec_bridge_table_get(ovs_idl_loop.idl), br_int, sbrec_chassis_table_get(ovnsb_idl_loop.idl), chassis_id, - sbrec_sb_global_first(ovnsb_idl_loop.idl)); + sbrec_sb_global_first(ovnsb_idl_loop.idl), + &transport_zones); if (ofctrl_is_connected()) { /* Calculate the active tunnels only if have an an active @@ -848,6 +862,7 @@ main(int argc, char *argv[]) sset_destroy(&local_lports); sset_destroy(&local_lport_ids); sset_destroy(&active_tunnels); + sset_destroy(&transport_zones); struct local_datapath *cur_node, *next_node; HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema index d87a02e7b..98007cb6e 100644 --- a/ovn/ovn-sb.ovsschema +++ b/ovn/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", "version": "2.2.0", - "cksum": "2100715070 17222", + "cksum": "4060521526 17409", "tables": { "SB_Global": { "columns": { @@ -37,7 +37,10 @@ "nb_cfg": {"type": {"key": "integer"}}, "external_ids": { "type": {"key": "string", "value": "string", - "min": 0, "max": "unlimited"}}}, + "min": 0, "max": "unlimited"}}, + "transport_zones" : {"type": {"key": "string", + "min": 0, + "max": "unlimited"}}}, "isRoot": true, "indexes": [["name"]]}, "Encap": { diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index 5c4a852a5..e4ac59f1c 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -293,6 +293,14 @@ See <code>ovn-controller</code>(8) for more information. </column> + <column name="transport_zones"> + <code>ovn-controller</code> populates this key with the transport + zones configured in the <ref table="Open_vSwitch" + column="external_ids:ovn-transport-zones"/> column of the Open_vSwitch + database's <ref table="Open_vSwitch" db="Open_vSwitch"/> table. + See <code>ovn-controller</code>(8) for more information. + </column> + <group title="Common Columns"> The overall purpose of these columns is described under <code>Common Columns</code> at the beginning of this document. diff --git a/tests/ovn.at b/tests/ovn.at index b3500e8c9..ad4d23caa 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -13652,3 +13652,154 @@ ovn-nbctl list logical_switch_port ovn-nbctl list logical_router_port AT_CLEANUP + +AT_SETUP([ovn -- test transport zones]) +ovn_start + +net_add n1 +for i in 1 2 3 4 5; do + sim_add hv$i + as hv$i + ovs-vsctl add-br br-phys + ovn_attach n1 br-phys 192.168.$i.1 +done + +dnl Assert that each Chassis has a tunnel formed to every other Chassis +as hv1 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv2-0 +ovn-hv3-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv2 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv3-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv3 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv4 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv3-0 +ovn-hv5-0 +]]) + +as hv5 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv3-0 +ovn-hv4-0 +]]) + +dnl Let's now add some Chassis to different transport zones +dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it +dnl should have tunnels formed between the other two Chassis (hv2 and hv3) +dnl +dnl * hv2: Will be part of one transport zone: tz1. It should have a tunnel +dnl to hv1 but not to hv3 +dnl +dnl * hv3: Will be part of one transport zone: tz2. It should have a tunnel +dnl to hv1 but not to hv2 +dnl +dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels +dnl between themselves and remove the tunnels to other Chassis which now +dnl belongs to some TZs +dnl +as hv1 +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2 + +as hv2 +ovs-vsctl set open . external-ids:ovn-transport-zones=tz1 + +as hv3 +ovs-vsctl set open . external-ids:ovn-transport-zones=tz2 + +as hv1 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv2-0 +ovn-hv3-0 +]]) + +as hv2 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +]]) + +as hv3 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +]]) + +as hv4 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv5-0 +]]) + +as hv5 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv4-0 +]]) + +dnl Removing the transport zones should make all Chassis to create +dnl tunnels between every other Chassis again +for i in 1 2 3; do + as hv$i + ovs-vsctl remove open . external-ids ovn-transport-zones +done + +as hv1 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv2-0 +ovn-hv3-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv2 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv3-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv3 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv4-0 +ovn-hv5-0 +]]) + +as hv4 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv3-0 +ovn-hv5-0 +]]) + +as hv5 +AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0], +[[ovn-hv1-0 +ovn-hv2-0 +ovn-hv3-0 +ovn-hv4-0 +]]) + +OVN_CLEANUP([hv1], [hv2], [hv3]) +AT_CLEANUP