[ovs-dev] [RFC 2/2] OVN: northd: add rate limiting support for SB controller events
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Tue Jul 30 13:37:37 UTC 2019
Introduce the capability to associate a meter to each controller event
type in order to not overload the pinctrl thread under heavy load.
Each event type relies on a meter with a defined name:
- empty_lb_backends: event-elb
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
ovn/northd/ovn-northd.c | 44 ++++++++++++++++++++++++++++++++---------
ovn/ovn-nb.xml | 8 ++++++++
tests/ovn.at | 1 +
3 files changed, 44 insertions(+), 9 deletions(-)
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index eb6c47cad..7af1471b1 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -3876,7 +3876,8 @@ ls_has_dns_records(const struct nbrec_logical_switch *nbs)
}
static void
-build_pre_lb(struct ovn_datapath *od, struct hmap *lflows)
+build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
+ struct shash *meter_groups)
{
/* Do not send ND packets to conntrack */
ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_LB, 110,
@@ -3914,7 +3915,11 @@ build_pre_lb(struct ovn_datapath *od, struct hmap *lflows)
if (controller_event_en && !node->value[0]) {
struct ds match = DS_EMPTY_INITIALIZER;
- char *action;
+ char *meter = "", *action;
+
+ if (shash_find(meter_groups, "event-elb")) {
+ meter = "event-elb";
+ }
if (addr_family == AF_INET) {
ds_put_format(&match, "ip4.dst == %s && %s",
@@ -3928,10 +3933,11 @@ build_pre_lb(struct ovn_datapath *od, struct hmap *lflows)
port);
}
action = xasprintf("trigger_event(event = \"%s\", "
- "vip = \"%s\", protocol = \"%s\", "
+ "meter = \"%s\", vip = \"%s\", "
+ "protocol = \"%s\", "
"load_balancer = \"" UUID_FMT "\");",
event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
- node->key, lb->protocol,
+ meter, node->key, lb->protocol,
UUID_ARGS(&lb->header_.uuid));
ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_LB, 120,
ds_cstr(&match), action);
@@ -4758,7 +4764,8 @@ build_lrouter_groups(struct hmap *ports, struct ovs_list *lr_list)
static void
build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
struct hmap *port_groups, struct hmap *lflows,
- struct hmap *mcgroups, struct hmap *igmp_groups)
+ struct hmap *mcgroups, struct hmap *igmp_groups,
+ struct shash *meter_groups)
{
/* This flow table structure is documented in ovn-northd(8), so please
* update ovn-northd.8.xml if you change anything. */
@@ -4775,7 +4782,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
build_pre_acls(od, lflows);
- build_pre_lb(od, lflows);
+ build_pre_lb(od, lflows, meter_groups);
build_pre_stateful(od, lflows);
build_acls(od, lflows, port_groups);
build_qos(od, lflows);
@@ -7880,12 +7887,13 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
static void
build_lflows(struct northd_context *ctx, struct hmap *datapaths,
struct hmap *ports, struct hmap *port_groups,
- struct hmap *mcgroups, struct hmap *igmp_groups)
+ struct hmap *mcgroups, struct hmap *igmp_groups,
+ struct shash *meter_groups)
{
struct hmap lflows = HMAP_INITIALIZER(&lflows);
build_lswitch_flows(datapaths, ports, port_groups, &lflows, mcgroups,
- igmp_groups);
+ igmp_groups, meter_groups);
build_lrouter_flows(datapaths, ports, &lflows);
/* Push changes to the Logical_Flow table to database. */
@@ -8498,6 +8506,16 @@ build_mcast_groups(struct northd_context *ctx,
}
}
+static void
+build_meter_groups(struct northd_context *ctx,
+ struct shash *meter_groups)
+{
+ const struct nbrec_meter *nb_meter;
+ NBREC_METER_FOR_EACH (nb_meter, ctx->ovnnb_idl) {
+ shash_add(meter_groups, nb_meter->name, nb_meter);
+ }
+}
+
static void
ovnnb_db_run(struct northd_context *ctx,
struct ovsdb_idl_index *sbrec_chassis_by_name,
@@ -8511,6 +8529,7 @@ ovnnb_db_run(struct northd_context *ctx,
struct hmap port_groups;
struct hmap mcast_groups;
struct hmap igmp_groups;
+ struct shash meter_groups = SHASH_INITIALIZER(&meter_groups);
build_datapaths(ctx, datapaths, lr_list);
build_ports(ctx, sbrec_chassis_by_name, datapaths, ports);
@@ -8519,8 +8538,9 @@ ovnnb_db_run(struct northd_context *ctx,
build_lrouter_groups(ports, lr_list);
build_ip_mcast(ctx, datapaths);
build_mcast_groups(ctx, datapaths, ports, &mcast_groups, &igmp_groups);
+ build_meter_groups(ctx, &meter_groups);
build_lflows(ctx, datapaths, ports, &port_groups, &mcast_groups,
- &igmp_groups);
+ &igmp_groups, &meter_groups);
sync_address_sets(ctx);
sync_port_groups(ctx);
@@ -8541,6 +8561,12 @@ ovnnb_db_run(struct northd_context *ctx,
hmap_destroy(&mcast_groups);
hmap_destroy(&port_groups);
+ struct shash_node *node, *next;
+ SHASH_FOR_EACH_SAFE (node, next, &meter_groups) {
+ shash_delete(&meter_groups, node);
+ }
+ shash_destroy(&meter_groups);
+
/* Sync ipsec configuration.
* Copy nb_cfg from northbound to southbound database.
* Also set up to update sb_cfg once our southbound transaction commits. */
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 57b6edbf8..53f267ab6 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -117,6 +117,14 @@
<ref table="Controller_Event"/> table.
The intention is for a CMS to see the events and take some sort of
action. Please see the <ref table="Controller_Event"/> table in SBDB.
+ It is possible to associate a meter to each controller event type
+ in order to not overload the pinctrl thread under heavy load.
+ Each event type relies on a meter with a defined name:
+
+ <ul>
+ <li>empty_lb_backends: event-elb</li>
+ </ul>
+
</column>
</group>
diff --git a/tests/ovn.at b/tests/ovn.at
index cb380d275..176b43a4c 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -14399,6 +14399,7 @@ ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
ovn-nbctl lb-add lb0 192.168.1.100:80 ""
ovn-nbctl ls-lb-add sw0 lb0
uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer name=lb0)
+ovn-nbctl --wait=hv meter-add event-elb drop 100 pktps 10
OVN_POPULATE_ARP
ovn-nbctl --timeout=3 --wait=hv sync
--
2.21.0
More information about the dev
mailing list