Skip to content

Commit

Permalink
ovn: Add Meter and Meter_Band tables to the NB and SB databases.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
justinpettit committed Jul 31, 2018
1 parent 441fef6 commit 185b13f
Show file tree
Hide file tree
Showing 8 changed files with 622 additions and 5 deletions.
145 changes: 145 additions & 0 deletions ovn/northd/ovn-northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
33 changes: 31 additions & 2 deletions ovn/ovn-nb.ovsschema
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down Expand Up @@ -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"},
Expand Down
84 changes: 83 additions & 1 deletion ovn/ovn-nb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@
</group>
</table>

<table name="QoS" title="QoS table">
<table name="QoS" title="QoS rule">
<p>
Each row in this table represents one QoS rule for a logical switch
that points to it through its <ref column="qos_rules"/> column.
Expand Down Expand Up @@ -1356,6 +1356,88 @@
</column>
</table>

<table name="Meter" title="Meter entry">
<p>
Each row in this table represents a meter that can be used for QoS or
rate-limiting.
</p>

<column name="name">
<p>
A name for this meter.
</p>

<p>
Names that begin with "__" (two underscores) are reserved for
OVN internal use and should not be added manually.
</p>
</column>

<column name="unit">
<p>
The unit for <ref column="rate" table="Meter_Band"/> and
<ref column="burst_rate" table="Meter_Band"/> parameters in
the <ref column="bands"/> entry. <code>kbps</code> specifies
kilobits per second, and <code>pktps</code> specifies packets
per second.
</p>
</column>

<column name="bands">
<p>
The bands associated with this meter. Each band specifies a
rate above which the band is to take the action
<code>action</code>. If multiple bands' rates are exceeded,
then the band with the highest rate among the exceeded bands is
selected.
</p>
</column>

<column name="external_ids">
See <em>External IDs</em> at the beginning of this document.
</column>
</table>

<table name="Meter_Band" title="Band for meter entries">
<p>
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 <ref column="bands" table="Meter"/> column in
the <ref table="Meter"/> table.
</p>

<column name="action">
<p>
The action to execute when this band matches. The only supported
action is <code>drop</code>.
</p>
</column>

<column name="rate">
<p>
The rate limit for this band, in kilobits per second or bits per
second, depending on whether the parent <ref table="Meter"/>
entry's <ref column="unit" table="Meter"/> column specified
<code>kbps</code> or <code>pktps</code>.
</p>
</column>

<column name="burst_size">
<p>
The maximum burst allowed for the band in kilobits or packets,
depending on whether <code>kbps</code> or <code>pktps</code> was
selected in the parent <ref table="Meter"/> entry's
<ref column="unit" table="Meter"/> column. If the size is zero,
the switch is free to select some reasonable value depending on
its configuration.
</p>
</column>

<column name="external_ids">
See <em>External IDs</em> at the beginning of this document.
</column>
</table>

<table name="Logical_Router_Port" title="L3 logical router port">
<p>
A port within an L3 logical router.
Expand Down
27 changes: 25 additions & 2 deletions ovn/ovn-sb.ovsschema
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down Expand Up @@ -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": {
Expand Down
Loading

0 comments on commit 185b13f

Please sign in to comment.