From patchwork Mon Jul 30 06:46:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Justin Pettit X-Patchwork-Id: 950723 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41f9BX3dHcz9ryt for ; Mon, 30 Jul 2018 16:48:20 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C07CCBBF; Mon, 30 Jul 2018 06:46:55 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 527ED720 for ; Mon, 30 Jul 2018 06:46:54 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 53C256A2 for ; Mon, 30 Jul 2018 06:46:52 +0000 (UTC) X-Originating-IP: 76.21.1.228 Received: from localhost.localdomain (unknown [76.21.1.228]) (Authenticated sender: jpettit@ovn.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 1DDC61BF20B for ; Mon, 30 Jul 2018 06:46:49 +0000 (UTC) From: Justin Pettit To: dev@openvswitch.org Date: Sun, 29 Jul 2018 23:46:35 -0700 Message-Id: <20180730064638.121021-4-jpettit@ovn.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180730064638.121021-1-jpettit@ovn.org> References: <20180730064638.121021-1-jpettit@ovn.org> X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [ACL Meters 4/7] ovn: Add Meter and Meter_Band tables to the NB and SB databases. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Add support for configuring meters through the Meter and Meter_Band tables in the Northbound database. This commit also has ovn-northd sync those tables between the Northbound and Southbound databases. Add support for configuring meters with ovn-nbctl. Signed-off-by: Justin Pettit Acked-by: Ben Pfaff --- ovn/northd/ovn-northd.c | 145 ++++++++++++++++++++++++++++++++++ ovn/ovn-nb.ovsschema | 33 +++++++- ovn/ovn-nb.xml | 80 +++++++++++++++++++ ovn/ovn-sb.ovsschema | 27 ++++++- ovn/ovn-sb.xml | 72 +++++++++++++++++ ovn/utilities/ovn-nbctl.8.xml | 50 ++++++++++++ ovn/utilities/ovn-nbctl.c | 143 +++++++++++++++++++++++++++++++++ tests/ovn-nbctl.at | 58 ++++++++++++++ 8 files changed, 604 insertions(+), 4 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 04a072ba8de7..45557170edc8 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -6606,6 +6606,140 @@ sync_port_groups(struct northd_context *ctx) shash_destroy(&sb_port_groups); } +struct band_entry { + int64_t rate; + int64_t burst_size; + const char *action; +}; + +static int +band_cmp(const void *band1_, const void *band2_) +{ + const struct band_entry *band1p = band1_; + const struct band_entry *band2p = band2_; + + if (band1p->rate != band2p->rate) { + return band1p->rate > band2p->rate ? -1 : 1; + } else if (band1p->burst_size != band2p->burst_size) { + return band1p->burst_size > band2p->burst_size ? -1 : 1; + } else { + return strcmp(band1p->action, band2p->action); + } +} + +static bool +bands_need_update(const struct nbrec_meter *nb_meter, + const struct sbrec_meter *sb_meter) +{ + if (nb_meter->n_bands != sb_meter->n_bands) { + return true; + } + + /* A single band is the most common scenario, so speed up that + * check. */ + if (nb_meter->n_bands == 1) { + struct nbrec_meter_band *nb_band = nb_meter->bands[0]; + struct sbrec_meter_band *sb_band = sb_meter->bands[0]; + + return !(nb_band->rate == sb_band->rate + && nb_band->burst_size == sb_band->burst_size + && !strcmp(sb_band->action, nb_band->action)); + } + + /* Place the Northbound entries in sorted order. */ + struct band_entry *nb_bands; + nb_bands = xmalloc(sizeof *nb_bands * nb_meter->n_bands); + for (size_t i = 0; i < nb_meter->n_bands; i++) { + struct nbrec_meter_band *nb_band = nb_meter->bands[i]; + + nb_bands[i].rate = nb_band->rate; + nb_bands[i].burst_size = nb_band->burst_size; + nb_bands[i].action = nb_band->action; + } + qsort(nb_bands, nb_meter->n_bands, sizeof *nb_bands, band_cmp); + + /* Place the Southbound entries in sorted order. */ + struct band_entry *sb_bands; + sb_bands = xmalloc(sizeof *sb_bands * sb_meter->n_bands); + for (size_t i = 0; i < sb_meter->n_bands; i++) { + struct sbrec_meter_band *sb_band = sb_meter->bands[i]; + + sb_bands[i].rate = sb_band->rate; + sb_bands[i].burst_size = sb_band->burst_size; + sb_bands[i].action = sb_band->action; + } + qsort(sb_bands, sb_meter->n_bands, sizeof *sb_bands, band_cmp); + + bool need_update = false; + for (size_t i = 0; i < nb_meter->n_bands; i++) { + if (nb_bands[i].rate != sb_bands[i].rate + || nb_bands[i].burst_size != sb_bands[i].burst_size + || strcmp(nb_bands[i].action, nb_bands[i].action)) { + need_update = true; + goto done; + } + } + +done: + free(nb_bands); + free(sb_bands); + + return need_update; +} + +/* Each entry in the Meter and Meter_Band tables in OVN_Northbound have + * a corresponding entries in the Meter and Meter_Band tables in + * OVN_Southbound. + */ +static void +sync_meters(struct northd_context *ctx) +{ + struct shash sb_meters = SHASH_INITIALIZER(&sb_meters); + + const struct sbrec_meter *sb_meter; + SBREC_METER_FOR_EACH (sb_meter, ctx->ovnsb_idl) { + shash_add(&sb_meters, sb_meter->name, sb_meter); + } + + const struct nbrec_meter *nb_meter; + NBREC_METER_FOR_EACH (nb_meter, ctx->ovnnb_idl) { + bool new_sb_meter = false; + + sb_meter = shash_find_and_delete(&sb_meters, nb_meter->name); + if (!sb_meter) { + sb_meter = sbrec_meter_insert(ctx->ovnsb_txn); + sbrec_meter_set_name(sb_meter, nb_meter->name); + new_sb_meter = true; + } + + if (new_sb_meter || bands_need_update(nb_meter, sb_meter)) { + struct sbrec_meter_band **sb_bands; + sb_bands = xcalloc(nb_meter->n_bands, sizeof *sb_bands); + for (size_t i = 0; i < nb_meter->n_bands; i++) { + const struct nbrec_meter_band *nb_band = nb_meter->bands[i]; + + sb_bands[i] = sbrec_meter_band_insert(ctx->ovnsb_txn); + + sbrec_meter_band_set_action(sb_bands[i], nb_band->action); + sbrec_meter_band_set_rate(sb_bands[i], nb_band->rate); + sbrec_meter_band_set_burst_size(sb_bands[i], + nb_band->burst_size); + } + sbrec_meter_set_bands(sb_meter, sb_bands, nb_meter->n_bands); + free(sb_bands); + } + + sbrec_meter_set_unit(sb_meter, nb_meter->unit); + } + + struct shash_node *node, *next; + SHASH_FOR_EACH_SAFE (node, next, &sb_meters) { + sbrec_meter_delete(node->data); + shash_delete(&sb_meters, node); + } + shash_destroy(&sb_meters); +} + /* * struct 'dns_info' is used to sync the DNS records between OVN Northbound db * and Southbound db. @@ -6726,6 +6860,7 @@ ovnnb_db_run(struct northd_context *ctx, sync_address_sets(ctx); sync_port_groups(ctx); + sync_meters(ctx); sync_dns_entries(ctx, &datapaths); struct ovn_port_group *pg, *next_pg; @@ -7351,6 +7486,16 @@ main(int argc, char *argv[]) &sbrec_rbac_permission_col_insert_delete); add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_permission_col_update); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_name); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_unit); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_bands); + + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter_band); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_action); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_rate); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_burst_size); + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name); diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema index 8e6ddec4662f..9a0d8ec70514 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.11.0", - "cksum": "1149260021 18713", + "version": "5.12.0", + "cksum": "2812995200 20238", "tables": { "NB_Global": { "columns": { @@ -195,6 +195,35 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "isRoot": false}, + "Meter": { + "columns": { + "name": {"type": "string"}, + "unit": {"type": {"key": {"type": "string", + "enum": ["set", ["kbps", "pktps"]]}}}, + "bands": {"type": {"key": {"type": "uuid", + "refTable": "Meter_Band", + "refType": "strong"}, + "min": 1, + "max": "unlimited"}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "indexes": [["name"]], + "isRoot": true}, + "Meter_Band": { + "columns": { + "action": {"type": {"key": {"type": "string", + "enum": ["set", ["drop"]]}}}, + "rate": {"type": {"key": {"type": "integer", + "minInteger": 1, + "maxInteger": 4294967295}}}, + "burst_size": {"type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 4294967295}}}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "isRoot": false}, "Logical_Router": { "columns": { "name": {"type": "string"}, diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index e4e72b27cf36..1feb2af52027 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -1356,6 +1356,86 @@ + +

+ Each row in this table represents a meter that can be used for QoS or + rate-limiting. +

+ + +

+ A name for this meter. +

+ +

+ Names that begin with "__" are reserved for OVN internal use and should + not be added manually. +

+
+ + +

+ The unit for and + parameters in + the entry. kbps specifies + kilobits per second, and pktps specifies packets + per second. +

+
+ + +

+ The bands associated with this meter. Each band specifies a + rate above which the band is to take the action + action. If multiple bands' rates are exceeded, + then the band with the highest rate among the exceeded bands is + selected. +

+
+ + + See External IDs at the beginning of this document. + +
+ + +

+ Each row in this table represents a meter band which specifies the + rate above which the configured action should be applied. These bands + are referenced by the column in + the table. +

+ + +

+ The action to execute when this band matches. The only supported + action is drop. +

+
+ + +

+ The relative rate limit for this band, in kilobits per second or + bits per second, depending on whether the parent + entry's column specified + kbps or pktps. +

+
+ + +

+ The maximum burst allowed for the band in kilobits or packets, + depending on whether kbps or pktps was + selected in the parent entry's + column. +

+
+ + + See External IDs at the beginning of this document. + +
+

A port within an L3 logical router. diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema index 9e271d433246..ad6ad3b71da0 100644 --- a/ovn/ovn-sb.ovsschema +++ b/ovn/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "1.15.0", - "cksum": "1839738004 13639", + "version": "1.16.0", + "cksum": "3046632234 14844", "tables": { "SB_Global": { "columns": { @@ -98,6 +98,29 @@ "indexes": [["datapath", "tunnel_key"], ["datapath", "name"]], "isRoot": true}, + "Meter": { + "columns": { + "name": {"type": "string"}, + "unit": {"type": {"key": {"type": "string", + "enum": ["set", ["kbps", "pktps"]]}}}, + "bands": {"type": {"key": {"type": "uuid", + "refTable": "Meter_Band", + "refType": "strong"}, + "min": 1, + "max": "unlimited"}}}, + "indexes": [["name"]], + "isRoot": true}, + "Meter_Band": { + "columns": { + "action": {"type": {"key": {"type": "string", + "enum": ["set", ["drop"]]}}}, + "rate": {"type": {"key": {"type": "integer", + "minInteger": 1, + "maxInteger": 4294967295}}}, + "burst_size": {"type": {"key": {"type": "integer", + "minInteger": 0, + "maxInteger": 4294967295}}}}, + "isRoot": false}, "Datapath_Binding": { "columns": { "tunnel_key": { diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index f9724d398ce6..57d8a9e042a5 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -1923,6 +1923,78 @@ tcp.flags = RST;

+ +

+ Each row in this table represents a meter that can be used for QoS or + rate-limiting. +

+ + +

+ A name for this meter. +

+ +

+ Names that begin with "__" are reserved for OVN internal use and should + not be added manually. +

+
+ + +

+ The unit for and + parameters in + the entry. kbps specifies + kilobits per second, and pktps specifies packets + per second. +

+
+ + +

+ The bands associated with this meter. Each band specifies a + rate above which the band is to take the action + action. If multiple bands' rates are exceeded, + then the band with the highest rate among the exceeded bands is + selected. +

+
+
+ + +

+ Each row in this table represents a meter band which specifies the + rate above which the configured action should be applied. These bands + are referenced by the column in + the table. +

+ + +

+ The action to execute when this band matches. The only supported + action is drop. +

+
+ + +

+ The relative rate limit for this band, in kilobits per second or + bits per second, depending on whether the parent + entry's column specified + kbps or pktps. +

+
+ + +

+ The maximum burst allowed for the band in kilobits or packets, + depending on whether kbps or pktps was + selected in the parent entry's + column. +

+
+
+

Each row in this table represents a logical datapath, which implements a diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index 2cd2fab304cd..a8ea7d8cb1e1 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -172,6 +172,56 @@ +

Meter Commands

+
+
meter-add name unit action rate [burst_size]
+
+

+ Adds the specified meter. name must be a unique + name to identify this meter. The action argument + specifies what should happen when this meter is exceeded. + The only supported action is drop. +

+ +

+ The unit specifies the unit for the rate + argument; valid values are kbps and + pktps for kilobits per second and packets per + second, respectively. The burst_rate option + configures the maximum burst allowed for the band in kilobits + or packets depending on whether the unit chosen was + kbps or pktps, respectively. +

+ +

+ ovn-nbctl only supports adding a meter with a + single band, but the other commands support meters with + multiple bands. +

+ +

+ Names that start with "__" are reserved for internal use by OVN, + so ovn-nbctl does not allow adding them. +

+
+ +
meter-del [name]
+
+

+ Deletes meters. By default, all meters are deleted. If + name is supplied, only the meter with that name + will be deleted. +

+
+ +
meter-list
+
+

+ Lists all meters. +

+
+
+

Logical Switch Port Commands

[--may-exist] lsp-add switch port
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 3c3e582cb906..9f0e6347c104 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -496,6 +496,12 @@ QoS commands:\n\ remove QoS rules from SWITCH\n\ qos-list SWITCH print QoS rules for SWITCH\n\ \n\ +Meter commands:\n\ + meter-add NAME UNIT ACTION RATE [BURST_SIZE]\n\ + add a meter\n\ + meter-del [NAME] remove meters\n\ + meter-list print meters\n\ +\n\ Logical switch port commands:\n\ lsp-add SWITCH PORT add logical port PORT on SWITCH\n\ lsp-add SWITCH PORT PARENT TAG\n\ @@ -2290,6 +2296,137 @@ nbctl_qos_del(struct ctl_context *ctx) } } +static int +meter_cmp(const void *meter1_, const void *meter2_) +{ + struct nbrec_meter *const *meter1p = meter1_; + struct nbrec_meter *const *meter2p = meter2_; + const struct nbrec_meter *meter1 = *meter1p; + const struct nbrec_meter *meter2 = *meter2p; + + return strcmp(meter1->name, meter2->name); +} + +static void +nbctl_meter_list(struct ctl_context *ctx) +{ + const struct nbrec_meter **meters = NULL; + const struct nbrec_meter *meter; + size_t n_capacity = 0; + size_t n_meters = 0; + + NBREC_METER_FOR_EACH (meter, ctx->idl) { + if (n_meters == n_capacity) { + meters = x2nrealloc(meters, &n_capacity, sizeof *meters); + } + + meters[n_meters] = meter; + n_meters++; + } + + if (n_meters) { + qsort(meters, n_meters, sizeof *meters, meter_cmp); + } + + for (size_t i = 0; i < n_meters; i++) { + meter = meters[i]; + ds_put_format(&ctx->output, "%s: unit=%s bands:\n", meter->name, + meter->unit); + + for (size_t j = 0; j < meter->n_bands; j++) { + const struct nbrec_meter_band *band = meter->bands[j]; + + ds_put_format(&ctx->output, " %s: rate=%"PRId64"", + band->action, band->rate); + if (band->burst_size) { + ds_put_format(&ctx->output, ", burst_size=%"PRId64"", + band->burst_size); + } + } + + ds_put_cstr(&ctx->output, "\n"); + } + + free(meters); +} + +static void +nbctl_meter_add(struct ctl_context *ctx) +{ + const struct nbrec_meter *meter; + + const char *name = ctx->argv[1]; + NBREC_METER_FOR_EACH (meter, ctx->idl) { + if (!strcmp(meter->name, name)) { + ctl_fatal("meter with name \"%s\" already exists", name); + } + } + + if (!strncmp(name, "__", 2)) { + ctl_fatal("meter names that begin with \"__\" are reserved"); + } + + const char *unit = ctx->argv[2]; + if (strcmp(unit, "kbps") && strcmp(unit, "pktps")) { + ctl_fatal("unit must be \"kbps\" or \"pktps\""); + } + + const char *action = ctx->argv[3]; + if (strcmp(action, "drop")) { + ctl_fatal("action must be \"drop\""); + } + + int64_t rate; + if (!ovs_scan(ctx->argv[4], "%"SCNd64, &rate) + || rate < 1 || rate > UINT32_MAX) { + ctl_fatal("rate must be in the range 1...4294967295"); + } + + int64_t burst_size = 0; + if (ctx->argc > 5) { + if (!ovs_scan(ctx->argv[5], "%"SCNd64, &burst_size) + || burst_size < 0 || burst_size > UINT32_MAX) { + ctl_fatal("burst_size must be in the range 0...4294967295"); + } + } + + /* Create the band. We only support adding a single band. */ + struct nbrec_meter_band *band = nbrec_meter_band_insert(ctx->txn); + nbrec_meter_band_set_action(band, action); + nbrec_meter_band_set_rate(band, rate); + nbrec_meter_band_set_burst_size(band, burst_size); + + /* Create the meter. */ + meter = nbrec_meter_insert(ctx->txn); + nbrec_meter_set_name(meter, name); + nbrec_meter_set_unit(meter, unit); + nbrec_meter_set_bands(meter, &band, 1); +} + +static void +nbctl_meter_del(struct ctl_context *ctx) +{ + const struct nbrec_meter *meter, *next; + + /* If a name is not specified, delete all meters. */ + if (ctx->argc == 1) { + NBREC_METER_FOR_EACH_SAFE (meter, next, ctx->idl) { + nbrec_meter_delete(meter); + } + return; + } + + /* Remove the matching meter. */ + NBREC_METER_FOR_EACH (meter, ctx->idl) { + if (strcmp(ctx->argv[1], meter->name)) { + continue; + } + + nbrec_meter_delete(meter); + return; + } +} + static void nbctl_lb_add(struct ctl_context *ctx) { @@ -4678,6 +4815,12 @@ static const struct ctl_command_syntax nbctl_commands[] = { nbctl_qos_del, NULL, "", RW }, { "qos-list", 1, 1, "SWITCH", NULL, nbctl_qos_list, NULL, "", RO }, + /* meter commands. */ + { "meter-add", 4, 5, "NAME UNIT ACTION RATE [BURST_SIZE]", NULL, + nbctl_meter_add, NULL, "", RW }, + { "meter-del", 0, 1, "[NAME]", NULL, nbctl_meter_del, NULL, "", RW }, + { "meter-list", 0, 0, "", NULL, nbctl_meter_list, NULL, "", RO }, + /* logical switch port commands. */ { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add, NULL, "--may-exist", RW }, diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 64e217654c2f..7a1445e312ff 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -323,6 +323,64 @@ OVN_NBCTL_TEST_STOP AT_CLEANUP dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - Meters]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl meter-add meter1 kbps drop 10]) +AT_CHECK([ovn-nbctl meter-add meter2 kbps drop 3 2]) +AT_CHECK([ovn-nbctl meter-add meter3 kbps drop 100 200]) + +dnl Add duplicate meter name +AT_CHECK([ovn-nbctl meter-add meter1 kbps drop 10], [1], [], [stderr]) +AT_CHECK([grep 'already exists' stderr], [0], [ignore]) + +dnl Add reserved meter name +AT_CHECK([ovn-nbctl meter-add __meter1 kbps drop 10], [1], [], [stderr]) +AT_CHECK([grep 'reserved' stderr], [0], [ignore]) + +dnl Add meter with invalid rates +AT_CHECK([ovn-nbctl meter-add meter4 kbps drop 100010111111], [1], [], +[ovn-nbctl: rate must be in the range 1...4294967295 +]) + +AT_CHECK([ovn-nbctl meter-add meter4 kbps drop 0], [1], [], +[ovn-nbctl: rate must be in the range 1...4294967295 +]) + +dnl Add meter with invalid burst_size +AT_CHECK([ovn-nbctl meter-add meter4 kbps drop 10 100010111111], [1], [], +[ovn-nbctl: burst_size must be in the range 0...4294967295 +]) + +AT_CHECK([ovn-nbctl meter-list], [0], [dnl +meter1: unit=kbps bands: + drop: rate=10 +meter2: unit=kbps bands: + drop: rate=3, burst_size=2 +meter3: unit=kbps bands: + drop: rate=100, burst_size=200 +]) + +dnl Delete a single meter. +AT_CHECK([ovn-nbctl meter-del meter2]) +AT_CHECK([ovn-nbctl meter-list], [0], [dnl +meter1: unit=kbps bands: + drop: rate=10 +meter3: unit=kbps bands: + drop: rate=100, burst_size=200 +]) + +dnl Delete all meters. +AT_CHECK([ovn-nbctl meter-del]) +AT_CHECK([ovn-nbctl meter-list], [0], [dnl +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + AT_SETUP([ovn-nbctl - NATs]) OVN_NBCTL_TEST_START AT_CHECK([ovn-nbctl lr-add lr0])