On Sat, Jul 19, 2025 at 8:27 AM Sragdhara Datta Chaudhuri
<sragdha.chau...@nutanix.com> wrote:
>
> Network function:
> network-function-add <nf-name> <inport> <outport> - Add a new NF
> network-function-del <nf-name-or-uuid> - Delete a NF
> network-function-list - List all NFs
>
> Network function group:
> network-function-group-add <nfg-name> [<nf1> <nf2> ...] - Add a new NFG
> network-function-group-del <nfg-name-or-uuid> - Delete a NFG
> network-function-group-list [<nfg-name-or-uuid>] - List all NFGs
> network-function-group-add-network-function <nfg-name-or-uuid> 
> <nf-name-or-uuid>
>  - Add a NF to a NFG
> network-function-group-del-network-function <nfg-name-or-uuid> 
> <nf-name-or-uuid>
>  - Remove a NF from a NFG
>
> ACL (new optional parameter added for NFG):
> acl-add <ls>|<pg> <direction> <priority> <match> <action> [<nfg-name-or-uuid>]
>
> Acked-by: Naveen Yerramneni <naveen.yerramn...@nutanix.com>
> Signed-off-by: Sragdhara Datta Chaudhuri <sragdha.chau...@nutanix.com>

Thanks for the patch.

You need to document the new commands in ovn-nbctl.8.xml.

With this comment addressed:
Acked-by:Numan Siddique <num...@ovn.org>

Numan

> ---
>  utilities/ovn-nbctl.c | 533 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 530 insertions(+), 3 deletions(-)
>
> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> index 56a513217..88e735c39 100644
> --- a/utilities/ovn-nbctl.c
> +++ b/utilities/ovn-nbctl.c
> @@ -283,7 +283,7 @@ Logical switch commands:\n\
>  \n\
>  ACL commands:\n\
>    [--type={switch | port-group}] [--log] [--severity=SEVERITY] [--name=NAME] 
> [--may-exist]\n\
> -  acl-add {SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION\n\
> +  acl-add {SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION 
> [NETWORK-FUNCTION-GROUP]\n\
>                              add an ACL to SWITCH/PORTGROUP\n\
>    [--type={switch | port-group}]\n\
>    acl-del {SWITCH | PORTGROUP} [DIRECTION [PRIORITY MATCH]]\n\
> @@ -373,6 +373,26 @@ Forwarding group commands:\n\
>    fwd-group-del GROUP       delete a forwarding group\n\
>    fwd-group-list [SWITCH]   print forwarding groups\n\
>  \n\
> +Network function group commands:\n\
> +  network-function-group-add NETWORK-FUNCTION-GROUP [NETWORK-FUNCTION]...\n\
> +                            create a network-functionr-group\n\
> +  network-function-group-del NETWORK-FUNCTION-GROUP\n\
> +                            delete a network-function-group\n\
> +  network-function-group-list print all network-function-groups\n\
> +  network-function-group-add-network-function NETWORK-FUNCTION-GROUP 
> NETWORK-FUNCTION\n\
> +                            add a network-function to a\n\
> +                            network-function-group\n\
> +  network-function-group-del-network-function NETWORK-FUNCTION-GROUP 
> NETWORK-FUNCTION\n\
> +                            delete a network-function from a\n\
> +                            network-function-group\n\
> +\n\
> +Network function commands:\n\
> +  network-function-add NETWORK-FUNCTION PORT-IN PORT-OUT\n\
> +                            create a network-function\n\
> +  network-function-del NETWORK-FUNCTION  delete a network-function\n\
> +  network-function-list     print all network-functions\n\
> +\n\n",program_name, program_name);
> +    printf("\
>  Logical router commands:\n\
>    lr-add [ROUTER]           create a logical router named ROUTER\n\
>    lr-del ROUTER             delete ROUTER and all its ports\n\
> @@ -429,7 +449,7 @@ Policy commands:\n\
>    lr-policy-del ROUTER [{PRIORITY | UUID} [MATCH]]\n\
>                              remove policies from ROUTER\n\
>    lr-policy-list ROUTER     print policies for ROUTER\n\
> -\n\n",program_name, program_name);
> +\n\n");
>      printf("\
>  NAT commands:\n\
>    [--stateless]\n\
> @@ -2135,6 +2155,462 @@ nbctl_lsp_get_ls(struct ctl_context *ctx)
>      }
>  }
>
> +
> +static char * OVS_WARN_UNUSED_RESULT
> +nf_group_by_name_or_uuid(
> +    struct ctl_context *ctx, const char *id,
> +    const bool must_exist,
> +    const struct nbrec_network_function_group **nf_group_p)
> +{
> +    const struct nbrec_network_function_group *nf_group = NULL;
> +    struct uuid nf_group_uuid;
> +    bool is_uuid = uuid_from_string(&nf_group_uuid, id);
> +
> +    *nf_group_p = NULL;
> +    if (is_uuid) {
> +        nf_group = nbrec_network_function_group_get_for_uuid(ctx->idl,
> +                                                             &nf_group_uuid);
> +    }
> +
> +    if (!nf_group) {
> +        const struct nbrec_network_function_group *iter;
> +        NBREC_NETWORK_FUNCTION_GROUP_FOR_EACH (iter, ctx->idl) {
> +            if (strcmp(iter->name, id)) {
> +                continue;
> +            }
> +            if (nf_group) {
> +                return xasprintf("Multiple network function group named 
> '%s'. "
> +                                 "Use a UUID.", id);
> +            }
> +            nf_group = iter;
> +        }
> +    }
> +    if (!nf_group && must_exist) {
> +        return xasprintf("%s: network function group %s not found", id,
> +                         is_uuid ? "UUID" : "name");
> +    }
> +
> +    *nf_group_p = nf_group;
> +    return NULL;
> +}
> +
> +static char * OVS_WARN_UNUSED_RESULT
> +nf_by_name_or_uuid(
> +    struct ctl_context *ctx, const char *id,
> +    bool must_exist, const struct nbrec_network_function **nf_p)
> +{
> +    const struct nbrec_network_function *nf = NULL;
> +    struct uuid nf_uuid;
> +    bool is_uuid = uuid_from_string(&nf_uuid, id);
> +
> +    *nf_p = NULL;
> +    if (is_uuid) {
> +        nf = nbrec_network_function_get_for_uuid(ctx->idl, &nf_uuid);
> +    }
> +
> +    if (!nf) {
> +        const struct nbrec_network_function *iter;
> +        NBREC_NETWORK_FUNCTION_FOR_EACH (iter, ctx->idl) {
> +            if (strcmp(iter->name, id)) {
> +                continue;
> +            }
> +            if (nf) {
> +                return xasprintf("Multiple network functions named '%s'. "
> +                                 "Use a UUID.", id);
> +            }
> +            nf = iter;
> +        }
> +    }
> +    if (!nf && must_exist) {
> +        return xasprintf("%s: network function %s not found", id,
> +                         is_uuid ? "UUID" : "name");
> +    }
> +
> +    *nf_p = nf;
> +    return NULL;
> +}
> +
> +/*
> + *  Network Function Groups CLI Functions
> + */
> +static void
> +nbctl_pre_nf_group_add(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
> +    ovsdb_idl_add_column(
> +        ctx->idl, &nbrec_network_function_group_col_network_function);
> +}
> +
> +static char *
> +set_network_function_in_network_function_group(
> +    struct ctl_context *ctx,
> +    const struct nbrec_network_function_group *nf_group,
> +    char **new_network_function, size_t num_new_network_function)
> +{
> +    struct nbrec_network_function **nfs;
> +    nfs = xmalloc(sizeof *nfs * num_new_network_function);
> +
> +    size_t i;
> +    char *error = NULL;
> +    for (i = 0; i < num_new_network_function; i++) {
> +        const struct nbrec_network_function *nf;
> +        error = nf_by_name_or_uuid(ctx, new_network_function[i], true, &nf);
> +        if (error) {
> +            free(nfs);
> +            return error;
> +        }
> +        nfs[i] = (struct nbrec_network_function *) nf;
> +    }
> +    nbrec_network_function_group_set_network_function(
> +        nf_group, nfs, num_new_network_function);
> +    free(nfs);
> +    return error;
> +}
> +
> +static void
> +nbctl_nf_group_add(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function_group *nf_group;
> +    const char *nfg_name = ctx->argv[1];
> +
> +    const bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
> +    const bool add_duplicate = shash_find(&ctx->options,
> +                                           "--add-duplicate") != NULL;
> +
> +    if (!add_duplicate) {
> +        NBREC_NETWORK_FUNCTION_GROUP_FOR_EACH (nf_group, ctx->idl) {
> +            if (!strcmp(nf_group->name, nfg_name)) {
> +                if (may_exist) {
> +                    return;
> +                }
> +                ctl_error(ctx, "%s: a network-function-group with this name "
> +                          "already exists", nfg_name);
> +                return;
> +            }
> +        }
> +    }
> +
> +    nf_group = nbrec_network_function_group_insert(ctx->txn);
> +    nbrec_network_function_group_set_name(nf_group, nfg_name);
> +    nbrec_network_function_group_set_mode(nf_group, "inline");
> +
> +    if (ctx->argc > 2) {
> +        ctx->error = set_network_function_in_network_function_group(
> +            ctx, nf_group, ctx->argv + 2, ctx->argc - 2);
> +    }
> +}
> +
> +static void
> +nbctl_pre_nf_group_del(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
> +}
> +
> +static void
> +nbctl_nf_group_del(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function_group *nf_group;
> +    const bool must_exist = !shash_find(&ctx->options, "--if-exists");
> +
> +    char *error = nf_group_by_name_or_uuid(
> +        ctx, ctx->argv[1], must_exist, &nf_group);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    if (!nf_group) {
> +        return;
> +    }
> +
> +    nbrec_network_function_group_delete(nf_group);
> +}
> +
> +static void
> +nbctl_pre_nf_group_list(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl,
> +                         &nbrec_network_function_group_col_network_function);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
> +}
> +
> +static void
> +nbctl_nf_group_list(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function_group *nf_group;
> +    struct smap nf_groups;
> +    size_t i;
> +
> +    smap_init(&nf_groups);
> +
> +    NBREC_NETWORK_FUNCTION_GROUP_FOR_EACH (nf_group, ctx->idl) {
> +        smap_add_format(&nf_groups, nf_group->name,
> +                        UUID_FMT " (%s)",
> +                        UUID_ARGS(&nf_group->header_.uuid),
> +                        nf_group->name);
> +    }
> +    const struct smap_node **nodes = smap_sort(&nf_groups);
> +    for (i = 0; i < smap_count(&nf_groups); i++) {
> +        const struct smap_node *node = nodes[i];
> +        ds_put_format(&ctx->output, "%s\n", node->value);
> +    }
> +    smap_destroy(&nf_groups);
> +    free(nodes);
> +}
> +
> +static void
> +nbctl_pre_nf_group_add_network_function(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl,
> +                         &nbrec_network_function_group_col_network_function);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +}
> +
> +static void
> +nbctl_nf_group_add_network_function(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function_group *nf_group;
> +    const struct nbrec_network_function *nf;
> +    const bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
> +
> +    char * error = nf_group_by_name_or_uuid(ctx, ctx->argv[1], true,
> +                                            &nf_group);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    if (!nf_group) {
> +        return;
> +    }
> +
> +    /* Check that network-function exists  */
> +    error = nf_by_name_or_uuid(ctx, ctx->argv[2], true, &nf);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +
> +    /* Do not add network_function more than once in a given
> +     * network-function-group */
> +    for (size_t i = 0; i < nf_group->n_network_function; i++) {
> +        if (nf_group->network_function[i] == nf) {
> +            if (!may_exist) {
> +                ctl_error(ctx, "network-function %s is already added to "
> +                          "network-function-group %s",
> +                          ctx->argv[2], ctx->argv[1]);
> +                return;
> +            }
> +            return;
> +        }
> +    }
> +
> +    /* Insert the logical network-function into the logical
> +     * network-function-group. */
> +    nbrec_network_function_group_verify_network_function(nf_group);
> +    struct nbrec_network_function  **new_network_function =
> +        xmalloc(sizeof *new_network_function
> +                * (nf_group->n_network_function + 1));
> +    memcpy(new_network_function, nf_group->network_function,
> +           sizeof *new_network_function * nf_group->n_network_function);
> +    new_network_function[nf_group->n_network_function] =
> +        CONST_CAST(struct nbrec_network_function *, nf);
> +    nbrec_network_function_group_set_network_function(nf_group,
> +        new_network_function, nf_group->n_network_function + 1);
> +    free(new_network_function);
> +}
> +
> +static void
> +remove_nf_from_network_function_group(
> +      const struct nbrec_network_function_group *nf_group, size_t idx)
> +{
> +
> +    struct nbrec_network_function **new_network_function
> +        = xmemdup(nf_group->network_function, sizeof *new_network_function *
> +                  nf_group->n_network_function);
> +    new_network_function[idx]
> +        = new_network_function[nf_group->n_network_function - 1];
> +    nbrec_network_function_group_verify_network_function(nf_group);
> +    nbrec_network_function_group_set_network_function(
> +        nf_group, new_network_function,
> +        nf_group->n_network_function - 1);
> +    free(new_network_function);
> +}
> +
> +static void
> +nbctl_pre_nf_group_del_network_function(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl,
> +                         &nbrec_network_function_group_col_network_function);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +}
> +
> +static void
> +nbctl_nf_group_del_network_function(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function *nf;
> +    const struct nbrec_network_function_group *nf_group;
> +    const bool must_exist = !shash_find(&ctx->options, "--if-exists");
> +
> +
> +    char * error = nf_group_by_name_or_uuid(ctx, ctx->argv[1], must_exist,
> +                                            &nf_group);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    if (!nf_group) {
> +        return;
> +    }
> +
> +    error = nf_by_name_or_uuid(ctx, ctx->argv[2], must_exist, &nf);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    /* Find the network-function_group that contains 'network-function',
> +     * then delete it. */
> +
> +    for (size_t i = 0; i < nf_group->n_network_function; i++) {
> +        if (nf_group->network_function[i] == nf) {
> +            remove_nf_from_network_function_group(nf_group,i);
> +            return;
> +        }
> +    }
> +    if (must_exist) {
> +        ctl_error(ctx, "network-function %s is not part of any logical 
> switch",
> +                  ctx->argv[1]);
> +        return;
> +    }
> +}
> +/* End of network-function-group operations */
> +
> +/*
> + * network-function operations
> + */
> +static void
> +nbctl_pre_nf_add(struct ctl_context *ctx)
> +{
> +    nbctl_pre_context(ctx);
> +
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_inport);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
> +}
> +
> +static void
> +nbctl_nf_add(struct ctl_context *ctx)
> +{
> +    const struct nbrec_logical_switch_port *lsp_in, *lsp_out;
> +    const struct nbrec_network_function *nf;
> +
> +    const bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
> +    const bool add_duplicate = shash_find(&ctx->options,
> +                                           "--add-duplicate") != NULL;
> +    if (may_exist && add_duplicate) {
> +        ctl_error(ctx,
> +                  "--may-exist and --add-duplicate may not be used 
> together");
> +        return;
> +    }
> +
> +    char * error = lsp_by_name_or_uuid(ctx, ctx->argv[2], true, &lsp_in);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    error = lsp_by_name_or_uuid(ctx, ctx->argv[3], true, &lsp_out);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +
> +    const char *nf_name = ctx->argv[1];
> +
> +    if (!add_duplicate) {
> +        NBREC_NETWORK_FUNCTION_FOR_EACH (nf, ctx->idl) {
> +            if (!strcmp(nf->name, nf_name)) {
> +                if (may_exist) {
> +                    return;
> +                }
> +                ctl_error(ctx, "%s: same name network-function already 
> exists",
> +                          nf_name);
> +                return;
> +            }
> +        }
> +    }
> +
> +    /* create the logical network-function. */
> +    nf = nbrec_network_function_insert(ctx->txn);
> +    nbrec_network_function_set_inport(nf, lsp_in);
> +    nbrec_network_function_set_outport(nf, lsp_out);
> +    nbrec_network_function_set_name(nf, nf_name);
> +}
> +
> +static void
> +nbctl_pre_nf_del(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +}
> +
> +static void
> +nbctl_nf_del(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function *nf;
> +    const bool must_exist = !shash_find(&ctx->options, "--if-exists");
> +
> +    char *error = nf_by_name_or_uuid(ctx, ctx->argv[1], must_exist, &nf);
> +    if (error) {
> +        ctx->error = error;
> +        return;
> +    }
> +    if (!nf) {
> +        return;
> +    }
> +    nbrec_network_function_delete(nf);
> +}
> +
> +static void
> +nbctl_pre_nf_list(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_name);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_inport);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_col_outport);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_logical_switch_port_col_name);
> +}
> +
> +static void
> +nbctl_nf_list(struct ctl_context *ctx)
> +{
> +    const struct nbrec_network_function *nf;
> +    struct smap nfs;
> +    size_t i;
> +
> +    smap_init(&nfs);
> +
> +    NBREC_NETWORK_FUNCTION_FOR_EACH (nf, ctx->idl) {
> +        const struct nbrec_logical_switch_port *linport  = nf->inport;
> +        const struct nbrec_logical_switch_port *loutport = nf->outport;
> +        const char *linport_name = linport ? linport->name : "<not_set>";
> +        const char *loutport_name = loutport ? loutport->name : "<not_set>";
> +        smap_add_format(&nfs, nf->name,
> +                        UUID_FMT " (%s) in:%s out:%s",
> +                        UUID_ARGS(&nf->header_.uuid),
> +                        nf->name, linport_name, loutport_name);
> +    }
> +    const struct smap_node **nodes = smap_sort(&nfs);
> +    for (i = 0; i < smap_count(&nfs); i++) {
> +        const struct smap_node *node = nodes[i];
> +        ds_put_format(&ctx->output, "%s\n", node->value);
> +    }
> +    smap_destroy(&nfs);
> +    free(nodes);
> +}
> +
> +/* End of network-function operations */
> +
> +
>  enum {
>      DIR_FROM_LPORT,
>      DIR_TO_LPORT
> @@ -2232,6 +2708,10 @@ nbctl_acl_print(struct ctl_context *ctx, const struct 
> nbrec_acl **acls,
>          ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s",
>                        acl->direction, acl->priority, acl->match,
>                        acl->action);
> +        if (acl->network_function_group) {
> +            ds_put_format(&ctx->output, " network-function-group=%s",
> +                          acl->network_function_group->name);
> +        }
>          if (acl->log) {
>              ds_put_cstr(&ctx->output, " log(");
>              if (acl->name) {
> @@ -2405,6 +2885,8 @@ nbctl_pre_acl(struct ctl_context *ctx)
>
>      ovsdb_idl_add_table(ctx->idl, &nbrec_table_sample_collector);
>      ovsdb_idl_add_table(ctx->idl, &nbrec_table_sample);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_network_function_group);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_network_function_group_col_name);
>  }
>
>  static void
> @@ -2461,10 +2943,21 @@ nbctl_acl_add(struct ctl_context *ctx)
>
>      /* Create the acl. */
>      struct nbrec_acl *acl = nbrec_acl_insert(ctx->txn);
> +    const struct nbrec_network_function_group *network_function_group = NULL;
>      nbrec_acl_set_priority(acl, priority);
>      nbrec_acl_set_direction(acl, direction);
>      nbrec_acl_set_match(acl, ctx->argv[4]);
>      nbrec_acl_set_action(acl, action);
> +    if ((ctx->argv[6]) && strcmp(ctx->argv[6], "--")) {
> +        error = nf_group_by_name_or_uuid(ctx, ctx->argv[6], true,
> +                                          &network_function_group);
> +        if (error) {
> +            ctx->error = error;
> +            return;
> +        }
> +
> +        nbrec_acl_set_network_function_group(acl, network_function_group);
> +    }
>
>      /* Logging options. */
>      bool log = shash_find(&ctx->options, "--log") != NULL;
> @@ -8264,7 +8757,8 @@ static const struct ctl_command_syntax nbctl_commands[] 
> = {
>      { "ls-list", 0, 0, "", nbctl_pre_ls_list, nbctl_ls_list, NULL, "", RO },
>
>      /* acl commands. */
> -    { "acl-add", 5, 6, "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH 
> ACTION",
> +    { "acl-add", 5, 7,
> +      "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION 
> [NETWORK-FUNCTION-GROUP]",
>        nbctl_pre_acl, nbctl_acl_add, NULL,
>        "--log,--may-exist,--type=,--name=,--severity=,--meter=,--label=,"
>        "--apply-after-lb,--tier=,--sample-new=,--sample-est=", RW },
> @@ -8356,6 +8850,39 @@ static const struct ctl_command_syntax 
> nbctl_commands[] = {
>      { "lsp-detach-mirror", 2, 2, "PORT MIRROR", nbctl_pre_lsp_mirror,
>        nbctl_lsp_detach_mirror, NULL, "", RW },
>
> +    /* network-function-group commands. */
> +    { "network-function-group-add", 1, INT_MAX,
> +      "NETWORK-FUNCTION-GROUP [NETWORK-FUNCTION]",
> +      nbctl_pre_nf_group_add,
> +      nbctl_nf_group_add, NULL, "--may-exist,--add-duplicate", RW },
> +    { "network-function-group-del", 1, 1, "NETWORK-FUNCTION-GROUP",
> +      nbctl_pre_nf_group_del,
> +      nbctl_nf_group_del,
> +      NULL, "--if-exists", RW },
> +    { "network-function-group-list", 0, 1, "[NETWORK-FUNCTION-GROUP]",
> +      nbctl_pre_nf_group_list,
> +      nbctl_nf_group_list,
> +      NULL, "", RO },
> +    { "network-function-group-add-network-function", 2, 2,
> +      "NETWORK-FUNCTION-GROUP NETWORK-FUNCTION",
> +      nbctl_pre_nf_group_add_network_function,
> +      nbctl_nf_group_add_network_function, NULL, "--may-exist", RW },
> +    { "network-function-group-del-network-function", 2, 2,
> +      "NETWORK-FUNCTION-GROUP NETWORK-FUNCTION",
> +      nbctl_pre_nf_group_del_network_function,
> +      nbctl_nf_group_del_network_function, NULL, "--if-exists", RW },
> +
> +    /* network-function commands. */
> +    { "network-function-add", 3, 3, "NETWORK-FUNCTION, PORT-IN, PORT-OUT",
> +      nbctl_pre_nf_add,
> +      nbctl_nf_add,
> +      NULL, "--may-exist,--add-duplicate", RW },
> +    { "network-function-del", 1, 1, "NETWORK-FUNCTION", nbctl_pre_nf_del,
> +      nbctl_nf_del,
> +      NULL, "--if-exists", RW },
> +    { "network-function-list", 0, 0, "", nbctl_pre_nf_list,
> +      nbctl_nf_list, NULL, "", RO },
> +
>      /* forwarding group commands. */
>      { "fwd-group-add", 4, INT_MAX, "SWITCH GROUP VIP VMAC PORT...",
>        nbctl_pre_fwd_group_add, nbctl_fwd_group_add, NULL, "--liveness", RW },
> --
> 2.39.3
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to