Add configuration option into NB global table
called "mac_binding_removal_limit" defaulting to 0.
This option allows to limit number of MAC bindings
that can be removed by the aging mechanism in a single
transaction. The 0 means that the mechanism is disabled.
If the limit is reached next removal will be delayed by
10 ms. This option when being set has a downside that
in theory we could never finish the removal, however in
practice it is unlikely considering that not all routers
will have aging enabled and the enabled will be with
reasonable threshold.

Reported-at: https://bugzilla.redhat.com/2084668
Acked-by: Mark Michelson <mmich...@redhat.com>
Acked-by: Dumitru Ceara <dce...@redhat.com>
Signed-off-by: Ales Musil <amu...@redhat.com>
---
 northd/inc-proc-northd.c   |  1 +
 northd/mac-binding-aging.c | 33 +++++++++++++++++++++++++++++++--
 ovn-nb.xml                 |  8 ++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index e30b281b8..582cb5af7 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -210,6 +210,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_northd, &en_sb_service_monitor, NULL);
     engine_add_input(&en_northd, &en_sb_load_balancer, NULL);
     engine_add_input(&en_northd, &en_sb_fdb, NULL);
+    engine_add_input(&en_mac_binding_aging, &en_nb_nb_global, NULL);
     engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL);
     engine_add_input(&en_mac_binding_aging, &en_northd, NULL);
     engine_add_input(&en_mac_binding_aging, &en_mac_binding_aging_waker, NULL);
diff --git a/northd/mac-binding-aging.c b/northd/mac-binding-aging.c
index 3859c050b..36d0a6fd7 100644
--- a/northd/mac-binding-aging.c
+++ b/northd/mac-binding-aging.c
@@ -28,6 +28,8 @@
 
 VLOG_DEFINE_THIS_MODULE(mac_binding_aging);
 
+#define MAC_BINDING_BULK_REMOVAL_DELAY_MSEC 10
+
 struct mac_binding_waker {
     bool should_schedule;
     long long next_wake_msec;
@@ -37,7 +39,8 @@ static void
 mac_binding_aging_run_for_datapath(const struct sbrec_datapath_binding *dp,
                                    const struct nbrec_logical_router *nbr,
                                    struct ovsdb_idl_index *mb_by_datapath,
-                                   int64_t now, int64_t *wake_delay)
+                                   int64_t now, int64_t *wake_delay,
+                                   uint32_t removal_limit, uint32_t *removed_n)
 {
     uint64_t threshold = smap_get_uint(&nbr->options,
                                        "mac_binding_age_threshold",
@@ -58,6 +61,10 @@ mac_binding_aging_run_for_datapath(const struct 
sbrec_datapath_binding *dp,
             continue;
         } else if (elapsed >= threshold) {
             sbrec_mac_binding_delete(mb);
+            (*removed_n)++;
+            if (removal_limit && *removed_n == removal_limit) {
+                break;
+            }
         } else {
             *wake_delay = MIN(*wake_delay, threshold - elapsed);
         }
@@ -65,6 +72,20 @@ mac_binding_aging_run_for_datapath(const struct 
sbrec_datapath_binding *dp,
     sbrec_mac_binding_index_destroy_row(mb_index_row);
 }
 
+static uint32_t
+get_removal_limit(struct engine_node *node)
+{
+    const struct nbrec_nb_global_table *nb_global_table =
+        EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
+    const struct nbrec_nb_global *nb =
+        nbrec_nb_global_table_first(nb_global_table);
+    if (!nb) {
+       return 0;
+    }
+
+    return smap_get_uint(&nb->options, "mac_binding_removal_limit", 0);
+}
+
 void
 en_mac_binding_aging_run(struct engine_node *node, void *data OVS_UNUSED)
 {
@@ -76,6 +97,8 @@ en_mac_binding_aging_run(struct engine_node *node, void *data 
OVS_UNUSED)
 
     int64_t next_expire_msec = INT64_MAX;
     int64_t now = time_wall_msec();
+    uint32_t removal_limit = get_removal_limit(node);
+    uint32_t removed_n = 0;
     struct northd_data *northd_data = engine_get_input_data("northd", node);
     struct mac_binding_waker *waker =
         engine_get_input_data("mac_binding_aging_waker", node);
@@ -88,7 +111,13 @@ en_mac_binding_aging_run(struct engine_node *node, void 
*data OVS_UNUSED)
         if (od->sb && od->nbr) {
             mac_binding_aging_run_for_datapath(od->sb, od->nbr,
                                                sbrec_mac_binding_by_datapath,
-                                               now, &next_expire_msec);
+                                               now, &next_expire_msec,
+                                               removal_limit, &removed_n);
+            if (removal_limit && removed_n == removal_limit) {
+                /* Schedule the next run after specified delay. */
+                next_expire_msec = MAC_BINDING_BULK_REMOVAL_DELAY_MSEC;
+                break;
+            }
         }
     }
 
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 4cc97c368..29789c4b6 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -162,6 +162,14 @@
         dynamically assigned, e.g. <code>00:11:22</code>
       </column>
 
+      <column name="options" key="mac_binding_removal_limit"
+              type='{"type": "integer", "minInteger": 0, "maxInteger": 
4294967295}'>
+        MAC binding aging bulk removal limit. This limits how many rows
+        can expire in a single transaction. Default value is 0 which
+        is unlimited. When we hit the limit next batch removal is delayed by
+        10 ms.
+      </column>
+
       <column name="options" key="controller_event" type='{"type": "boolean"}'>
         Value set by the CMS to enable/disable ovn-controller event reporting.
         Traffic into OVS can raise a 'controller' event that results in a
-- 
2.37.3

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to