[ovs-dev] [ovn-controller-vtep V7 2/3] ovn-controller-vtep: Extend vtep module to install Ucast_Macs_Remote.
Alex Wang
alexw at nicira.com
Thu Aug 20 16:34:58 UTC 2015
On Thu, Aug 20, 2015 at 9:09 AM, Russell Bryant <rbryant at redhat.com> wrote:
> Looks good to me except for the one thing I noticed that was introduced
> in the last patch.
>
> On 08/18/2015 05:58 PM, Alex Wang wrote:
> > This commit extends the vtep module to support creating the
> > 'Ucast_Macs_Remote' table entries in the vtep database for
> > MAC addresses on the ovn logical ports.
> >
> > Signed-off-by: Alex Wang <alexw at nicira.com>
> > ---
> > V6->V7:
> > - rebase.
> > - adopt suggestions from Russell.
> >
> > V5->V6:
> > - rebase.
> >
> > V4->V5:
> > - rebase on top of master.
> > - rewrite the feature since a lot have changed.
> >
> > V3->V4:
> > - add logic to remove Ucast_Macs_Remote for non-existent MACs.
> >
> > V2->V3:
> > - rebase to master.
> >
> > PATCH->V2:
> > - split into separate commit.
> > - few optimizations.
> > ---
> > ovn/controller-vtep/vtep.c | 303
> ++++++++++++++++++++++++++++++++++++++----
> > tests/ovn-controller-vtep.at | 136 +++++++++++++++++++
> > 2 files changed, 411 insertions(+), 28 deletions(-)
> >
> > diff --git a/ovn/controller-vtep/vtep.c b/ovn/controller-vtep/vtep.c
> > index 9870296..8f9572c 100644
> > --- a/ovn/controller-vtep/vtep.c
> > +++ b/ovn/controller-vtep/vtep.c
> > @@ -19,7 +19,8 @@
> >
> > #include "lib/hash.h"
> > #include "lib/hmap.h"
> > -#include "lib/smap.h"
> > +#include "lib/shash.h"
> > +#include "lib/sset.h"
> > #include "lib/util.h"
> > #include "ovn-controller-vtep.h"
> > #include "openvswitch/vlog.h"
> > @@ -29,39 +30,75 @@
> > VLOG_DEFINE_THIS_MODULE(vtep);
> >
> > /*
> > - * Scans through the Binding table in ovnsb and updates the vtep logical
> > - * switch tunnel keys.
> > + * Scans through the Binding table in ovnsb, and updates the vtep
> logical
> > + * switch tunnel keys and the 'Ucast_Macs_Remote' table in the VTEP
> > + * database.
> > *
> > */
> >
> > +/* Searches the 'chassis_rec->encaps' for the first vtep tunnel
> > + * configuration, returns the 'ip'. */
> > +static const char *
> > +get_chassis_vtep_ip(const struct sbrec_chassis *chassis_rec)
> > +{
> > + if (chassis_rec) {
> > + size_t i;
> > +
> > + for (i = 0; i < chassis_rec->n_encaps; i++) {
> > + if (!strcmp(chassis_rec->encaps[i]->type, "vxlan")) {
> > + return chassis_rec->encaps[i]->ip;
> > + }
> > + }
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > +/* Creates a new 'Ucast_Macs_Remote'. */
> > +static struct vteprec_ucast_macs_remote *
> > +create_umr(struct ovsdb_idl_txn *vtep_idl_txn, const char *mac,
> > + const struct vteprec_logical_switch *vtep_ls)
> > +{
> > + struct vteprec_ucast_macs_remote *new_umr;
> > +
> > + new_umr = vteprec_ucast_macs_remote_insert(vtep_idl_txn);
> > + vteprec_ucast_macs_remote_set_MAC(new_umr, mac);
> > + vteprec_ucast_macs_remote_set_logical_switch(new_umr, vtep_ls);
> > +
> > + return new_umr;
> > +}
> > +
> > +/* Creates a new 'Physical_Locator'. */
> > +static struct vteprec_physical_locator *
> > +create_pl(struct ovsdb_idl_txn *vtep_idl_txn, const char *chassis_ip)
> > +{
> > + struct vteprec_physical_locator *new_pl;
> > +
> > + new_pl = vteprec_physical_locator_insert(vtep_idl_txn);
> > + vteprec_physical_locator_set_dst_ip(new_pl, chassis_ip);
> > + vteprec_physical_locator_set_encapsulation_type(new_pl,
> VTEP_ENCAP_TYPE);
> > +
> > + return new_pl;
> > +}
> > +
> > +
> > /* Updates the vtep Logical_Switch table entries' tunnel keys based
> > * on the port bindings. */
> > static void
> > -vtep_lswitch_run(struct controller_vtep_ctx *ctx)
> > +vtep_lswitch_run(struct shash *vtep_pbs, struct shash *vtep_lswitches)
> > {
> > - struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
> > - const struct sbrec_port_binding *port_binding_rec;
> > - const struct vteprec_logical_switch *vtep_ls;
> > -
> > - /* Stores all logical switches to 'vtep_lswitches' with name as
> key. */
> > - VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, ctx->vtep_idl) {
> > - shash_add(&vtep_lswitches, vtep_ls->name, vtep_ls);
> > - }
> > + struct sset used_ls = SSET_INITIALIZER(&used_ls);
> > + struct shash_node *node;
> >
> > - ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
> > - "ovn-controller-vtep: update logical
> switch "
> > - "tunnel keys");
> > /* Collects the logical switch bindings from port binding entries.
> > * Since the binding module has already guaranteed that each vtep
> > * logical switch is bound only to one ovn-sb logical datapath,
> > * we can just iterate and assign tunnel key to vtep logical
> switch. */
> > - SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
> > - if (strcmp(port_binding_rec->type, "vtep")
> > - || !port_binding_rec->chassis) {
> > - continue;
> > - }
> > + SHASH_FOR_EACH (node, vtep_pbs) {
> > + const struct sbrec_port_binding *port_binding_rec = node->data;
> > const char *lswitch_name = smap_get(&port_binding_rec->options,
> > "vtep-logical-switch");
> > + const struct vteprec_logical_switch *vtep_ls;
> >
>
> I went back and mentioned this on the last patch, but I think we're
> missing some validation here to ensure that the vtep port binding we're
> looking at is bound to this chassis and not another one that happens to
> have a logical switch of the same name.
>
By 'this chassis', I think you mean all 'chassis' registered in one VTEP
database. In other words, if we have another VTEP database with same-
named logical switches, the logic here will mistakenly report warning for
Port_Binding entries for other VTEP database, right? I think I'll bring the
'options:vtep_physical_switch' in for help,
Thanks,
Alex Wang,
>
> > /* If 'port_binding_rec->chassis' exists then 'lswitch_name'
> > * must also exist. */
> > @@ -74,14 +111,19 @@ vtep_lswitch_run(struct controller_vtep_ctx *ctx)
> > port_binding_rec->chassis->name);
> > continue;
> > }
> > - vtep_ls = shash_find_and_delete(&vtep_lswitches, lswitch_name);
> > + vtep_ls = shash_find_data(vtep_lswitches, lswitch_name);
> > if (!vtep_ls) {
> > + /* This could only happen when someone is messing up
> > + * using ovn-sbctl command. */
> > VLOG_ERR("logical port (%s) bound to non-exist vtep logical
> "
> > "switch (%s), something is seriously wrong",
> > port_binding_rec->logical_port, lswitch_name);
> > } else {
> > int64_t tnl_key;
> >
> > + if (sset_find(&used_ls, lswitch_name)) {
> > + continue;
> > + }
> > tnl_key = port_binding_rec->datapath->tunnel_key;
> > if (vtep_ls->n_tunnel_key
> > && vtep_ls->tunnel_key[0] != tnl_key) {
> > @@ -90,17 +132,152 @@ vtep_lswitch_run(struct controller_vtep_ctx *ctx)
> > vtep_ls->tunnel_key[0], tnl_key);
> > }
> > vteprec_logical_switch_set_tunnel_key(vtep_ls, &tnl_key, 1);
> > + /* sset will ignore duplicates. */
> > + sset_add(&used_ls, lswitch_name);
> > + }
> > + }
> > + /* Resets the tunnel keys for unused vtep logical switches. */
> > + SHASH_FOR_EACH (node, vtep_lswitches) {
> > + const struct vteprec_logical_switch *vtep_ls = node->data;
> > + if (!sset_find(&used_ls, vtep_ls->name)) {
> > + int64_t tnl_key = 0;
> > + vteprec_logical_switch_set_tunnel_key(node->data, &tnl_key,
> 1);
> > }
> > }
> > + sset_destroy(&used_ls);
> > +}
> > +
> > +/* Updates the vtep 'Ucast_Macs_Remote' table based on non-vtep port
> > + * bindings. */
> > +static void
> > +vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash
> *ucast_macs_rmts,
> > + struct shash *physical_locators, struct shash
> *vtep_lswitches,
> > + struct shash *other_pbs)
> > +{
> > struct shash_node *node;
> > - /* Resets the tunnel keys for the rest of vtep logical switches. */
> > - SHASH_FOR_EACH (node, &vtep_lswitches) {
> > - int64_t tnl_key = 0;
> > + struct hmap ls_map;
> > +
> > + /* Maps from ovn logical datapath tunnel key (which is also the vtep
> > + * logical switch tunnel key) to the corresponding vtep logical
> switch
> > + * instance. Also, the shash map 'added_macs' is used for checking
> > + * duplicated MAC addresses in the same ovn logical datapath. */
> > + struct ls_hash_node {
> > + struct hmap_node hmap_node;
> >
> > - vteprec_logical_switch_set_tunnel_key(node->data, &tnl_key, 1);
> > + const struct vteprec_logical_switch *vtep_ls;
> > + struct shash added_macs;
> > + };
> > +
> > + hmap_init(&ls_map);
> > + SHASH_FOR_EACH (node, vtep_lswitches) {
> > + struct ls_hash_node *ls_node = xmalloc(sizeof *ls_node);
> > +
> > + ls_node->vtep_ls = node->data;
> > + shash_init(&ls_node->added_macs);
> > + hmap_insert(&ls_map, &ls_node->hmap_node,
> > + hash_uint64((uint64_t)
> ls_node->vtep_ls->tunnel_key[0]));
> > }
> >
> > - shash_destroy(&vtep_lswitches);
> > + SHASH_FOR_EACH (node, other_pbs) {
> > + const struct sbrec_port_binding *port_binding_rec = node->data;
> > + const struct sbrec_chassis *chassis_rec;
> > + struct ls_hash_node *ls_node;
> > + const char *chassis_ip;
> > + int64_t tnl_key;
> > + size_t i;
> > +
> > + chassis_rec = port_binding_rec->chassis;
> > + chassis_ip = get_chassis_vtep_ip(chassis_rec);
> > +
> > + /* Unreachable chassis, continue. */
> > + if (!chassis_ip) {
> > + continue;
> > + }
> > +
> > + tnl_key = port_binding_rec->datapath->tunnel_key;
> > + HMAP_FOR_EACH_WITH_HASH (ls_node, hmap_node,
> > + hash_uint64((uint64_t) tnl_key),
> > + &ls_map) {
> > + if (ls_node->vtep_ls->tunnel_key[0] == tnl_key) {
> > + break;
> > + }
> > + }
> > + /* If 'ls_node' is NULL, that means no vtep logical switch is
> > + * attached to the corresponding ovn logical datapath, so pass.
> > + * 'ls_node' will be NULL, if the previous loop does not break,
> > + * since the 'hmap_node' is the first member of the struct. */
> > + if (!ls_node) {
> > + continue;
> > + }
> > +
> > + for (i = 0; i < port_binding_rec->n_mac; i++) {
> > + const struct vteprec_ucast_macs_remote *umr;
> > + const struct vteprec_physical_locator *pl;
> > + const struct sbrec_port_binding *conflict;
> > + char *mac = port_binding_rec->mac[i];
> > +
> > + /* xxx Need to address this later when we support
> > + * update of 'Mcast_Macs_Remote' table in VTEP. */
> > + if (!strcmp(mac, "unknown")) {
> > + continue;
> > + }
> > +
> > + /* Checks for duplicate MAC in the same vtep logical
> switch. */
> > + conflict = shash_find_data(&ls_node->added_macs, mac);
> > + if (conflict) {
> > + VLOG_WARN("MAC address (%s) has already been known to
> be "
> > + "on logical port (%s) in the same logical "
> > + "datapath, so just ignore this logical port
> (%s)",
> > + mac, conflict->logical_port,
> > + port_binding_rec->logical_port);
> > + continue;
> > + }
> > + shash_add(&ls_node->added_macs, mac, port_binding_rec);
> > +
> > + char *mac_ip = xasprintf("%s%s", mac, chassis_ip);
> > + umr = shash_find_data(ucast_macs_rmts, mac_ip);
> > + /* If finds the 'umr' entry for the mac and ip, deletes the
> > + * entry from shash so that it is not gargage collected.
> > + *
> > + * If not found, creates a new 'umr' entry.
> > + *
> > + * If vtep logical switch does not match, the logical port
> > + * owning the MAC may be moved to a new ovn logical
> datapath.
> > + * In that case, just creates a new umr entry for the MAC.
> > + * The old one will be garbage collected. */
> > + if (umr && umr->logical_switch == ls_node->vtep_ls) {
> > + shash_find_and_delete(ucast_macs_rmts, mac_ip);
> > + } else {
> > + const struct vteprec_ucast_macs_remote *new_umr;
> > +
> > + new_umr = create_umr(vtep_idl_txn, mac,
> ls_node->vtep_ls);
> > + pl = shash_find_data(physical_locators, chassis_ip);
> > + if (pl) {
> > + vteprec_ucast_macs_remote_set_locator(new_umr, pl);
> > + } else {
> > + const struct vteprec_physical_locator *new_pl;
> > +
> > + new_pl = create_pl(vtep_idl_txn, chassis_ip);
> > + vteprec_ucast_macs_remote_set_locator(new_umr,
> new_pl);
> > + /* Updates the 'physical_locators'. */
> > + shash_add(physical_locators, chassis_ip, new_pl);
> > + }
> > + }
> > + free(mac_ip);
> > + }
> > + }
> > +
> > + /* Removes all remaining 'umr's, since they do not exist anymore. */
> > + SHASH_FOR_EACH (node, ucast_macs_rmts) {
> > + vteprec_ucast_macs_remote_delete(node->data);
> > + }
> > + struct ls_hash_node *iter, *next;
> > + HMAP_FOR_EACH_SAFE (iter, next, hmap_node, &ls_map) {
> > + hmap_remove(&ls_map, &iter->hmap_node);
> > + shash_destroy(&iter->added_macs);
> > + free(iter);
> > + }
> > + hmap_destroy(&ls_map);
> > }
> >
> > /* Since we do not own any vtep logical switch, just sets their tunnel
> key
> > @@ -123,6 +300,19 @@ vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
> > return done;
> > }
> >
> > +/* Removes all entries in the 'Ucast_Macs_Remote' table in vtep
> database.
> > + * Returns true when all done (no entry to remove). */
> > +static bool
> > +vtep_macs_cleanup(struct ovsdb_idl *vtep_idl)
> > +{
> > + const struct vteprec_ucast_macs_remote *umr;
> > +
> > + VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, vtep_idl) {
> > + vteprec_ucast_macs_remote_delete(umr);
> > + return false;
> > + }
> > + return true;
> > +}
> >
> > /* Updates vtep logical switch tunnel keys. */
> > void
> > @@ -131,7 +321,59 @@ vtep_run(struct controller_vtep_ctx *ctx)
> > if (!ctx->vtep_idl_txn) {
> > return;
> > }
> > - vtep_lswitch_run(ctx);
> > +
> > + struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
> > + struct shash ucast_macs_rmts = SHASH_INITIALIZER(&ucast_macs_rmts);
> > + struct shash physical_locators =
> SHASH_INITIALIZER(&physical_locators);
> > + struct shash vtep_pbs = SHASH_INITIALIZER(&vtep_pbs);
> > + struct shash other_pbs = SHASH_INITIALIZER(&other_pbs);
> > + const struct vteprec_logical_switch *vtep_ls;
> > + const struct vteprec_ucast_macs_remote *umr;
> > + const struct vteprec_physical_locator *pl;
> > + const struct sbrec_port_binding *port_binding_rec;
> > +
> > + /* Collects 'Logical_Switch's. */
> > + VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, ctx->vtep_idl) {
> > + shash_add(&vtep_lswitches, vtep_ls->name, vtep_ls);
> > + }
> > +
> > + /* Collects 'Ucast_Macs_Remote's. */
> > + VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, ctx->vtep_idl) {
> > + char *mac_ip =
> > + xasprintf("%s%s", umr->MAC,
> > + umr->locator ? umr->locator->dst_ip : "");
>
> I'd be tempted to use a "struct ds" around this loop so that I could
> easily reuse the same memory allocation instead of malloc/free every
> time (potentially hundreds or thousands of times), but it's probably not
> a big deal overall.
>
> > +
> > + shash_add(&ucast_macs_rmts, mac_ip, umr);
> > + free(mac_ip);
> > + }
> > + /* Collects 'Physical_Locator's. */
> > + VTEPREC_PHYSICAL_LOCATOR_FOR_EACH (pl, ctx->vtep_idl) {
> > + shash_add(&physical_locators, pl->dst_ip, pl);
> > + }
> > + /* Collects and classifies 'Port_Binding's. */
> > + SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
> > + struct shash *target =
> > + !strcmp(port_binding_rec->type, "vtep") ? &vtep_pbs :
> &other_pbs;
> > +
> > + if (!port_binding_rec->chassis) {
> > + continue;
> > + }
> > + shash_add(target, port_binding_rec->logical_port,
> port_binding_rec);
> > + }
> > +
> > + ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
> > + "ovn-controller-vtep: update logical
> switch "
> > + "tunnel keys and 'ucast_macs_remote's");
> > +
> > + vtep_lswitch_run(&vtep_pbs, &vtep_lswitches);
> > + vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts,
> &physical_locators,
> > + &vtep_lswitches, &other_pbs);
> > +
> > + shash_destroy(&vtep_lswitches);
> > + shash_destroy(&ucast_macs_rmts);
> > + shash_destroy(&physical_locators);
> > + shash_destroy(&vtep_pbs);
> > + shash_destroy(&other_pbs);
> > }
> >
> > /* Cleans up all related entries in vtep. Returns true when done (i.e.
> > @@ -143,7 +385,12 @@ vtep_cleanup(struct controller_vtep_ctx *ctx)
> > return false;
> > }
> >
> > + bool all_done;
> > +
> > ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
> > "cleans up vtep configuration");
> > - return vtep_lswitch_cleanup(ctx->vtep_idl);
> > + all_done = vtep_lswitch_cleanup(ctx->vtep_idl);
> > + all_done = vtep_macs_cleanup(ctx->vtep_idl) && all_done;
> > +
> > + return all_done;
> > }
> > diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at
> > index 1460188..de97bf9 100644
> > --- a/tests/ovn-controller-vtep.at
> > +++ b/tests/ovn-controller-vtep.at
> > @@ -306,3 +306,139 @@ AT_CHECK([vtep-ctl --columns=tunnel_key list
> Logical_Switch | cut -d ':' -f2 | t
> >
> > OVN_CONTROLLER_VTEP_STOP
> > AT_CLEANUP
> > +
> > +
> > +# Tests vtep module 'Ucast_Macs_Remote's.
> > +AT_SETUP([ovn-controller-vtep - test vtep-macs 1])
> > +OVN_CONTROLLER_VTEP_START
> > +
> > +# creates a simple logical network with the vtep device and a fake hv
> chassis
> > +# 'ch0'.
> > +AT_CHECK([ovn-nbctl lport-add br-test vif0])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif0 f0:ab:cd:ef:01:02])
> > +AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
> > +AT_CHECK([ovn-sbctl lport-bind vif0 ch0])
> > +
> > +# creates the logical switch in vtep and adds the corresponding logical
> > +# port to 'br-test'.
> > +AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> > +OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
> [lswitch0])
> > +OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
> br-vtep_lswitch0`"])
> > +
> > +# adds another lswitch 'br-void' in ovn-nb database.
> > +AT_CHECK([ovn-nbctl lswitch-add br-void])
> > +# adds fake hv chassis 'ch1'.
> > +AT_CHECK([ovn-nbctl lport-add br-void vif1])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif1 f0:ab:cd:ef:01:02])
> > +AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
> > +AT_CHECK([ovn-sbctl lport-bind vif1 ch1])
> > +OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])
> > +
> > +# checks Ucast_Macs_Remote creation.
> > +OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
> _uuid`"])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' '], [0], [dnl
> > +"f0:ab:cd:ef:01:02"
> > +])
> > +
> > +# checks physical locator creation.
> > +OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep
> _uuid`"])
> > +AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut -d ':'
> -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
> > +"1.2.3.5"
> > +])
> > +
> > +# checks tunnel creation by ovs-vtep.
> > +OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
> > +AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 | cut
> -d ':' -f2 | tr -d ' '], [0], [dnl
> > +{remote_ip="1.2.3.5"}
> > +])
> > +
> > +# adds another mac to lport.
> > +AT_CHECK([ovn-nbctl lport-set-macs vif0 f0:ab:cd:ef:01:02
> f0:ab:cd:ef:01:03])
> > +OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep 03`"])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' ' | sort], [0], [dnl
> > +
> > +"f0:ab:cd:ef:01:02"
> > +"f0:ab:cd:ef:01:03"
> > +])
> > +
> > +# removes one mac to lport.
> > +AT_CHECK([ovn-nbctl lport-set-macs vif0 f0:ab:cd:ef:01:03])
> > +OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote
> | grep 02`"])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' ' | sort], [0], [dnl
> > +"f0:ab:cd:ef:01:03"
> > +])
> > +
> > +# migrates mac to lport vif1 on 'br-void'.
> > +AT_CHECK([ovn-nbctl lport-set-macs vif0])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif1 f0:ab:cd:ef:01:03])
> > +OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote
> | grep 03`"])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' ' | sort], [0], [dnl
> > +])
> > +
> > +OVN_CONTROLLER_VTEP_STOP
> > +AT_CLEANUP
> > +
> > +
> > +# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
> > +AT_SETUP([ovn-controller-vtep - test vtep-macs 2])
> > +OVN_CONTROLLER_VTEP_START
> > +
> > +# creates a simple logical network with the vtep device and a fake hv
> chassis
> > +# 'ch0'.
> > +AT_CHECK([ovn-nbctl lport-add br-test vif0])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif0 f0:ab:cd:ef:01:02])
> > +AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
> > +AT_CHECK([ovn-sbctl lport-bind vif0 ch0])
> > +
> > +# creates another vif in the same logical switch with duplicate mac.
> > +AT_CHECK([ovn-nbctl lport-add br-test vif1])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif1 f0:ab:cd:ef:01:02])
> > +AT_CHECK([ovn-sbctl lport-bind vif1 ch0])
> > +
> > +# creates the logical switch in vtep and adds the corresponding logical
> > +# port to 'br-test'.
> > +AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> > +OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
> [lswitch0])
> > +OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
> br-vtep_lswitch0`"])
> > +
> > +# checks Ucast_Macs_Remote creation. Should still only be one entry,
> since duplicate
> > +# mac in the same logical switch is not allowed.
> > +OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
> _uuid`"])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' '], [0], [dnl
> > +"f0:ab:cd:ef:01:02"
> > +])
> > +# confirms the warning log.
> > +OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
> > +AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log |
> sed 's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
> > +|WARN|MAC address () has already been known to be on logical port () in
> the same logical datapath, so just ignore this logical port ()
> > +])
> > +
> > +# deletes vif1.
> > +AT_CHECK([ovn-nbctl lport-del vif1])
> > +
> > +# adds another lswitch 'br-void' in ovn-nb database.
> > +AT_CHECK([ovn-nbctl lswitch-add br-void])
> > +# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
> > +AT_CHECK([ovn-nbctl lport-add br-void vif1])
> > +AT_CHECK([ovn-nbctl lport-set-macs vif1 f0:ab:cd:ef:01:02])
> > +AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
> > +AT_CHECK([ovn-sbctl lport-bind vif1 ch1])
> > +OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])
> > +
> > +# creates another logical switch in vtep and adds the corresponding
> logical
> > +# port to 'br-void'.
> > +AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
> > +OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep],
> [lswitch1])
> > +OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
> br-void_lswitch1`"])
> > +
> > +# checks Ucast_Macs_Remote creation. Should see two entries since it
> is allowed
> > +# to have duplicate macs in different logical switches.
> > +OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list Ucast_Macs_Remote |
> grep 02 | wc -l` -gt 1])
> > +AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':'
> -f2- | tr -d ' ' | sort], [0], [dnl
> > +
> > +"f0:ab:cd:ef:01:02"
> > +"f0:ab:cd:ef:01:02"
> > +])
> > +
> > +OVN_CONTROLLER_VTEP_STOP(["/has already been known to be on logical
> port/d"])
> > +AT_CLEANUP
> >
>
>
> --
> Russell Bryant
>
More information about the dev
mailing list