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

Dumitru Ceara dceara at redhat.com
Mon Nov 4 11:54:20 UTC 2019


On Mon, Nov 4, 2019 at 12:49 PM Numan Siddique <numans at ovn.org> wrote:
>
> Thanks for the patch. It would be really helpful in debugging.
>
> I applied this to master.
>
> Thanks
> Numan

Thanks for the reviews and for merging the patch.

Regards,
Dumitru

>
> 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