On 6/18/25 12:08 PM, Mairtin O'Loingsigh via dev wrote:
> Add support for using ovn-nbctl to list ports in a port group
> 
> pg-get-ports: Get logical switch ports of a port group
> 
> Reported-at: https://issues.redhat.com/browse/FDP-1463
> Signed-off-by: Mairtin O'Loingsigh <moloi...@redhat.com>
> ---

Hi Mairtin,

Thanks for the patch!  To me it looks correct from a functional
perspective.  I left a bunch of minor comments below though.

>  tests/ovn-nbctl.at    | 10 +++++++-
>  utilities/ovn-nbctl.c | 56 +++++++++++++++++++++++++++++++++++++++++++

Nit: we probably need to add a NEWS entry mentioning this new command.

Please also update the ovn-nbctl man page (ovn-nbctl.8.xml) and document
this new get command.

>  2 files changed, 65 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index 447a0666f..b2f0b7df8 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -2798,15 +2798,23 @@ pg1
>  AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1], 
> [0], [dnl
>  $SW1P1
>  ])
> +AT_CHECK([ovn-nbctl pg-get-ports pg1],[0], [dnl
> +sw1-p1
> +])
>  
>  AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
>  AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1], 
> [0], [dnl
>  $SW1P2
>  ])
> +AT_CHECK([ovn-nbctl pg-get-ports pg1],[0], [dnl
> +sw1-p2
> +])
>  
>  AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>  AT_CHECK([ovn-nbctl list port_group], [0], [])
> -])
> +AT_CHECK([ovn-nbctl pg-get-ports pg1], [1], [],
> +  [ovn-nbctl: pg1: port group name not found
> +])])

Thanks for adding tests!  But, for completeness, can we also add a test
that configures port groups with more than one port in them?  That'd
also test the sorting part.

>  dnl ---------------------------------------------------------------------
>  
>  OVN_NBCTL_TEST([ovn_nbctl_fwd_groups], [fwd groups], [
> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> index 33e789523..b3c9b89fb 100644
> --- a/utilities/ovn-nbctl.c
> +++ b/utilities/ovn-nbctl.c
> @@ -483,6 +483,7 @@ Port group commands:\n\
>    pg-add PG [PORTS]           Create port group PG with optional PORTS\n\
>    pg-set-ports PG PORTS       Set PORTS on port group PG\n\
>    pg-del PG                   Delete port group PG\n\
> +  pg-get-ports PG             List port group PG\n\

Maybe "Get PORTS on port group PG" is slightly more accurate?

>  HA chassis group commands:\n\
>    ha-chassis-group-add GRP    Create an HA chassis group GRP\n\
>    ha-chassis-group-del GRP    Delete the HA chassis group GRP\n\
> @@ -7489,6 +7490,59 @@ cmd_pg_del(struct ctl_context *ctx)
>      nbrec_port_group_delete(pg);
>  }
>  
> +static void
> +cmd_pre_pg_get_ports(struct ctl_context *ctx)

Nit: This is identical to cmd_pre_pg_set_ports() and given that I think
we always want to "get" back exactly the same information we can "set"
it might make sense to just rename it to cmd_pre_pg_set_get_ports() and
avoid duplicating the code.

> +{
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_port_group_col_ports);
> +}
> +
> +static int
> +port_name_cmp(const void *s1_, const void *s2_)
> +{
> +    const char *s1 = *(char **) s1_, *s2 = *(char **) s2_;

I think I'd rewrite this as:

    const char *s1 = *(const char **) s1_;
    const char *s2 = *(const char **) s2_;

> +    return strcmp(s1, s2);
> +}
> +
> +static void
> +cmd_pg_get_ports(struct ctl_context *ctx)
> +{
> +    const struct nbrec_port_group *pg;
> +    struct nbrec_logical_switch_port **ports;
> +    size_t i;
> +    char **port_names;
> +    char *error;
> +
> +    error = pg_by_name_or_uuid(ctx, ctx->argv[1], true, &pg);

In this case I think we'd prefer to define the variable here directly
(as close to where it's used), i.e.:

char *error = pg_by_name_or_uuid(...);

> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +
> +    ports = pg->ports;
> +    if (pg->n_ports == 0) {
> +        return;
> +    }
> +
> +    port_names = xmalloc(sizeof(char *) * pg->n_ports);

Per our coding guidelines this should be "sizeof *port_names":
https://github.com/ovn-org/ovn/blob/main/Documentation/internals/contributing/coding-style.rst#expressions

> +    for (i = 0; i < pg->n_ports; i++) {
> +        port_names[i] = ports[i]->name;

I'd just use pg->ports here instead of having the new local 'ports'.

> +    }
> +
> +    qsort(port_names, pg->n_ports, sizeof(char *), port_name_cmp);

Same here, "sizeof *port_names".

> +    ds_put_format(&ctx->output, "%s", port_names[0]);
> +    for (i = 1; i < pg->n_ports; i++) {
> +        ds_put_format(&ctx->output, " %s", port_names[i]);
> +    }
> +

'i' is always > 0 here, isn't it?

Which means we can just always limit the scope of the 'i' variable to
the loop it's used in.  That is we can do this in both loops above:

for (size_t i = ...)


> +    if (i > 0) {
> +        ds_put_cstr(&ctx->output, "\n");
> +    }
> +
> +    free(port_names);
> +}
> +
>  static const struct nbrec_ha_chassis_group*
>  ha_chassis_group_by_name_or_uuid(struct ctl_context *ctx, const char *id,
>                                   bool must_exist)
> @@ -8420,6 +8474,8 @@ static const struct ctl_command_syntax nbctl_commands[] 
> = {
>      {"pg-set-ports", 2, INT_MAX, "", cmd_pre_pg_set_ports, cmd_pg_set_ports,
>       NULL, "", RW },
>      {"pg-del", 1, 1, "", cmd_pre_pg_del, cmd_pg_del, NULL, "", RW },
> +    {"pg-get-ports", 1, 1, "", cmd_pre_pg_get_ports, cmd_pg_get_ports,

"ovn-nbctl pg-get-ports" expects exactly one argument.  The third field
of the 'struct ctl_command_syntax' structure is:

    /* Names that roughly describe the arguments that the command
     * uses.  These should be similar to the names displayed in the
     * man page or in the help output. */
    const char *arguments;

We should probably change this to:

{ "pg-get-ports", 1, 1, "", "PORT_GROUP", ...

> +        NULL, "", RO },
>  
>      /* HA chassis group commands. */
>      {"ha-chassis-group-add", 1, 1, "[CHASSIS GROUP]",

Regards,
Dumitru

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to