[ovs-dev] [PATCH ovn] Improve debuggability of OVN to OpenFlow translations.

Numan Siddique numans at ovn.org
Mon Nov 4 11:49:05 UTC 2019


Thanks for the patch. It would be really helpful in debugging.

I applied this to master.

Thanks
Numan

On Sat, Nov 2, 2019 at 2:39 AM Mark Michelson <mmichels at redhat.com> wrote:
>
> Great addition, Dumitru!
>
> Acked-by: Mark Michelson <mmichels at redhat.com>
>
> On 11/1/19 8:05 AM, Dumitru Ceara wrote:
> > Until now, when translating SB database contents to OpenFlow flows,
> > ovn-controller stored (part of) the SB record UUID in the cookie field
> > of the OpenFlow entry only when translating logical flows.
> >
> > Extend this behavior to the following SB Database table records too:
> > - Port_Binding
> > - Mac_Binding
> > - Multicast_Group
> > - Chassis
> >
> > This makes debugging easier by allowing the user to trace back the
> > original SB entry that generated the OpenFlow entry. Also, the
> > "ovn-sbctl lflow-list" command now supports an additional "--vflows"
> > argument (virtual flows). When present this will instruct ovn-sbctl
> > to also pretty print the contents of the above mentioned tables for
> > the given datapath (or all datapaths if none is specified).
> >
> > Combined with the "--ovs" and "--stats" arguments it allows the
> > user to have a more complete view of how forwarding in the
> > logical network is translated to forwarding in OVS.
> >
> > A usage example:
> > $ ovn-sbctl --ovs --vflows lflow-list
> > [...]
> > Port Bindings:
> >    datapath="ls", logical_port=vm2, tunnel_key=4
> >      cookie=0xeaee10a0, duration=2122.949s, table=65, n_packets=0,
> >        n_bytes=0, priority=100,reg15=0x4,metadata=0x2 actions=output:2
> >    datapath="rtr", logical_port=rtr-ls, tunnel_key=1
> >      cookie=0x640b6337, duration=2122.945s, table=65, n_packets=0,
> >        n_bytes=0, priority=100,reg15=0x1,metadata=0x1
> >        actions=clone(ct_clear,set_field:0->reg11,set_field:0->reg12,
> >          set_field:0->reg13,set_field:0x4->reg11,set_field:0x3->reg12,
> >          set_field:0x2->metadata,set_field:0x3->reg14,set_field:0->reg10,
> >          set_field:0->reg15,set_field:0->reg0,set_field:0->reg1,
> >          set_field:0->reg2,set_field:0->reg3,set_field:0->reg4,
> >          set_field:0->reg5,set_field:0->reg6,set_field:0->reg7,
> >          set_field:0->reg8,set_field:0->reg9,set_field:0->in_port,
> >          resubmit(,8))
> >
> > MAC Bindings:
> >    datapath="rtr", logical_port=rtr-ls, ip=10::254, mac=00:00:00:00:00:01
> >      cookie=0x1c2b771d, duration=2122.946s, table=66, n_packets=0,
> >        n_bytes=0,priority=100,reg0=0x100000,reg1=0,reg2=0,reg3=0x254,
> >        reg15=0x1,metadata=0x1
> >        actions=set_field:00:00:00:00:00:01->eth_dst
> >      cookie=0x1c2b771d, duration=2122.945s, table=67, n_packets=0,
> >        n_bytes=0,priority=100,icmp6,reg0=0x100000,reg1=0,reg2=0,
> >        reg3=0x254,reg14=0x1,metadata=0x1,dl_src=00:00:00:00:00:01,icmp_code=0
> >        actions=load:0x1->NXM_NX_REG10[6]
> >
> > MC Groups:
> >    datapath="ls", name=_MC_flood, tunnel_key=32768, ports=(vm1, ls-rtr, vm2)
> >      cookie=0x4a196492, duration=2122.949s, table=33, n_packets=0,
> >        n_bytes=0, priority=100,reg15=0x8000,metadata=0x2
> >        actions=set_field:0x1->reg13,set_field:0x2->reg15,resubmit(,34),
> >        set_field:0xc->reg13,set_field:0x4->reg15,resubmit(,34),
> >        set_field:0x8000->reg15
> >      cookie=0x4a196492, duration=2122.947s, table=32, n_packets=0,
> >        n_bytes=0, priority=100,reg15=0x8000,metadata=0x2
> >        actions=set_field:0x3->reg15,resubmit(,34),set_field:0x8000->reg15,
> >        resubmit(,33)
> > [..]
> >
> > Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> > ---
> >   controller/lflow.c       |   6 +-
> >   controller/physical.c    |  58 +++++++++-----
> >   utilities/ovn-sbctl.8.in |   8 +-
> >   utilities/ovn-sbctl.c    | 196 +++++++++++++++++++++++++++++++++++++++++++----
> >   4 files changed, 230 insertions(+), 38 deletions(-)
> >
> > diff --git a/controller/lflow.c b/controller/lflow.c
> > index f34abce..36150bd 100644
> > --- a/controller/lflow.c
> > +++ b/controller/lflow.c
> > @@ -817,7 +817,8 @@ consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >       uint64_t stub[1024 / 8];
> >       struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
> >       put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts);
> > -    ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, 0, &get_arp_match,
> > +    ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100,
> > +                    b->header_.uuid.parts[0], &get_arp_match,
> >                       &ofpacts, &b->header_.uuid);
> >
> >       ofpbuf_clear(&ofpacts);
> > @@ -825,7 +826,8 @@ consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >       put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1,
> >                &ofpacts);
> >       match_set_dl_src(&lookup_arp_match, mac);
> > -    ofctrl_add_flow(flow_table, OFTABLE_MAC_LOOKUP, 100, 0, &lookup_arp_match,
> > +    ofctrl_add_flow(flow_table, OFTABLE_MAC_LOOKUP, 100,
> > +                    b->header_.uuid.parts[0], &lookup_arp_match,
> >                       &ofpacts, &b->header_.uuid);
> >
> >       ofpbuf_uninit(&ofpacts);
> > diff --git a/controller/physical.c b/controller/physical.c
> > index 6e606d3..500d419 100644
> > --- a/controller/physical.c
> > +++ b/controller/physical.c
> > @@ -298,7 +298,8 @@ put_remote_port_redirect_bridged(const struct
> >                                &value, NULL);
> >
> >           put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p);
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100,
> > +                        binding->header_.uuid.parts[0],
> >                           match, ofpacts_p, &binding->header_.uuid);
> >
> >   }
> > @@ -393,7 +394,8 @@ put_remote_port_redirect_overlay(const struct
> >           bundle->fields = NX_HASH_FIELDS_ETH_SRC;
> >           ofpact_finish_BUNDLE(ofpacts_p, &bundle);
> >       }
> > -    ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0,
> > +    ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100,
> > +                    binding->header_.uuid.parts[0],
> >                       match, ofpacts_p, &binding->header_.uuid);
> >   }
> >
> > @@ -406,6 +408,7 @@ struct remote_chassis_mac {
> >       struct hmap_node hmap_node;
> >       char *chassis_mac;
> >       char *chassis_id;
> > +    uint32_t chassis_sb_cookie;
> >   };
> >
> >   static void
> > @@ -446,6 +449,8 @@ populate_remote_chassis_macs(const struct sbrec_chassis *my_chassis,
> >                           hash_string(chassis_mac_bridge, 0));
> >               remote_chassis_mac->chassis_mac = xstrdup(chassis_mac_str);
> >               remote_chassis_mac->chassis_id = xstrdup(chassis->name);
> > +            remote_chassis_mac->chassis_sb_cookie =
> > +                chassis->header_.uuid.parts[0];
> >           }
> >           free(tokstr);
> >       }
> > @@ -496,7 +501,8 @@ put_chassis_mac_conj_id_flow(const struct sbrec_chassis_table *chassis_table,
> >           conj->id = CHASSIS_MAC_TO_ROUTER_MAC_CONJID;
> >           conj->n_clauses = 2;
> >           conj->clause = 0;
> > -        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 180, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 180,
> > +                        mac->chassis_sb_cookie,
> >                           &match, ofpacts_p, hc_uuid);
> >       }
> >
> > @@ -568,8 +574,9 @@ put_replace_chassis_mac_flows(const struct simap *ct_zones,
> >
> >           /* Resubmit to first logical ingress pipeline table. */
> >           put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
> > -        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG,
> > -                        180, 0, &match, ofpacts_p, hc_uuid);
> > +        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 180,
> > +                        rport_binding->header_.uuid.parts[0],
> > +                        &match, ofpacts_p, hc_uuid);
> >
> >           /* Provide second search criteria, i.e localnet port's
> >            * vlan ID for conjunction flow */
> > @@ -587,8 +594,9 @@ put_replace_chassis_mac_flows(const struct simap *ct_zones,
> >           conj->id = CHASSIS_MAC_TO_ROUTER_MAC_CONJID;
> >           conj->n_clauses = 2;
> >           conj->clause = 1;
> > -        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 180, 0, &match,
> > -                        ofpacts_p, hc_uuid);
> > +        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 180,
> > +                        rport_binding->header_.uuid.parts[0],
> > +                        &match, ofpacts_p, hc_uuid);
> >       }
> >   }
> >
> > @@ -687,7 +695,8 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
> >
> >           ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
> >
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 150, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 150,
> > +                        localnet_port->header_.uuid.parts[0],
> >                           &match, ofpacts_p, &localnet_port->header_.uuid);
> >       }
> >   }
> > @@ -902,7 +911,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >           ofpacts_p->header = clone;
> >           ofpact_finish_CLONE(ofpacts_p, &clone);
> >
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100,
> > +                        binding->header_.uuid.parts[0],
> >                           &match, ofpacts_p, &binding->header_.uuid);
> >           return;
> >       }
> > @@ -971,7 +981,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >               put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p);
> >           }
> >
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100,
> > +                        binding->header_.uuid.parts[0],
> >                           &match, ofpacts_p, &binding->header_.uuid);
> >
> >           goto out;
> > @@ -1124,8 +1135,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >           /* Resubmit to first logical ingress pipeline table. */
> >           put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
> >           ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG,
> > -                        tag ? 150 : 100, 0, &match, ofpacts_p,
> > -                        &binding->header_.uuid);
> > +                        tag ? 150 : 100, binding->header_.uuid.parts[0],
> > +                        &match, ofpacts_p, &binding->header_.uuid);
> >
> >           if (!tag && (!strcmp(binding->type, "localnet")
> >                        || !strcmp(binding->type, "l2gateway"))) {
> > @@ -1135,7 +1146,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >                * action. */
> >               ofpbuf_pull(ofpacts_p, ofpacts_orig_size);
> >               match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI));
> > -            ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p,
> > +            ofctrl_add_flow(flow_table, 0, 100,
> > +                            binding->header_.uuid.parts[0], &match, ofpacts_p,
> >                               &binding->header_.uuid);
> >           }
> >
> > @@ -1168,7 +1180,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >                * switch will also contain the tag. */
> >               ofpact_put_STRIP_VLAN(ofpacts_p);
> >           }
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100,
> > +                        binding->header_.uuid.parts[0],
> >                           &match, ofpacts_p, &binding->header_.uuid);
> >
> >           if (!strcmp(binding->type, "localnet")) {
> > @@ -1199,7 +1212,8 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >
> >           /* Resubmit to table 33. */
> >           put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p);
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100,
> > +                        binding->header_.uuid.parts[0],
> >                           &match, ofpacts_p, &binding->header_.uuid);
> >       } else {
> >
> > @@ -1322,7 +1336,8 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
> >            * group as the logical output port. */
> >           put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts);
> >
> > -        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0,
> > +        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100,
> > +                        mc->header_.uuid.parts[0],
> >                           &match, &ofpacts, &mc->header_.uuid);
> >       }
> >
> > @@ -1360,7 +1375,8 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
> >               if (local_ports) {
> >                   put_resubmit(OFTABLE_LOCAL_OUTPUT, &remote_ofpacts);
> >               }
> > -            ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0,
> > +            ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100,
> > +                            mc->header_.uuid.parts[0],
> >                               &match, &remote_ofpacts, &mc->header_.uuid);
> >           }
> >       }
> > @@ -1672,8 +1688,9 @@ physical_run(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >               put_load(1, MFF_LOG_FLAGS, MLF_RCV_FROM_VXLAN_BIT, 1, &ofpacts);
> >               put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts);
> >
> > -            ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, &match,
> > -                            &ofpacts, hc_uuid);
> > +            ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100,
> > +                            binding->header_.uuid.parts[0],
> > +                            &match, &ofpacts, hc_uuid);
> >           }
> >       }
> >
> > @@ -1730,7 +1747,8 @@ physical_run(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >           if (pb && !strcmp(pb->type, "localport")) {
> >               match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, pb->tunnel_key);
> >               match_set_metadata(&match, htonll(pb->datapath->tunnel_key));
> > -            ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0,
> > +            ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150,
> > +                            pb->header_.uuid.parts[0],
> >                               &match, &ofpacts, hc_uuid);
> >           }
> >       }
> > diff --git a/utilities/ovn-sbctl.8.in b/utilities/ovn-sbctl.8.in
> > index 644f944..d9fc3a5 100644
> > --- a/utilities/ovn-sbctl.8.in
> > +++ b/utilities/ovn-sbctl.8.in
> > @@ -167,7 +167,7 @@ to unbind logical port that is not bound has no effect.
> >   .
> >   .SS "Logical Flow Commands"
> >   .
> > -.IP "[\fB\-\-uuid\fR] [\fB\-\-ovs\fR[\fB=\fIremote\fR]] [\fB\-\-stats\fR] \fBlflow\-list\fR [\fIlogical-datapath\fR] [\fIlflow\fR...]"
> > +.IP "[\fB\-\-uuid\fR] [\fB\-\-ovs\fR[\fB=\fIremote\fR]] [\fB\-\-stats\fR] [\fB\-\-vflows\fR] \fBlflow\-list\fR [\fIlogical-datapath\fR] [\fIlflow\fR...]"
> >   List logical flows.  If \fIlogical-datapath\fR is specified, only list
> >   flows for that logical datapath.  The \fIlogical-datapath\fR may be
> >   given as a UUID or as a datapath name (reporting an error if multiple
> > @@ -197,6 +197,12 @@ for more information about the OpenFlow flow output.
> >   By default, OpenFlow flow output includes only match and actions.  Add
> >   \fB\-\-stats\fR to include all OpenFlow information, such as packet
> >   and byte counters, duration, and timeouts.
> > +.IP
> > +If \fB\-\-vflows\fR is included, other southbound database records directly
> > +used for generating OpenFlow flows are also listed. This includes:
> > +\fIport-bindings\fR, \fImac-bindings\fR, \fImulticast-groups\fR,
> > +\fIchassis\fR.  The \fB\-\-ovs\fR and \fB\-\-stats\fR can also be used in
> > +conjunction with \fB\-\-vflows\fR.
> >   .
> >   .IP "[\fB\-\-uuid\fR] \fBdump\-flows\fR [\fIlogical-datapath\fR]"
> >   Alias for \fBlflow\-list\fB.
> > diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
> > index ffcaee2..4facdb1 100644
> > --- a/utilities/ovn-sbctl.c
> > +++ b/utilities/ovn-sbctl.c
> > @@ -516,7 +516,9 @@ pre_get_info(struct ctl_context *ctx)
> >       ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_ip);
> >
> >       ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_logical_port);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_tunnel_key);
> >       ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
> > +    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_pipeline);
> > @@ -530,6 +532,16 @@ pre_get_info(struct ctl_context *ctx)
> >
> >       ovsdb_idl_add_column(ctx->idl, &sbrec_ip_multicast_col_datapath);
> >       ovsdb_idl_add_column(ctx->idl, &sbrec_ip_multicast_col_seq_no);
> > +
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_multicast_group_col_name);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_multicast_group_col_datapath);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_multicast_group_col_tunnel_key);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_multicast_group_col_ports);
> > +
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_mac_binding_col_datapath);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_mac_binding_col_logical_port);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_mac_binding_col_ip);
> > +    ovsdb_idl_add_column(ctx->idl, &sbrec_mac_binding_col_mac);
> >   }
> >
> >   static struct cmd_show_table cmd_show_tables[] = {
> > @@ -844,6 +856,161 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats)
> >   }
> >
> >   static void
> > +print_datapath_name(const struct sbrec_datapath_binding *dp)
> > +{
> > +    const struct smap *ids = &dp->external_ids;
> > +    const char *name = smap_get(ids, "name");
> > +    const char *name2 = smap_get(ids, "name2");
> > +    if (name && name2) {
> > +        printf("\"%s\" aka \"%s\"", name, name2);
> > +    } else if (name || name2) {
> > +        printf("\"%s\"", name ? name : name2);
> > +    }
> > +}
> > +
> > +static void
> > +print_vflow_datapath_name(const struct sbrec_datapath_binding *dp,
> > +                          bool do_print)
> > +{
> > +    if (!do_print) {
> > +        return;
> > +    }
> > +    printf("datapath=");
> > +    print_datapath_name(dp);
> > +    printf(", ");
> > +}
> > +
> > +static void
> > +print_uuid_part(const struct uuid *uuid, bool do_print)
> > +{
> > +    if (!do_print) {
> > +        return;
> > +    }
> > +    printf("uuid=0x%08"PRIx32", ", uuid->parts[0]);
> > +}
> > +
> > +static void
> > +cmd_lflow_list_port_bindings(struct ctl_context *ctx, struct vconn *vconn,
> > +                             const struct sbrec_datapath_binding *datapath,
> > +                             bool stats, bool print_uuid)
> > +{
> > +    const struct sbrec_port_binding *pb;
> > +    const struct sbrec_port_binding *pb_prev = NULL;
> > +    SBREC_PORT_BINDING_FOR_EACH (pb, ctx->idl) {
> > +
> > +        if (datapath && pb->datapath != datapath) {
> > +            continue;
> > +        }
> > +
> > +        if (!pb_prev) {
> > +            printf("\nPort Bindings:\n");
> > +        }
> > +
> > +        printf("  ");
> > +        print_uuid_part(&pb->header_.uuid, print_uuid);
> > +        print_vflow_datapath_name(pb->datapath, !datapath);
> > +        printf("logical_port=%s, tunnel_key=%-5"PRId64"\n",
> > +               pb->logical_port, pb->tunnel_key);
> > +        if (vconn) {
> > +            sbctl_dump_openflow(vconn, &pb->header_.uuid, stats);
> > +        }
> > +
> > +        pb_prev = pb;
> > +    }
> > +}
> > +
> > +static void
> > +cmd_lflow_list_mac_bindings(struct ctl_context *ctx, struct vconn *vconn,
> > +                            const struct sbrec_datapath_binding *datapath,
> > +                            bool stats, bool print_uuid)
> > +{
> > +    const struct sbrec_mac_binding *mb;
> > +    const struct sbrec_mac_binding *mb_prev = NULL;
> > +    SBREC_MAC_BINDING_FOR_EACH (mb, ctx->idl) {
> > +        if (datapath && mb->datapath != datapath) {
> > +            continue;
> > +        }
> > +
> > +        if (!mb_prev) {
> > +            printf("\nMAC Bindings:\n");
> > +        }
> > +
> > +        printf("  ");
> > +        print_uuid_part(&mb->header_.uuid, print_uuid);
> > +        print_vflow_datapath_name(mb->datapath, !datapath);
> > +
> > +        printf("logical_port=%s, ip=%s, mac=%s\n",
> > +               mb->logical_port, mb->ip, mb->mac);
> > +        if (vconn) {
> > +            sbctl_dump_openflow(vconn, &mb->header_.uuid, stats);
> > +        }
> > +
> > +        mb_prev = mb;
> > +    }
> > +}
> > +
> > +static void
> > +cmd_lflow_list_mc_groups(struct ctl_context *ctx, struct vconn *vconn,
> > +                         const struct sbrec_datapath_binding *datapath,
> > +                         bool stats, bool print_uuid)
> > +{
> > +    const struct sbrec_multicast_group *mc;
> > +    const struct sbrec_multicast_group *mc_prev = NULL;
> > +    SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->idl) {
> > +        if (datapath && mc->datapath != datapath) {
> > +            continue;
> > +        }
> > +
> > +        if (!mc_prev) {
> > +            printf("\nMC Groups:\n");
> > +        }
> > +
> > +        printf("  ");
> > +        print_uuid_part(&mc->header_.uuid, print_uuid);
> > +        print_vflow_datapath_name(mc->datapath, !datapath);
> > +
> > +        printf("name=%s, tunnel_key=%-5"PRId64", ports=(",
> > +               mc->name, mc->tunnel_key);
> > +        for (size_t i = 0; i < mc->n_ports; i++) {
> > +            printf("%s", mc->ports[i]->logical_port);
> > +            if (i != mc->n_ports - 1) {
> > +                printf(", ");
> > +            }
> > +        }
> > +        printf(")\n");
> > +
> > +        if (vconn) {
> > +            sbctl_dump_openflow(vconn, &mc->header_.uuid, stats);
> > +        }
> > +
> > +        mc_prev = mc;
> > +    }
> > +}
> > +
> > +static void
> > +cmd_lflow_list_chassis(struct ctl_context *ctx, struct vconn *vconn,
> > +                       bool stats, bool print_uuid)
> > +{
> > +    const struct sbrec_chassis *chassis;
> > +    const struct sbrec_chassis *chassis_prev = NULL;
> > +    SBREC_CHASSIS_FOR_EACH (chassis, ctx->idl) {
> > +        if (!chassis_prev) {
> > +            printf("\nChassis:\n");
> > +        }
> > +
> > +        printf("  ");
> > +        print_uuid_part(&chassis->header_.uuid, print_uuid);
> > +
> > +        printf("name=%s\n", chassis->name);
> > +        if (vconn) {
> > +            sbctl_dump_openflow(vconn, &chassis->header_.uuid, stats);
> > +        }
> > +
> > +        chassis_prev = chassis;
> > +    }
> > +}
> > +
> > +static void
> >   cmd_lflow_list(struct ctl_context *ctx)
> >   {
> >       const struct sbrec_datapath_binding *datapath = NULL;
> > @@ -925,16 +1092,8 @@ cmd_lflow_list(struct ctl_context *ctx)
> >           if (!prev
> >               || prev->logical_datapath != lflow->logical_datapath
> >               || strcmp(prev->pipeline, lflow->pipeline)) {
> > -            printf("Datapath:");
> > -
> > -            const struct smap *ids = &lflow->logical_datapath->external_ids;
> > -            const char *name = smap_get(ids, "name");
> > -            const char *name2 = smap_get(ids, "name2");
> > -            if (name && name2) {
> > -                printf(" \"%s\" aka \"%s\"", name, name2);
> > -            } else if (name || name2) {
> > -                printf(" \"%s\"", name ? name : name2);
> > -            }
> > +            printf("Datapath: ");
> > +            print_datapath_name(lflow->logical_datapath);
> >               printf(" ("UUID_FMT")  Pipeline: %s\n",
> >                      UUID_ARGS(&lflow->logical_datapath->header_.uuid),
> >                      lflow->pipeline);
> > @@ -942,9 +1101,7 @@ cmd_lflow_list(struct ctl_context *ctx)
> >
> >           /* Print the flow. */
> >           printf("  ");
> > -        if (print_uuid) {
> > -            printf("uuid=0x%08"PRIx32", ", lflow->header_.uuid.parts[0]);
> > -        }
> > +        print_uuid_part(&lflow->header_.uuid, print_uuid);
> >           printf("table=%-2"PRId64"(%-19s), priority=%-5"PRId64
> >                  ", match=(%s), action=(%s)\n",
> >                  lflow->table_id,
> > @@ -956,6 +1113,14 @@ cmd_lflow_list(struct ctl_context *ctx)
> >           prev = lflow;
> >       }
> >
> > +    bool vflows = shash_find(&ctx->options, "--vflows") != NULL;
> > +    if (vflows) {
> > +        cmd_lflow_list_port_bindings(ctx, vconn, datapath, stats, print_uuid);
> > +        cmd_lflow_list_mac_bindings(ctx, vconn, datapath, stats, print_uuid);
> > +        cmd_lflow_list_mc_groups(ctx, vconn, datapath, stats, print_uuid);
> > +        cmd_lflow_list_chassis(ctx, vconn, stats, print_uuid);
> > +    }
> > +
> >       vconn_close(vconn);
> >       free(lflows);
> >   }
> > @@ -1509,10 +1674,11 @@ static const struct ctl_command_syntax sbctl_commands[] = {
> >       /* Logical flow commands */
> >       {"lflow-list", 0, INT_MAX, "[DATAPATH] [LFLOW...]",
> >        pre_get_info, cmd_lflow_list, NULL,
> > -     "--uuid,--ovs?,--stats", RO},
> > +     "--uuid,--ovs?,--stats,--vflows?", RO},
> >       {"dump-flows", 0, INT_MAX, "[DATAPATH] [LFLOW...]",
> >        pre_get_info, cmd_lflow_list, NULL,
> > -     "--uuid,--ovs?,--stats", RO}, /* Friendly alias for lflow-list */
> > +     "--uuid,--ovs?,--stats,--vflows?",
> > +     RO}, /* Friendly alias for lflow-list */
> >
> >       /* IP multicast commands. */
> >       {"ip-multicast-flush", 0, 1, "SWITCH",
> >
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list