Signed-off-by: Ilya Maximets <i.maxim...@ovn.org> Acked-by: Dumitru Ceara <dce...@redhat.com> Acked-by: Mark Michelson <mmich...@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 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev