[ovs-dev] [PATCH v3 2/9] ovs-vsctl: Add conntrack zone commands.

Darrell Ball dlu998 at gmail.com
Tue Aug 13 04:54:42 UTC 2019


Thanks for the patch

Thanks for the fixups; mostly minor comments inline.

On Mon, Aug 12, 2019 at 5:53 PM Yi-Hung Wei <yihung.wei at gmail.com> wrote:

> From: William Tu <u9012063 at gmail.com>
>
> The patch adds commands creating/deleting/listing conntrack zone
> timeout policies:
>   $ ovs-vsctl {add,del,list}-zone-tp dp zone=zone_id ...
>
> Signed-off-by: William Tu <u9012063 at gmail.com>
> ---
>  tests/ovs-vsctl.at       |  34 ++++++++-
>  utilities/ovs-vsctl.8.in |  26 +++++++
>  utilities/ovs-vsctl.c    | 194
> +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 252 insertions(+), 2 deletions(-)
>
> diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
> index 46fa3c5b1a33..df15fb6901a0 100644
> --- a/tests/ovs-vsctl.at
> +++ b/tests/ovs-vsctl.at
> @@ -805,6 +805,20 @@ AT_CHECK(
>    [RUN_OVS_VSCTL([--if-exists remove netflow x targets '"1.2.3.4:567
> "'])])
>  AT_CHECK(
>    [RUN_OVS_VSCTL([--if-exists clear netflow x targets])])
> +
> +AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 --
> set Open_vSwitch . datapaths:"netdev"=@m])], [0], [stdout])
> +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=1 icmp_first=1
> icmp_reply=2])])
> +AT_CHECK([RUN_OVS_VSCTL([--may-exist add-zone-tp netdev zone=1
> icmp_first=1 icmp_reply=2])])
> +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:1, Timeout
> Policies: icmp_first=1 icmp_reply=2
> +])
> +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2
> icmp_reply=3])])
> +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:1, Timeout
> Policies: icmp_first=1 icmp_reply=2
> +Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3
> +])
> +AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=1])])
> +AT_CHECK([RUN_OVS_VSCTL([--if-exists del-zone-tp netdev zone=1])])
> +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout
> Policies: icmp_first=2 icmp_reply=3
> +])
>  OVS_VSCTL_CLEANUP
>  AT_CLEANUP
>
> @@ -890,10 +904,10 @@ AT_CHECK([RUN_OVS_VSCTL([set bridge br0
> flood_vlans=-1])],
>  AT_CHECK([RUN_OVS_VSCTL([set bridge br0 flood_vlans=4096])],
>    [1], [], [ovs-vsctl: constraint violation: 4096 is not in the valid
> range 0 to 4095 (inclusive)
>  ])
> -AT_CHECK([RUN_OVS_VSCTL([set c br1 'connection-mode=xyz'])],
> +AT_CHECK([RUN_OVS_VSCTL([set controller br1 'connection-mode=xyz'])],
>    [1], [], [[ovs-vsctl: constraint violation: xyz is not one of the
> allowed values ([in-band, out-of-band])
>  ]])
> -AT_CHECK([RUN_OVS_VSCTL([set c br1 connection-mode:x=y])],
> +AT_CHECK([RUN_OVS_VSCTL([set controller br1 connection-mode:x=y])],
>    [1], [], [ovs-vsctl: cannot specify key to set for non-map column
> connection_mode
>  ])
>  AT_CHECK([RUN_OVS_VSCTL([add bridge br1 datapath_id x y])],
> @@ -929,6 +943,22 @@ AT_CHECK([RUN_OVS_VSCTL([remove bridge br1
> flood-vlans true])],
>  AT_CHECK([RUN_OVS_VSCTL([clear bridge br1 name])],
>    [1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
>  ])
> +
> +AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 --
> set Open_vSwitch . datapaths:"netdev"=@m])], [0], [stdout])
>

If I execute

AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 --
set Open_vSwitch . datapaths:"netdevvv"=@m])], [0], [stdout])

it works, but there is no such datapath type 'netdevvv'

I think it would be better to enforce an enum here as well thru the schema,
as I mentioned in V2, since this handles errors better.
This is actually the same idea as enforcing enum for timeout keys that was
done for V3 to block bad timeout keys like "foo_bar=3"
I commented patch 1 anyways.


> +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdevxx zone=1 icmp_first=1
> icmp_reply=2])],
> +  [1], [], [ovs-vsctl: datapath netdevxx does not exist
> +])
> +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2
> icmp_reply=3])])
> +AT_CHECK([RUN_OVS_VSCTL([add-zone-tp netdev zone=2 icmp_first=2
> icmp_reply=3])],
> +  [1], [], [ovs-vsctl: zone id 2 already exists
> +])
> +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout
> Policies: icmp_first=2 icmp_reply=3
> +])
> +AT_CHECK([RUN_OVS_VSCTL([del-zone-tp netdev zone=11])],
> +  [1], [], [ovs-vsctl: zone id 11 does not exist
> +])
> +AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout
> Policies: icmp_first=2 icmp_reply=3
> +])
>  OVS_VSCTL_CLEANUP
>  AT_CLEANUP
>
> diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in
> index 7c09df79bd29..5b9883ae1c3d 100644
> --- a/utilities/ovs-vsctl.8.in
> +++ b/utilities/ovs-vsctl.8.in
> @@ -353,6 +353,32 @@ list.
>  Prints the name of the bridge that contains \fIiface\fR on standard
>  output.
>  .
> +.SS "Conntrack Zone Commands"
> +These commands query and modify datapath CT zones and Timeout Policies.
> +.
> +.IP "[\fB\-\-may\-exist\fR] \fBadd\-zone\-tp \fIdatapath
> \fBzone=\fIzone_id \fIpolicies\fR"
> +Creates a conntrack zone timeout policy with \fIzone_id\fR in
> +\fIdatapath\fR.  The \fIpolicies\fR consist of \fIkey\fB=\fIvalue\fR
> +pairs, separated by spaces.  For example, \fBicmp_first=30
> +icmp_reply=60\fR specifies a 30-second timeout policy for the first ICMP
> +packet and a 60-second policy for ICMP reply packet.  See the
> +\fBCT_Timeout_Policy\fR table in \fBovs-vswitchd.conf.db\fR(5) for the
> +supported keys.
> +.IP
> +Without \fB\-\-may\-exist\fR, attempting to add a \fIzone_id\fR that
> +already exists is an error.  With \fB\-\-may\-exist\fR,
> +this command does nothing if \fIzone_id\fR is already created\fR.
> +.
> +.IP "[\fB\-\-if\-exists\fR] \fBdel\-zone\-tp \fIdatapath
> \fBzone=\fIzone_id\fR"
> +Delete the timeout policy associated with \fIzone_id\fR from
> \fIdatapath\fR.
> +.IP
> +Without \fB\-\-if\-exists\fR, attempting to delete a zone that
> +does not exist is an error.  With \fB\-\-if\-exists\fR, attempting to
> +delete a zone that does not exist has no effect.
> +.
> +.IP "\fBlist\-zone\-tp \fIdatapath\fR"
> +Prints the timeout policies of all zones in \fIdatapath\fR.
> +.
>  .SS "OpenFlow Controller Connectivity"
>  .
>  \fBovs\-vswitchd\fR can perform all configured bridging and switching
> diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
> index 4948137efe8c..7419f723804c 100644
> --- a/utilities/ovs-vsctl.c
> +++ b/utilities/ovs-vsctl.c
> @@ -40,6 +40,7 @@
>  #include "ovsdb-idl.h"
>  #include "openvswitch/poll-loop.h"
>  #include "process.h"
> +#include "simap.h"
>  #include "stream.h"
>  #include "stream-ssl.h"
>  #include "smap.h"
> @@ -49,6 +50,7 @@
>  #include "table.h"
>  #include "timeval.h"
>  #include "util.h"
> +#include "openvswitch/ofp-parse.h"
>

include ordering is not right


>  #include "openvswitch/vconn.h"
>  #include "openvswitch/vlog.h"
>
> @@ -1153,6 +1155,191 @@ cmd_emer_reset(struct ctl_context *ctx)
>      vsctl_context_invalidate_cache(ctx);
>  }
>
> +static struct ovsrec_datapath *
> +find_datapath(struct vsctl_context *vsctl_ctx, const char *dp_name)
> +{
> +    const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs;
> +    int i;
>

remove



> +
> +    for (i = 0; i < ovs->n_datapaths; i++) {
>

+    for (int i = 0; i < ovs->n_datapaths; i++) {


> +        if (!strcmp(ovs->key_datapaths[i], dp_name)) {
> +            return ovs->value_datapaths[i];
> +        }
> +    }
> +    return NULL;
> +}
> +
> +static struct ovsrec_ct_zone *
> +find_ct_zone(struct ovsrec_datapath *dp, const int64_t zone_id)
> +{
> +    int i;
>

remove


> +
> +    for (i = 0; i < dp->n_ct_zones; i++) {


+    for (int i = 0; i < dp->n_ct_zones; i++) {


> +        if (dp->key_ct_zones[i] == zone_id) {
> +            return dp->value_ct_zones[i];
> +        }
> +    }
> +    return NULL;
> +}
> +
> +static struct ovsrec_ct_timeout_policy *
> +create_timeout_policy(struct ctl_context *ctx, char **argv, int n_tps)
>

recommend checking for n_tps of 0 and bailing out early
Could also check in the caller cmd_add_zone_tp().


> +{
> +    const struct ovsrec_ct_timeout_policy_table *tp_table;
> +    const struct ovsrec_ct_timeout_policy *row;
> +    struct ovsrec_ct_timeout_policy *tp = NULL;
>

I think the above 3 declarations could be moved after 'done:' label.

+    struct simap new_tp = SIMAP_INITIALIZER(&new_tp);
> +
> +    char **policies = xzalloc(sizeof *policies * n_tps);
> +    const char **key_timeouts = xmalloc(sizeof *key_timeouts * n_tps);
> +    int64_t *value_timeouts = xmalloc(sizeof *value_timeouts * n_tps);
> +
> +    /* Parse timeout arguments. */
> +    for (int i = 0; i < n_tps; i++) {
> +        policies[i] = xstrdup(argv[i]);
> +
> +        char *key, *value;
> +        char *policy = policies[i];
> +        if (!ofputil_parse_key_value(&policy, &key, &value)) {
> +            goto done;
> +        }
> +        key_timeouts[i] = key;
> +        value_timeouts[i] = atoi(value);
> +        simap_put(&new_tp, key, (unsigned int)value_timeouts[i]);
> +    }
> +
> +done:
> +    tp_table = ovsrec_ct_timeout_policy_table_get(ctx->idl);
> +    OVSREC_CT_TIMEOUT_POLICY_TABLE_FOR_EACH (row, tp_table) {
> +        struct simap s = SIMAP_INITIALIZER(&s);
> +
> +        /* Convert to simap. */
> +        for (int i = 0; i < row->n_timeouts; i++) {
> +            simap_put(&s, row->key_timeouts[i], row->value_timeouts[i]);
> +        }
> +
> +        if (simap_equal(&s, &new_tp)) {
> +            tp = CONST_CAST(struct ovsrec_ct_timeout_policy *, row);
> +            simap_destroy(&s);
> +            break;
> +        }
> +        simap_destroy(&s);
> +    }
> +
> +    if (!tp) {
> +        tp = ovsrec_ct_timeout_policy_insert(ctx->txn);
> +        ovsrec_ct_timeout_policy_set_timeouts(tp, key_timeouts,
> +                                              (const int64_t
> *)value_timeouts,
> +                                              n_tps);
> +    }
> +
> +    for (int i = 0; i < n_tps; i++) {
> +        free(policies[i]);
> +    }
> +    free(policies);
> +    simap_destroy(&new_tp);
> +    free(key_timeouts);
> +    free(value_timeouts);
> +    return tp;
> +}
> +
> +static void
> +cmd_add_zone_tp(struct ctl_context *ctx)
> +{
> +    struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
> +    struct ovsrec_ct_timeout_policy *tp;
> +    int64_t zone_id;
> +
> +    const char *dp_name = ctx->argv[1];
> +    ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id);
> +    bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
> +
> +    struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name);
> +    if (!dp) {
> +        ctl_fatal("datapath %s does not exist", dp_name);
> +    }
> +
> +    int n_tps = ctx->argc - 3;
> +    struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id);
> +
> +    if (zone && !may_exist) {
> +        ctl_fatal("zone id %"PRIu64" already exists", zone_id);
> +    }
> +
> +    tp = create_timeout_policy(ctx, &ctx->argv[3], n_tps);
> +    if (zone) {
> +        ovsrec_ct_zone_set_timeout_policy(zone, tp);
> +    } else {
> +        zone = ovsrec_ct_zone_insert(ctx->txn);
> +        ovsrec_ct_zone_set_timeout_policy(zone, tp);
> +        ovsrec_datapath_update_ct_zones_setkey(dp, zone_id, zone);
> +    }
> +}
> +
> +static void
> +cmd_del_zone_tp(struct ctl_context *ctx)
> +{
> +    struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
> +    int64_t zone_id;
> +
> +    bool must_exist = !shash_find(&ctx->options, "--if-exists");
> +    const char *dp_name = ctx->argv[1];
> +    ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id);
> +
> +    struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name);
> +    if (!dp) {
> +        ctl_fatal("datapath %s does not exist", dp_name);
> +    }
> +
> +    struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id);
> +    if (must_exist && !zone) {
> +        ctl_fatal("zone id %"PRIu64" does not exist", zone_id);
> +    }
> +
> +    if (zone) {
> +        ovsrec_datapath_update_ct_zones_delkey(dp, zone_id);
> +    }
> +}
> +
> +static void
> +cmd_list_zone_tp(struct ctl_context *ctx)
> +{
> +    struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
> +
> +    struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, ctx->argv[1]);
> +    if (!dp) {
> +        ctl_fatal("datapath: %s record not found", ctx->argv[1]);
> +    }
> +
> +    for (int i = 0; i < dp->n_ct_zones; i++) {
> +        struct ovsrec_ct_zone *zone = dp->value_ct_zones[i];
> +        ds_put_format(&ctx->output, "Zone:%"PRIu64", Timeout Policies: ",
> +                      dp->key_ct_zones[i]);
> +
> +        struct ovsrec_ct_timeout_policy *tp = zone->timeout_policy;
> +
> +        int j;
>
remove



> +        for (j = 0; j < tp->n_timeouts; j++) {
>


move into for loop
+        for (int j = 0; j < tp->n_timeouts; j++) {


> +            if (j == tp->n_timeouts - 1) {
> +                ds_put_format(&ctx->output, "%s=%"PRIu64"\n",
> +                          tp->key_timeouts[j], tp->value_timeouts[j]);
> +            } else {
> +                ds_put_format(&ctx->output, "%s=%"PRIu64" ",
> +                          tp->key_timeouts[j], tp->value_timeouts[j]);
> +            }
> +        }
> +    }
> +}
> +
> +static void
> +pre_get_zone(struct ctl_context *ctx)
> +{
> +    ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_datapaths);
> +    ovsdb_idl_add_column(ctx->idl, &ovsrec_datapath_col_ct_zones);
> +    ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_zone_col_timeout_policy);
> +    ovsdb_idl_add_column(ctx->idl,
> &ovsrec_ct_timeout_policy_col_timeouts);
> +}
> +
>  static void
>  cmd_add_br(struct ctl_context *ctx)
>  {
> @@ -2896,6 +3083,13 @@ static const struct ctl_command_syntax
> vsctl_commands[] = {
>      /* Switch commands. */
>      {"emer-reset", 0, 0, "", pre_cmd_emer_reset, cmd_emer_reset, NULL,
> "", RW},
>
> +    /* Zone and CT Timeout Policy commands. */
> +    {"add-zone-tp", 2, 19, "", pre_get_zone, cmd_add_zone_tp, NULL,
>

s/19/18/ ?


> +     "--may-exist", RW},
> +    {"del-zone-tp", 2, 2, "", pre_get_zone, cmd_del_zone_tp, NULL,
> +     "--if-exists", RW},
> +    {"list-zone-tp", 1, 1, "", pre_get_zone, cmd_list_zone_tp, NULL, "",
> RO},
> +
>      {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
>  };
>
> --
> 2.7.4
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list