@@ -215,6 +215,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_northd, &en_sb_load_balancer, NULL);
engine_add_input(&en_northd, &en_sb_fdb, NULL);
engine_add_input(&en_northd, &en_sb_static_mac_binding, 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);
@@ -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;
+ }
}
}
@@ -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