On Mon, Apr 10, 2023 at 7:26 PM Mark Michelson <mmich...@redhat.com> wrote:

> This modifies the acl-add and acl-del commands so that an ACL
> tier can be specified when adding or deleting ACLs.
>
> For acl-add, if the tier is specified, then the ACL created by the
> command will have that tier set.
>
> For acl-del, if the tier is specified, then the tier will be one of the
> criteria used when deciding which ACLs to delete. Because the tier is
> not any more or less specific than the other criteria used for deleting
> ACLs, a bitmap approach is used to determine the final set of ACLs that
> should be deleted.
>
> Signed-off-by: Mark Michelson <mmich...@redhat.com>
>
> Hi Mark,

I have two comments, see below.


> ---
>  tests/ovn-nbctl.at    |  81 ++++++++++++++++++++++++++
>  utilities/ovn-nbctl.c | 131 +++++++++++++++++++++++++++++-------------
>  2 files changed, 172 insertions(+), 40 deletions(-)
>
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index aa5baade4..3352064d1 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -2616,6 +2616,87 @@ ovn-nbctl: no row "foo1" in table Logical_Switch
>
>  dnl ---------------------------------------------------------------------
>
> +OVN_NBCTL_TEST([acl_tiers], [ACL tier operations], [
> +check ovn-nbctl ls-add ls
> +#check ovn-nbctl acl-add ls from-lport 1000 "ip" drop
> +#check_column 0 nb:ACL tier priority=1000
> +#
> +#check ovn-nbctl acl-del ls


Leftover comment?


> +check ovn-nbctl --tier=3 acl-add ls from-lport 1000 "ip" drop
> +check_column 3 nb:ACL tier priority=1000
> +
> +check ovn-nbctl --tier=3 acl-add ls from-lport 1001 "ip" drop
> +check_column 3 nb:ACL tier priority=1001
> +
> +check ovn-nbctl --tier=2 acl-add ls from-lport 1002 "ip" drop
> +check_column 2 nb:ACL tier priority=1002
> +
> +# Removing the tier 3 acls from ls should result in 1 ACL
> +# remaining.
> +check ovn-nbctl --tier=3 acl-del ls
> +check_row_count nb:ACL 1
> +check_column 2 nb:ACL tier priority=1002
> +
> +# Add two egress ACLs at tier 2.
> +check ovn-nbctl --tier=2 acl-add ls to-lport 1000 "ip" drop
> +check ovn-nbctl --tier=2 acl-add ls to-lport 1001 "ip" drop
> +
> +check_row_count nb:ACL 3 tier=2
> +
> +# This should remove the egress tier 2 ACLs and leave the
> +# ingress tier 2 ACL
> +check ovn-nbctl --tier=2 acl-del ls to-lport
> +check_row_count nb:ACL 1
> +check_column 2 nb:ACL tier priority=1002
> +check_column from-lport nb:ACL direction priority=1002
> +
> +# Re-add two ingress ACLs at tier 2.
> +check ovn-nbctl --tier=2 acl-add ls from-lport 1000 "ip" drop
> +check ovn-nbctl --tier=2 acl-add ls from-lport 1001 "ip" drop
> +
> +check_row_count nb:ACL 3
> +
> +# Attempt to remove all tier 3 ACLs. All three ACLs are tier 2
> +# so this shouldn't have any effect.
> +check ovn-nbctl --tier=3 acl-del ls
> +check_row_count nb:ACL 3
> +
> +# Attempt to remove all ingress tier 3 ACLs. All three ACLs are tier
> +# 2, so this shouldn't have any effect.
> +check ovn-nbctl --tier=3 acl-del ls from-lport
> +check_row_count nb:ACL 3
> +
> +# Attempt to remove the 1000 priority ACL but specify tier 3. Since
> +# all ACLs are tier 2, this should have no effect.
> +check ovn-nbctl --tier=3 acl-del ls from-lport 1000 "ip"
> +check_row_count nb:ACL 3
> +
> +# Specifying the proper tier should result in all ACLs being deleted.
> +check ovn-nbctl --tier=2 acl-del ls
> +check_row_count nb:ACL 0
> +
> +# Now let's experiment with identical ACLs at different tiers.
> +check ovn-nbctl --tier=1 acl-add ls from-lport 1000 "ip" drop
> +check ovn-nbctl --tier=2 acl-add ls from-lport 1000 "ip" drop
> +check ovn-nbctl --tier=3 acl-add ls from-lport 1000 "ip" drop
> +check_row_count nb:ACL 3
> +check_row_count nb:ACL 1 tier=1
> +check_row_count nb:ACL 1 tier=2
> +check_row_count nb:ACL 1 tier=3
> +
> +# Specifying tier 1 should result in only one ACL being deleted.
> +check ovn-nbctl --tier=1 acl-del ls from-lport 1000 "ip"
> +check_row_count nb:ACL 2
> +check_row_count nb:ACL 1 tier=2
> +check_row_count nb:ACL 1 tier=3
> +
> +# Not specifying a tier should result in all ACLs being deleted.
> +check ovn-nbctl acl-del ls from-lport 1000 "ip"
> +check_row_count nb:ACL 0
> +])
> +
> +dnl ---------------------------------------------------------------------
> +
>  AT_SETUP([ovn-nbctl - daemon retry connection])
>  OVN_NBCTL_TEST_START daemon
>  AT_CHECK([kill `cat ovsdb-server.pid`])
> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> index 22313ecd5..7910b9d3f 100644
> --- a/utilities/ovn-nbctl.c
> +++ b/utilities/ovn-nbctl.c
> @@ -48,6 +48,7 @@
>  #include "unixctl.h"
>  #include "util.h"
>  #include "openvswitch/vlog.h"
> +#include "bitmap.h"
>
>  VLOG_DEFINE_THIS_MODULE(nbctl);
>
> @@ -2100,6 +2101,8 @@ acl_cmp(const void *acl1_, const void *acl2_)
>          return after_lb2 ? -1 : 1;
>      } else if (acl1->priority != acl2->priority) {
>          return acl1->priority > acl2->priority ? -1 : 1;
> +    } else if (acl1->tier != acl2->tier) {
> +        return acl1->tier > acl2->tier ? -1 : 1;
>      } else {
>          return strcmp(acl1->match, acl2->match);
>      }
> @@ -2283,6 +2286,7 @@ nbctl_pre_acl(struct ctl_context *ctx)
>      ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_priority);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_match);
>      ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_options);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_tier);
>  }
>
>  static void
> @@ -2390,6 +2394,16 @@ nbctl_acl_add(struct ctl_context *ctx)
>          nbrec_acl_set_options(acl, &options);
>      }
>
> +    const char *tier_s = shash_find_data(&ctx->options, "--tier");
> +    if (tier_s) {
> +        int64_t tier;
> +        if (!str_to_long(tier_s, 10, &tier)) {
> +            ctl_error(ctx, "Invalid tier %s", tier_s);
> +            return;
> +        }
> +        nbrec_acl_set_tier(acl, tier);
> +    }
> +
>      /* Check if same acl already exists for the ls/portgroup */
>      size_t n_acls = pg ? pg->n_acls : ls->n_acls;
>      struct nbrec_acl **acls = pg ? pg->acls : ls->acls;
> @@ -2418,6 +2432,10 @@ nbctl_acl_del(struct ctl_context *ctx)
>  {
>      const struct nbrec_logical_switch *ls = NULL;
>      const struct nbrec_port_group *pg = NULL;
> +    const char *tier_s = shash_find_data(&ctx->options, "--tier");
> +    int64_t tier;
> +    unsigned long *bitmaps[3];
> +    size_t n_bitmaps = 0;
>
>      char *error = acl_cmd_get_pg_or_ls(ctx, &ls, &pg);
>      if (error) {
> @@ -2425,8 +2443,13 @@ nbctl_acl_del(struct ctl_context *ctx)
>          return;
>      }
>
> -    if (ctx->argc == 2) {
> -        /* If direction, priority, and match are not specified, delete
> +    if (tier_s && !str_to_long(tier_s, 10, &tier)) {
> +        ctl_error(ctx, "Invalid tier %s", tier_s);
> +        return;
> +    }
> +
> +    if (ctx->argc == 2 && !tier_s) {
> +        /* If direction, priority, tier, and match are not specified,
> delete
>           * all ACLs. */
>          if (pg) {
>              nbrec_port_group_verify_acls(pg);
> @@ -2438,55 +2461,83 @@ nbctl_acl_del(struct ctl_context *ctx)
>          return;
>      }
>
> -    const char *direction;
> -    error = parse_direction(ctx->argv[2], &direction);
> -    if (error) {
> -        ctx->error = error;
> -        return;
> -    }
> -
>      size_t n_acls = pg ? pg->n_acls : ls->n_acls;
>      struct nbrec_acl **acls = pg ? pg->acls : ls->acls;
> -    /* If priority and match are not specified, delete all ACLs with the
> -     * specified direction. */
> -    if (ctx->argc == 3) {
> +
> +    if (tier_s) {
> +        bitmaps[n_bitmaps] = bitmap_allocate(n_acls);
>          for (size_t i = 0; i < n_acls; i++) {
> -            if (!strcmp(direction, acls[i]->direction)) {
> -                if (pg) {
> -                    nbrec_port_group_update_acls_delvalue(pg, acls[i]);
> -                } else {
> -                    nbrec_logical_switch_update_acls_delvalue(ls,
> acls[i]);
> -                }
> +            if (acls[i]->tier == tier) {
> +                bitmap_set1(bitmaps[n_bitmaps], i);
>              }
>          }
> -        return;
> +        n_bitmaps++;
>      }
>
> -    int64_t priority;
> -    error = parse_priority(ctx->argv[3], &priority);
> -    if (error) {
> -        ctx->error = error;
> -        return;
> -    }
> +    if (ctx->argc >= 3) {
> +        const char *direction;
> +        error = parse_direction(ctx->argv[2], &direction);
> +        if (error) {
> +            ctx->error = error;
> +            goto cleanup;
> +        }
>
> -    if (ctx->argc == 4) {
> -        ctl_error(ctx, "cannot specify priority without match");
> -        return;
> +        /* If priority and match are not specified, delete all ACLs with
> the
> +         * specified direction. */
> +        bitmaps[n_bitmaps] = bitmap_allocate(n_acls);
> +        for (size_t i = 0; i < n_acls; i++) {
> +            if (!strcmp(direction, acls[i]->direction)) {
> +                bitmap_set1(bitmaps[n_bitmaps], i);
> +            }
> +        }
> +        n_bitmaps++;
>      }
>
> -    /* Remove the matching rule. */
> -    for (size_t i = 0; i < n_acls; i++) {
> -        struct nbrec_acl *acl = acls[i];
> +    if (ctx->argc >= 4) {
> +        int64_t priority;
> +        error = parse_priority(ctx->argv[3], &priority);
> +        if (error) {
> +            ctx->error = error;
> +            goto cleanup;
> +        }
>
> -        if (priority == acl->priority && !strcmp(ctx->argv[4],
> acl->match) &&
> -             !strcmp(direction, acl->direction)) {
> -            if (pg) {
> -                nbrec_port_group_update_acls_delvalue(pg, acl);
> -            } else {
> -                nbrec_logical_switch_update_acls_delvalue(ls, acl);
> +        if (ctx->argc == 4) {
> +            ctl_error(ctx, "cannot specify priority without match");
> +            goto cleanup;
> +        }
> +
> +        /* Remove the matching rule. */
> +        bitmaps[n_bitmaps] = bitmap_allocate(n_acls);
> +        for (size_t i = 0; i < n_acls; i++) {
> +            struct nbrec_acl *acl = acls[i];
> +
> +            if (priority == acl->priority &&
> +                !strcmp(ctx->argv[4], acl->match)) {
> +                bitmap_set1(bitmaps[n_bitmaps], i);
>              }
> -            return;
>          }
> +        n_bitmaps++;
> +    }
> +
> +    unsigned long *bitmap_result = bitmap_allocate1(n_acls);
> +    for (size_t i = 0; i < n_bitmaps; i++) {
> +        bitmap_result = bitmap_and(bitmap_result, bitmaps[i], n_acls);
> +    }
> +
> +    size_t index;
> +    BITMAP_FOR_EACH_1 (index, n_acls, bitmap_result) {
> +        if (pg) {
> +            nbrec_port_group_update_acls_delvalue(pg, acls[index]);
> +        } else {
> +            nbrec_logical_switch_update_acls_delvalue(ls, acls[index]);
> +        }
> +    }
> +
> +    free(bitmap_result);
> +
> +cleanup:
> +    for (size_t i = 0; i < n_bitmaps; i++) {
> +        free(bitmaps[i]);
>      }
>  }
>
> @@ -7658,9 +7709,9 @@ static const struct ctl_command_syntax
> nbctl_commands[] = {
>      { "acl-add", 5, 6, "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH
> ACTION",
>        nbctl_pre_acl, nbctl_acl_add, NULL,
>        "--log,--may-exist,--type=,--name=,--severity=,--meter=,--label=,"
> -      "--apply-after-lb", RW },
> +      "--apply-after-lb,--tier=", RW },
>      { "acl-del", 1, 4, "{SWITCH | PORTGROUP} [DIRECTION [PRIORITY
> MATCH]]",
> -      nbctl_pre_acl, nbctl_acl_del, NULL, "--type=", RW },
> +      nbctl_pre_acl, nbctl_acl_del, NULL, "--type=,--tier=", RW },
>      { "acl-list", 1, 1, "{SWITCH | PORTGROUP}",
>        nbctl_pre_acl_list, nbctl_acl_list, NULL, "--type=", RO },
>
> --
> 2.38.1
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Please also add the --tier option into ovn-nbctl.8.xml.

Thanks,
Ales

-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com    IM: amusil
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to