[ovs-dev] [PATCH ovn v3 4/6] utilities: Add support for Logical Datapath Groups.

Ilya Maximets i.maximets at ovn.org
Fri Dec 4 17:54:12 UTC 2020


Signed-off-by: Ilya Maximets <i.maximets at ovn.org>
Acked-by: Dumitru Ceara <dceara at redhat.com>
Acked-by: Mark Michelson <mmichels at redhat.com>
---
 utilities/ovn-detrace.in |   8 ++-
 utilities/ovn-sbctl.c    | 108 ++++++++++++++++++++++++++++-----------
 utilities/ovn-trace.c    |  40 +++++++++++----
 3 files changed, 115 insertions(+), 41 deletions(-)

diff --git a/utilities/ovn-detrace.in b/utilities/ovn-detrace.in
index af42b5fc4..1e4f76dd7 100755
--- a/utilities/ovn-detrace.in
+++ b/utilities/ovn-detrace.in
@@ -270,8 +270,12 @@ class LogicalFlowHandler(CookieHandlerByUUUID):
         ]
 
     def print_record(self, lflow):
-        print_p('Logical datapath: %s [%s]' %
-                    (datapath_str(lflow.logical_datapath), lflow.pipeline))
+        print_p('Logical datapaths:')
+        datapaths = lflow.logical_datapath
+        if lflow.logical_dp_group:
+            datapaths.extend(lflow.logical_dp_group[0].datapaths)
+        for datapath in datapaths:
+            print_p('    %s [%s]' % (datapath_str(datapath), lflow.pipeline))
         print_p('Logical flow: table=%s (%s), priority=%s, '
                 'match=(%s), actions=(%s)' %
                     (lflow.table_id, lflow.external_ids.get('stage-name'),
diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
index c21b1369a..0a1b9ffdc 100644
--- a/utilities/ovn-sbctl.c
+++ b/utilities/ovn-sbctl.c
@@ -528,6 +528,7 @@ pre_get_info(struct ctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_datapath);
 
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
+    ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_dp_group);
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_pipeline);
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_actions);
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_priority);
@@ -535,6 +536,8 @@ pre_get_info(struct ctl_context *ctx)
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_match);
     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_external_ids);
 
+    ovsdb_idl_add_column(ctx->idl, &sbrec_logical_dp_group_col_datapaths);
+
     ovsdb_idl_add_column(ctx->idl, &sbrec_datapath_binding_col_external_ids);
 
     ovsdb_idl_add_column(ctx->idl, &sbrec_ip_multicast_col_datapath);
@@ -717,16 +720,22 @@ pipeline_encode(const char *pl)
     OVS_NOT_REACHED();
 }
 
+struct sbctl_lflow {
+    const struct sbrec_logical_flow *lflow;
+    const struct sbrec_datapath_binding *dp;
+};
+
 static int
-lflow_cmp(const void *a_, const void *b_)
+sbctl_lflow_cmp(const void *a_, const void *b_)
 {
-    const struct sbrec_logical_flow *const *ap = a_;
-    const struct sbrec_logical_flow *const *bp = b_;
-    const struct sbrec_logical_flow *a = *ap;
-    const struct sbrec_logical_flow *b = *bp;
+    const struct sbctl_lflow *a_ctl_lflow = a_;
+    const struct sbctl_lflow *b_ctl_lflow = b_;
+
+    const struct sbrec_logical_flow *a = a_ctl_lflow->lflow;
+    const struct sbrec_logical_flow *b = b_ctl_lflow->lflow;
 
-    const struct sbrec_datapath_binding *adb = a->logical_datapath;
-    const struct sbrec_datapath_binding *bdb = b->logical_datapath;
+    const struct sbrec_datapath_binding *adb = a_ctl_lflow->dp;
+    const struct sbrec_datapath_binding *bdb = b_ctl_lflow->dp;
     const char *a_name = smap_get_def(&adb->external_ids, "name", "");
     const char *b_name = smap_get_def(&bdb->external_ids, "name", "");
     int cmp = strcmp(a_name, b_name);
@@ -1071,6 +1080,35 @@ cmd_lflow_list_load_balancers(struct ctl_context *ctx, struct vconn *vconn,
     }
 }
 
+static bool
+datapath_group_contains_datapath(const struct sbrec_logical_dp_group *g,
+                                 const struct sbrec_datapath_binding *dp)
+{
+    if (!g || !dp) {
+        return false;
+    }
+    for (size_t i = 0; i < g->n_datapaths; i++) {
+        if (g->datapaths[i] == dp) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void
+sbctl_lflow_add(struct sbctl_lflow **lflows,
+                size_t *n_flows, size_t *n_capacity,
+                const struct sbrec_logical_flow *lflow,
+                const struct sbrec_datapath_binding *dp)
+{
+    if (*n_flows == *n_capacity) {
+        *lflows = x2nrealloc(*lflows, n_capacity, sizeof **lflows);
+    }
+    (*lflows)[*n_flows].lflow = lflow;
+    (*lflows)[*n_flows].dp = dp;
+    (*n_flows)++;
+}
+
 static void
 cmd_lflow_list(struct ctl_context *ctx)
 {
@@ -1102,31 +1140,42 @@ cmd_lflow_list(struct ctl_context *ctx)
     struct vconn *vconn = sbctl_open_vconn(&ctx->options);
     bool stats = shash_find(&ctx->options, "--stats") != NULL;
 
-    const struct sbrec_logical_flow **lflows = NULL;
+    struct sbctl_lflow *lflows = NULL;
     size_t n_flows = 0;
     size_t n_capacity = 0;
     const struct sbrec_logical_flow *lflow;
+    const struct sbrec_logical_dp_group *dp_group;
     SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->idl) {
-        if (datapath && lflow->logical_datapath != datapath) {
+        if (datapath
+            && lflow->logical_datapath != datapath
+            && !datapath_group_contains_datapath(lflow->logical_dp_group,
+                                                 datapath)) {
             continue;
         }
-
-        if (n_flows == n_capacity) {
-            lflows = x2nrealloc(lflows, &n_capacity, sizeof *lflows);
+        if (datapath) {
+            sbctl_lflow_add(&lflows, &n_flows, &n_capacity, lflow, datapath);
+            continue;
+        }
+        if (lflow->logical_datapath) {
+            sbctl_lflow_add(&lflows, &n_flows, &n_capacity,
+                            lflow, lflow->logical_datapath);
+        }
+        dp_group = lflow->logical_dp_group;
+        for (size_t i = 0; dp_group && i < dp_group->n_datapaths; i++) {
+            sbctl_lflow_add(&lflows, &n_flows, &n_capacity,
+                            lflow, dp_group->datapaths[i]);
         }
-        lflows[n_flows] = lflow;
-        n_flows++;
     }
 
     if (n_flows) {
-        qsort(lflows, n_flows, sizeof *lflows, lflow_cmp);
+        qsort(lflows, n_flows, sizeof *lflows, sbctl_lflow_cmp);
     }
 
     bool print_uuid = shash_find(&ctx->options, "--uuid") != NULL;
 
-    const struct sbrec_logical_flow *prev = NULL;
+    const struct sbctl_lflow *curr, *prev = NULL;
     for (size_t i = 0; i < n_flows; i++) {
-        lflow = lflows[i];
+        curr = &lflows[i];
 
         /* Figure out whether to print this particular flow.  By default, we
          * print all flows, but if any UUIDs were listed on the command line
@@ -1135,7 +1184,7 @@ cmd_lflow_list(struct ctl_context *ctx)
         if (ctx->argc > 1) {
             include = false;
             for (size_t j = 1; j < ctx->argc; j++) {
-                if (is_partial_uuid_match(&lflow->header_.uuid,
+                if (is_partial_uuid_match(&curr->lflow->header_.uuid,
                                           ctx->argv[j])) {
                     include = true;
                     break;
@@ -1151,27 +1200,28 @@ cmd_lflow_list(struct ctl_context *ctx)
         /* Print a header line for this datapath or pipeline, if we haven't
          * already done so. */
         if (!prev
-            || prev->logical_datapath != lflow->logical_datapath
-            || strcmp(prev->pipeline, lflow->pipeline)) {
+            || prev->dp != curr->dp
+            || strcmp(prev->lflow->pipeline, curr->lflow->pipeline)) {
             printf("Datapath: ");
-            print_datapath_name(lflow->logical_datapath);
+            print_datapath_name(curr->dp);
             printf(" ("UUID_FMT")  Pipeline: %s\n",
-                   UUID_ARGS(&lflow->logical_datapath->header_.uuid),
-                   lflow->pipeline);
+                   UUID_ARGS(&curr->dp->header_.uuid),
+                   curr->lflow->pipeline);
         }
 
         /* Print the flow. */
         printf("  ");
-        print_uuid_part(&lflow->header_.uuid, print_uuid);
+        print_uuid_part(&curr->lflow->header_.uuid, print_uuid);
         printf("table=%-2"PRId64"(%-19s), priority=%-5"PRId64
                ", match=(%s), action=(%s)\n",
-               lflow->table_id,
-               smap_get_def(&lflow->external_ids, "stage-name", ""),
-               lflow->priority, lflow->match, lflow->actions);
+               curr->lflow->table_id,
+               smap_get_def(&curr->lflow->external_ids, "stage-name", ""),
+               curr->lflow->priority, curr->lflow->match,
+               curr->lflow->actions);
         if (vconn) {
-            sbctl_dump_openflow(vconn, &lflow->header_.uuid, stats);
+            sbctl_dump_openflow(vconn, &curr->lflow->header_.uuid, stats);
         }
-        prev = lflow;
+        prev = curr;
     }
 
     bool vflows = shash_find(&ctx->options, "--vflows") != NULL;
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
index 8eb7263b3..6fad36512 100644
--- a/utilities/ovn-trace.c
+++ b/utilities/ovn-trace.c
@@ -874,18 +874,14 @@ ovntrace_make_names_friendly(const char *in)
 }
 
 static void
-read_flows(void)
+parse_lflow_for_datapath(const struct sbrec_logical_flow *sblf,
+                        const struct sbrec_datapath_binding *sbdb)
 {
-    ovn_init_symtab(&symtab);
-
-    const struct sbrec_logical_flow *sblf;
-    SBREC_LOGICAL_FLOW_FOR_EACH (sblf, ovnsb_idl) {
-        const struct sbrec_datapath_binding *sbdb = sblf->logical_datapath;
         struct ovntrace_datapath *dp
             = ovntrace_datapath_find_by_sb_uuid(&sbdb->header_.uuid);
         if (!dp) {
             VLOG_WARN("logical flow missing datapath");
-            continue;
+            return;
         }
 
         char *error;
@@ -897,7 +893,7 @@ read_flows(void)
             VLOG_WARN("%s: parsing expression failed (%s)",
                       sblf->match, error);
             free(error);
-            continue;
+            return;
         }
 
         struct ovnact_parse_params pp = {
@@ -919,7 +915,7 @@ read_flows(void)
             VLOG_WARN("%s: parsing actions failed (%s)", sblf->actions, error);
             free(error);
             expr_destroy(match);
-            continue;
+            return;
         }
 
         match = expr_combine(EXPR_T_AND, match, prereqs);
@@ -930,7 +926,7 @@ read_flows(void)
             expr_destroy(match);
             ovnacts_free(ovnacts.data, ovnacts.size);
             ofpbuf_uninit(&ovnacts);
-            continue;
+            return;
         }
         if (match) {
             match = expr_simplify(match);
@@ -960,6 +956,30 @@ read_flows(void)
                                    sizeof *dp->flows);
         }
         dp->flows[dp->n_flows++] = flow;
+}
+
+static void
+read_flows(void)
+{
+    ovn_init_symtab(&symtab);
+
+    const struct sbrec_logical_flow *sblf;
+    SBREC_LOGICAL_FLOW_FOR_EACH (sblf, ovnsb_idl) {
+        bool missing_datapath = true;
+
+        if (sblf->logical_datapath) {
+            parse_lflow_for_datapath(sblf, sblf->logical_datapath);
+            missing_datapath = false;
+        }
+
+        const struct sbrec_logical_dp_group *g = sblf->logical_dp_group;
+        for (size_t i = 0; g && i < g->n_datapaths; i++) {
+            parse_lflow_for_datapath(sblf, g->datapaths[i]);
+            missing_datapath = false;
+        }
+        if (missing_datapath) {
+            VLOG_WARN("logical flow missing datapath");
+        }
     }
 
     const struct ovntrace_datapath *dp;
-- 
2.25.4



More information about the dev mailing list