Add a new OVS external-id, "ovn-limit-lflow-cache", through which users
can specify the maximum size of the ovn-controller logical flow cache.

To maintain backwards compatibility the default behavior is to not
enforce any limit on the size of the cache.

Signed-off-by: Dumitru Ceara <[email protected]>
---
 NEWS                            |    3 +++
 controller/chassis.c            |   23 ++++++++++++++++++++++-
 controller/lflow-cache.c        |   25 +++++++++++++++++++++++--
 controller/lflow-cache.h        |    2 +-
 controller/ovn-controller.8.xml |   16 ++++++++++++++++
 controller/ovn-controller.c     |    8 +++++++-
 6 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index d4619dd..68c9a8e 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,9 @@ Post-v20.12.0
   - ovn-ctl: Added new command line argument '--ovsdb-disable-file-column-diff'
     to support ovsdb-server upgrades from version 2.14 and earlier to
     2.15 and later.  See ovsdb(7) for more details.
+  - ovn-controller: Add a configuration knob, through OVS external-id
+    "ovn-limit-lflow-cache", to allow enforcing a limit for the size of the
+    logical flow cache.
 
 OVN v20.12.0 - 18 Dec 2020
 --------------------------
diff --git a/controller/chassis.c b/controller/chassis.c
index b4d4b0e..c66837a 100644
--- a/controller/chassis.c
+++ b/controller/chassis.c
@@ -49,6 +49,7 @@ struct ovs_chassis_cfg {
     const char *monitor_all;
     const char *chassis_macs;
     const char *enable_lflow_cache;
+    const char *limit_lflow_cache;
 
     /* Set of encap types parsed from the 'ovn-encap-type' external-id. */
     struct sset encap_type_set;
@@ -135,6 +136,12 @@ get_enable_lflow_cache(const struct smap *ext_ids)
 }
 
 static const char *
+get_limit_lflow_cache(const struct smap *ext_ids)
+{
+    return smap_get_def(ext_ids, "ovn-limit-lflow-cache", "");
+}
+
+static const char *
 get_encap_csum(const struct smap *ext_ids)
 {
     return smap_get_def(ext_ids, "ovn-encap-csum", "true");
@@ -256,6 +263,7 @@ chassis_parse_ovs_config(const struct 
ovsrec_open_vswitch_table *ovs_table,
     ovs_cfg->monitor_all = get_monitor_all(&cfg->external_ids);
     ovs_cfg->chassis_macs = get_chassis_mac_mappings(&cfg->external_ids);
     ovs_cfg->enable_lflow_cache = get_enable_lflow_cache(&cfg->external_ids);
+    ovs_cfg->limit_lflow_cache = get_limit_lflow_cache(&cfg->external_ids);
 
     if (!chassis_parse_ovs_encap_type(encap_type, &ovs_cfg->encap_type_set)) {
         return false;
@@ -283,13 +291,16 @@ chassis_build_other_config(struct smap *config, const 
char *bridge_mappings,
                            const char *datapath_type, const char *cms_options,
                            const char *monitor_all, const char *chassis_macs,
                            const char *iface_types,
-                           const char *enable_lflow_cache, bool is_interconn)
+                           const char *enable_lflow_cache,
+                           const char *limit_lflow_cache,
+                           bool is_interconn)
 {
     smap_replace(config, "ovn-bridge-mappings", bridge_mappings);
     smap_replace(config, "datapath-type", datapath_type);
     smap_replace(config, "ovn-cms-options", cms_options);
     smap_replace(config, "ovn-monitor-all", monitor_all);
     smap_replace(config, "ovn-enable-lflow-cache", enable_lflow_cache);
+    smap_replace(config, "ovn-limit-lflow-cache", limit_lflow_cache);
     smap_replace(config, "iface-types", iface_types);
     smap_replace(config, "ovn-chassis-mac-mappings", chassis_macs);
     smap_replace(config, "is-interconn", is_interconn ? "true" : "false");
@@ -305,6 +316,7 @@ chassis_other_config_changed(const char *bridge_mappings,
                              const char *monitor_all,
                              const char *chassis_macs,
                              const char *enable_lflow_cache,
+                             const char *limit_lflow_cache,
                              const struct ds *iface_types,
                              bool is_interconn,
                              const struct sbrec_chassis *chassis_rec)
@@ -344,6 +356,13 @@ chassis_other_config_changed(const char *bridge_mappings,
         return true;
     }
 
+    const char *chassis_limit_lflow_cache =
+        get_limit_lflow_cache(&chassis_rec->other_config);
+
+    if (strcmp(limit_lflow_cache, chassis_limit_lflow_cache)) {
+        return true;
+    }
+
     const char *chassis_mac_mappings =
         get_chassis_mac_mappings(&chassis_rec->other_config);
     if (strcmp(chassis_macs, chassis_mac_mappings)) {
@@ -523,6 +542,7 @@ chassis_update(const struct sbrec_chassis *chassis_rec,
                                      ovs_cfg->monitor_all,
                                      ovs_cfg->chassis_macs,
                                      ovs_cfg->enable_lflow_cache,
+                                     ovs_cfg->limit_lflow_cache,
                                      &ovs_cfg->iface_types,
                                      ovs_cfg->is_interconn,
                                      chassis_rec)) {
@@ -536,6 +556,7 @@ chassis_update(const struct sbrec_chassis *chassis_rec,
                                    ovs_cfg->chassis_macs,
                                    ds_cstr_ro(&ovs_cfg->iface_types),
                                    ovs_cfg->enable_lflow_cache,
+                                   ovs_cfg->limit_lflow_cache,
                                    ovs_cfg->is_interconn);
         sbrec_chassis_verify_other_config(chassis_rec);
         sbrec_chassis_set_other_config(chassis_rec, &other_config);
diff --git a/controller/lflow-cache.c b/controller/lflow-cache.c
index 4fd7bf4..ee7ea9b 100644
--- a/controller/lflow-cache.c
+++ b/controller/lflow-cache.c
@@ -37,9 +37,11 @@ COVERAGE_DEFINE(lflow_cache_add);
 COVERAGE_DEFINE(lflow_cache_hit);
 COVERAGE_DEFINE(lflow_cache_miss);
 COVERAGE_DEFINE(lflow_cache_delete);
+COVERAGE_DEFINE(lflow_cache_full);
 
 struct lflow_cache {
     struct hmap entries;
+    uint32_t capacity;
     bool enabled;
 };
 
@@ -99,12 +101,14 @@ lflow_cache_destroy(struct lflow_cache *lc)
 }
 
 void
-lflow_cache_enable(struct lflow_cache *lc, bool enabled)
+lflow_cache_enable(struct lflow_cache *lc, bool enabled, uint32_t capacity)
 {
-    if (lc->enabled && !enabled) {
+    if ((lc->enabled && !enabled) || capacity < hmap_count(&lc->entries)) {
         lflow_cache_flush(lc);
     }
+
     lc->enabled = enabled;
+    lc->capacity = capacity;
 }
 
 bool
@@ -121,6 +125,10 @@ lflow_cache_add_conj_id(struct lflow_cache *lc,
     struct lflow_cache_value *lcv =
         lflow_cache_add__(lc, lflow, LCACHE_T_CONJ_ID);
 
+    if (!lcv) {
+        return;
+    }
+
     COVERAGE_INC(lflow_cache_add_conj_id);
     lcv->conj_id_ofs = conj_id_ofs;
 }
@@ -134,6 +142,10 @@ lflow_cache_add_expr(struct lflow_cache *lc,
     struct lflow_cache_value *lcv =
         lflow_cache_add__(lc, lflow, LCACHE_T_EXPR);
 
+    if (!lcv) {
+        return;
+    }
+
     COVERAGE_INC(lflow_cache_add_expr);
     lcv->conj_id_ofs = conj_id_ofs;
     lcv->expr = expr;
@@ -147,6 +159,10 @@ lflow_cache_add_matches(struct lflow_cache *lc,
     struct lflow_cache_value *lcv =
         lflow_cache_add__(lc, lflow, LCACHE_T_MATCHES);
 
+    if (!lcv) {
+        return;
+    }
+
     COVERAGE_INC(lflow_cache_add_matches);
     lcv->expr_matches = matches;
 }
@@ -192,6 +208,11 @@ lflow_cache_add__(struct lflow_cache *lc,
                   const struct sbrec_logical_flow *lflow,
                   enum lflow_cache_type type)
 {
+    if (hmap_count(&lc->entries) == lc->capacity) {
+        COVERAGE_INC(lflow_cache_full);
+        return NULL;
+    }
+
     struct lflow_cache_entry *lce = xzalloc(sizeof *lce);
 
     COVERAGE_INC(lflow_cache_add);
diff --git a/controller/lflow-cache.h b/controller/lflow-cache.h
index 5c622d5..6d3ea05 100644
--- a/controller/lflow-cache.h
+++ b/controller/lflow-cache.h
@@ -53,7 +53,7 @@ struct lflow_cache_value {
 struct lflow_cache *lflow_cache_create(void);
 void lflow_cache_flush(struct lflow_cache *);
 void lflow_cache_destroy(struct lflow_cache *);
-void lflow_cache_enable(struct lflow_cache *, bool enabled);
+void lflow_cache_enable(struct lflow_cache *, bool enabled, uint32_t capacity);
 bool lflow_cache_is_enabled(struct lflow_cache *);
 
 void lflow_cache_add_conj_id(struct lflow_cache *,
diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml
index 29833c7..e92db6d 100644
--- a/controller/ovn-controller.8.xml
+++ b/controller/ovn-controller.8.xml
@@ -249,6 +249,22 @@
         processing the southbound and local Open vSwitch database changes.
         The default value is considered false if this option is not defined.
       </dd>
+
+      <dt><code>external_ids:ovn-enable-lflow-cache</code></dt>
+      <dd>
+        The boolean flag indicates if <code>ovn-controller</code> should
+        enable/disable the logical flow in-memory cache it uses when
+        processing Southbound database logical flow changes.  By default
+        caching is enabled.
+      </dd>
+
+      <dt><code>external_ids:ovn-limit-lflow-cache</code></dt>
+      <dd>
+        When used, this configuration value determines the maximum number of
+        logical flow cache entries <code>ovn-controller</code> may create
+        when the logical flow cache is enabled.  By default the size of the
+        cache is unlimited.
+      </dd>
     </dl>
 
     <p>
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index c0737a8..f551142 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -95,6 +95,9 @@ static unixctl_cb_func debug_delay_nb_cfg_report;
 static char *parse_options(int argc, char *argv[]);
 OVS_NO_RETURN static void usage(void);
 
+/* By default don't set an upper bound for the lflow cache. */
+#define DEFAULT_LFLOW_CACHE_MAX_ENTRIES UINT32_MAX
+
 struct controller_engine_ctx {
     struct lflow_cache *lflow_cache;
 };
@@ -581,7 +584,10 @@ update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl 
*ovnsb_idl,
         lflow_cache_enable(ctx->lflow_cache,
                            smap_get_bool(&cfg->external_ids,
                                          "ovn-enable-lflow-cache",
-                                         true));
+                                         true),
+                           smap_get_uint(&cfg->external_ids,
+                                         "ovn-limit-lflow-cache",
+                                         DEFAULT_LFLOW_CACHE_MAX_ENTRIES));
     }
 }
 

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to