[ovs-dev] [PATCH] Patch v2: OVN: Support BUM traffic in the VTEP schema

Darrell Ball dlu998 at gmail.com
Fri Mar 25 07:04:36 UTC 2016


This patch implements BUM support in the VTEP schema.
This relates to BUM traffic flowing from a gateway towards
HVs. This code would be relevant to HW gateways and
the ovs-vtep simulator.
In order to do this, the mcast macs remote table in the VTEP
schema is populated based on the OVN SB port binding.
For each logical switch, the SB port bindings are queried
to find all the physical locators to send BUM traffic to
and the VTEP DB is updated.
These code changes are contained in vtep.c.

An OVN test for the ovs-vtep based gateway was
enabled for relevant packet types to test this functionality.
This test is contained in ovn.at

The AUTHORS file was updated as well.

Signed-off-by: Darrell Ball <dball at vmware.com>
---
 AUTHORS                    |   1 +
 ovn/controller-vtep/vtep.c | 236 +++++++++++++++++++++++++++++++++++++++------
 tests/ovn.at               |   6 +-
 3 files changed, 212 insertions(+), 31 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 9e44e4c..dd0fc85 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -50,6 +50,7 @@ Daniel Roman            droman at nicira.com
 Daniele Di Proietto     daniele.di.proietto at gmail.com
 Daniele Venturino       daniele.venturino at m3s.it
 Danny Kukawka           danny.kukawka at bisect.de
+Darrell Ball            dlu998 at gmail.com
 Dave Tucker             dave at dtucker.co.uk
 David Erickson          derickso at stanford.edu
 David S. Miller         davem at davemloft.net
diff --git a/ovn/controller-vtep/vtep.c b/ovn/controller-vtep/vtep.c
index 016c2e0..4c7d77e 100644
--- a/ovn/controller-vtep/vtep.c
+++ b/ovn/controller-vtep/vtep.c
@@ -30,6 +30,16 @@
 
 VLOG_DEFINE_THIS_MODULE(vtep);
 
+struct vtep_rec_physical_locator_list_entry {
+    struct ovs_list locators_node;
+    const struct vteprec_physical_locator *vteprec_ploc;
+};
+
+struct mmr_hash_node_data {
+    const struct vteprec_mcast_macs_remote *mmr;
+    struct shash physical_locators;
+};
+
 /*
  * Scans through the Binding table in ovnsb, and updates the vtep logical
  * switch tunnel keys and the 'Ucast_Macs_Remote' table in the VTEP
@@ -84,6 +94,96 @@ create_pl(struct ovsdb_idl_txn *vtep_idl_txn, const char *chassis_ip)
 }
 
 
+/* Creates a new 'Mcast_Macs_Remote'. entry */
+static void
+vtep_create_mmr(struct ovsdb_idl_txn *vtep_idl_txn,
+           const char *mac,
+           const struct vteprec_logical_switch *vtep_ls,
+           const struct vteprec_physical_locator_set *ploc_set)
+{
+    struct vteprec_mcast_macs_remote *new_mmr =
+       vteprec_mcast_macs_remote_insert(vtep_idl_txn);
+
+    vteprec_mcast_macs_remote_set_MAC(new_mmr, mac);
+    vteprec_mcast_macs_remote_set_logical_switch(new_mmr, vtep_ls);
+    vteprec_mcast_macs_remote_set_locator_set(new_mmr, ploc_set);
+}
+
+/* Compares prev and new mmr locator sets and return true if they
+ * differ; false otherwise; also preps new locator set
+ * for database write */
+static bool
+vtep_process_pls(const struct ovs_list *locators_list,
+                 const struct mmr_hash_node_data *mmr_ext,
+                 struct vteprec_physical_locator **locators)
+{
+    int i;
+    size_t n_locators_prev = 0;
+    size_t n_locators_new = list_size(locators_list);
+    struct vtep_rec_physical_locator_list_entry *ploc_entry;
+    const struct vteprec_physical_locator *pl = NULL;
+    bool prev_and_new_locator_lists_differ = false;
+
+    if (mmr_ext) {
+        n_locators_prev = mmr_ext->mmr->locator_set->n_locators;
+    }
+    if (n_locators_prev != n_locators_new) {
+        prev_and_new_locator_lists_differ = true;
+    }
+
+    if (n_locators_new) {
+        i = 0;
+        LIST_FOR_EACH (ploc_entry, locators_node, locators_list) {
+            locators[i] = (struct vteprec_physical_locator *)
+                           ploc_entry->vteprec_ploc;
+            if (mmr_ext) {
+                pl = shash_find_data(&mmr_ext->physical_locators,
+                                     locators[i]->dst_ip);
+                if (!pl) {
+                    prev_and_new_locator_lists_differ = true;
+                }
+            }
+            i++;
+        }
+    }
+
+    return prev_and_new_locator_lists_differ;
+}
+
+/* Creates a new 'Mcast_Macs_Remote' entry if needed.
+ * Also cleans prev remote mcast mac entries as needed */
+static void
+vtep_update_mmr(struct ovsdb_idl_txn *vtep_idl_txn,
+                struct ovs_list *locators_list,
+                const struct vteprec_logical_switch *vtep_ls,
+                const struct mmr_hash_node_data *mmr_ext)
+{
+    struct vteprec_physical_locator **locators = NULL;
+    size_t n_locators_new = list_size(locators_list);
+    bool mmr_changed = false;
+    const struct vteprec_physical_locator_set *ploc_set;
+
+    locators = xmalloc(n_locators_new * sizeof *locators);
+
+    if (vtep_process_pls(locators_list, mmr_ext, locators)) {
+        mmr_changed = true;
+    }
+
+    if (mmr_ext && !n_locators_new) {
+        vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
+    } else if ((mmr_ext && mmr_changed) ||
+               (!mmr_ext && n_locators_new)) {
+
+        ploc_set = vteprec_physical_locator_set_insert(vtep_idl_txn);
+
+        vtep_create_mmr(vtep_idl_txn, "unknown-dst", vtep_ls, ploc_set);
+
+        vteprec_physical_locator_set_set_locators(ploc_set, locators,
+                                                  n_locators_new);
+    }
+    free(locators);
+}
+
 /* Updates the vtep Logical_Switch table entries' tunnel keys based
  * on the port bindings. */
 static void
@@ -149,25 +249,36 @@ vtep_lswitch_run(struct shash *vtep_pbs, struct sset *vtep_pswitches,
     sset_destroy(&used_ls);
 }
 
-/* Updates the vtep 'Ucast_Macs_Remote' table based on non-vtep port
- * bindings. */
+/* Updates the vtep 'Ucast_Macs_Remote' and 'Mcast_Macs_Remote' tables
+ * 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 *non_vtep_pbs)
+              struct shash *mcast_macs_rmts, struct shash *physical_locators,
+              struct shash *vtep_lswitches, struct shash *non_vtep_pbs)
 {
     struct shash_node *node;
     struct hmap ls_map;
 
+    struct vtep_rec_physical_locator_list_entry *ploc_entry;
+    const struct vteprec_physical_locator *pl;
+    const struct vteprec_physical_locator *ls_pl;
+
     /* 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. */
+     * duplicated MAC addresses in the same ovn logical datapath.
+     * mmr_ext is used to track mmr info per LS that needs creation/update
+     * and locators_list collects the physical locators to be bound
+     * for an mmr; physical_locators is used to track existing locators
+     * and filter duplicates. */
     struct ls_hash_node {
         struct hmap_node hmap_node;
 
         const struct vteprec_logical_switch *vtep_ls;
         struct shash added_macs;
+        struct ovs_list locators_list;
+        struct shash physical_locators;
+        struct mmr_hash_node_data *mmr_ext;
     };
 
     hmap_init(&ls_map);
@@ -181,6 +292,9 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts,
         ls_node = xmalloc(sizeof *ls_node);
         ls_node->vtep_ls = vtep_ls;
         shash_init(&ls_node->added_macs);
+        shash_init(&ls_node->physical_locators);
+        list_init(&ls_node->locators_list);
+        ls_node->mmr_ext = NULL;
         hmap_insert(&ls_map, &ls_node->hmap_node,
                     hash_uint64((uint64_t) vtep_ls->tunnel_key[0]));
     }
@@ -222,18 +336,40 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts,
             continue;
         }
 
+        pl = shash_find_data(physical_locators, chassis_ip);
+        if (!pl) {
+            pl = create_pl(vtep_idl_txn, chassis_ip);
+            shash_add(physical_locators, chassis_ip, pl);
+        }
+        ls_pl = shash_find_data(&ls_node->physical_locators, chassis_ip);
+        if (!ls_pl) {
+            ploc_entry = xmalloc(sizeof *ploc_entry);
+            ploc_entry->vteprec_ploc = pl;
+            list_push_back(&ls_node->locators_list,
+                           &ploc_entry->locators_node);
+            shash_add(&ls_node->physical_locators, chassis_ip, pl);
+        }
+
+        char *mac_tnlkey =
+            xasprintf("%s_%"PRId64, "unknown-dst", tnl_key);
+        ls_node->mmr_ext =
+               shash_find_data(mcast_macs_rmts, mac_tnlkey);
+
+        if (ls_node->mmr_ext &&
+            ls_node->mmr_ext->mmr->logical_switch == ls_node->vtep_ls) {
+
+            /* Delete the entry from the hash table so the MMR does
+             * not get removed from the DB later on during stale
+             * checking. */
+            shash_find_and_delete(mcast_macs_rmts, mac_tnlkey);
+        }
+        free(mac_tnlkey);
+
         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) {
@@ -257,19 +393,8 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts,
                 shash_find_and_delete(ucast_macs_rmts, mac_ip_tnlkey);
             } 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);
-                }
+                vteprec_ucast_macs_remote_set_locator(new_umr, pl);
             }
             free(mac_ip_tnlkey);
         }
@@ -281,14 +406,27 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts,
     }
     struct ls_hash_node *iter, *next;
     HMAP_FOR_EACH_SAFE (iter, next, hmap_node, &ls_map) {
+        vtep_update_mmr(vtep_idl_txn, &iter->locators_list,
+                        iter->vtep_ls, iter->mmr_ext);
+        LIST_FOR_EACH_POP(ploc_entry, locators_node,
+                          &iter->locators_list) {
+            free(ploc_entry);
+        }
         hmap_remove(&ls_map, &iter->hmap_node);
         shash_destroy(&iter->added_macs);
+        shash_destroy(&iter->physical_locators);
         free(iter);
     }
     hmap_destroy(&ls_map);
+    /* Clean the stale MMRs. */
+    struct mmr_hash_node_data *mmr_ext;
+    SHASH_FOR_EACH (node, mcast_macs_rmts) {
+        mmr_ext = node->data;
+        vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
+    }
 }
 
-/* Resets all logical switches' 'tunnel_key' to NULL */
+/* Resets all logical switches' 'tunnel_key' to NULL. */
 static bool
 vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
 {
@@ -305,17 +443,23 @@ vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
     return done;
 }
 
-/* Removes all entries in the 'Ucast_Macs_Remote' table in vtep database.
+/* Removes all entries in the 'Ucast_Macs_Remote'
+ * and 'Mcast_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;
+    const struct vteprec_mcast_macs_remote *mmr;
 
     VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, vtep_idl) {
         vteprec_ucast_macs_remote_delete(umr);
         return false;
     }
+    VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, vtep_idl) {
+        vteprec_mcast_macs_remote_delete(mmr);
+        return false;
+    }
     return true;
 }
 
@@ -330,6 +474,7 @@ vtep_run(struct controller_vtep_ctx *ctx)
     struct sset vtep_pswitches = SSET_INITIALIZER(&vtep_pswitches);
     struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
     struct shash ucast_macs_rmts = SHASH_INITIALIZER(&ucast_macs_rmts);
+    struct shash mcast_macs_rmts = SHASH_INITIALIZER(&mcast_macs_rmts);
     struct shash physical_locators = SHASH_INITIALIZER(&physical_locators);
     struct shash vtep_pbs = SHASH_INITIALIZER(&vtep_pbs);
     struct shash non_vtep_pbs = SHASH_INITIALIZER(&non_vtep_pbs);
@@ -338,6 +483,13 @@ vtep_run(struct controller_vtep_ctx *ctx)
     const struct vteprec_ucast_macs_remote *umr;
     const struct vteprec_physical_locator *pl;
     const struct sbrec_port_binding *port_binding_rec;
+    const struct vteprec_mcast_macs_remote *mmr;
+    struct mmr_hash_node_data *mmr_ext;
+    const struct vteprec_physical_locator_set *locator_set;
+    struct vteprec_physical_locator **locators_list;
+    size_t n_locators;
+    size_t i;
+    struct shash_node *node;
 
     /* Collects 'Physical_Switch's. */
     VTEPREC_PHYSICAL_SWITCH_FOR_EACH (vtep_ps, ctx->vtep_idl) {
@@ -360,6 +512,29 @@ vtep_run(struct controller_vtep_ctx *ctx)
         shash_add(&ucast_macs_rmts, mac_ip_tnlkey, umr);
         free(mac_ip_tnlkey);
     }
+    /* Collects 'Mcast_Macs_Remote's. */
+    VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, ctx->vtep_idl) {
+        char *mac_tnlkey =
+            xasprintf("%s_%"PRId64, mmr->MAC,
+                      mmr->logical_switch && mmr->logical_switch->n_tunnel_key
+                          ? mmr->logical_switch->tunnel_key[0] : INT64_MAX);
+
+        mmr_ext = xmalloc(sizeof *mmr_ext);
+        shash_add(&mcast_macs_rmts, mac_tnlkey, mmr_ext);
+        mmr_ext->mmr = mmr;
+        locator_set = mmr_ext->mmr->locator_set;
+        n_locators = locator_set->n_locators;
+        locators_list = locator_set->locators;
+
+        shash_init(&mmr_ext->physical_locators);
+        for (i = 0; i < n_locators; i++) {
+            shash_add(&mmr_ext->physical_locators,
+                      locators_list[i]->dst_ip,
+                      locators_list[i]);
+        }
+
+        free(mac_tnlkey);
+    }
     /* Collects 'Physical_Locator's. */
     VTEPREC_PHYSICAL_LOCATOR_FOR_EACH (pl, ctx->vtep_idl) {
         shash_add(&physical_locators, pl->dst_ip, pl);
@@ -380,12 +555,19 @@ vtep_run(struct controller_vtep_ctx *ctx)
                               "tunnel keys and 'ucast_macs_remote's");
 
     vtep_lswitch_run(&vtep_pbs, &vtep_pswitches, &vtep_lswitches);
-    vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts, &physical_locators,
+    vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts,
+                  &mcast_macs_rmts, &physical_locators,
                   &vtep_lswitches, &non_vtep_pbs);
 
     sset_destroy(&vtep_pswitches);
     shash_destroy(&vtep_lswitches);
     shash_destroy(&ucast_macs_rmts);
+    SHASH_FOR_EACH (node, &mcast_macs_rmts) {
+        mmr_ext = node->data;
+        shash_destroy(&mmr_ext->physical_locators);
+        free(mmr_ext);
+    }
+    shash_destroy(&mcast_macs_rmts);
     shash_destroy(&physical_locators);
     shash_destroy(&vtep_pbs);
     shash_destroy(&non_vtep_pbs);
diff --git a/tests/ovn.at b/tests/ovn.at
index 2e5d2b7..0524c2c 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1172,10 +1172,8 @@ for s in 1 2 3; do
     done
 
     # Broadcast and multicast.
-    # xxx ovn-controller-vtep doesn't handle multicast traffic that is
-    # xxx sourced from the gateway properly.
-    #test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast             #2
-    #test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast             #2
+    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast             #2
+    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast             #2
 
     test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown           #3
 done
-- 
1.9.1




More information about the dev mailing list