Northd handles virtual port binding requests received by ovn-controllers
without tracking those requests or saving any info about the last
binding requests and the number of requests received for an individual
virtual port.

This patch adds a basic tracking mechanism for each virtual port that
future patches will use to limit/pause the controller from sending
binding requests for a specific virtual port if this port overflows the
system by such requests.

Signed-off-by: Mohammad Heib <[email protected]>
---
 northd/northd.c     | 88 +++++++++++++++++++++++++++++++++++++++++++++
 northd/northd.h     |  2 ++
 northd/ovn-northd.c |  3 ++
 3 files changed, 93 insertions(+)

diff --git a/northd/northd.c b/northd/northd.c
index a8a0b6f94..89d5b2936 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3757,6 +3757,79 @@ build_lb_port_related_data(
     build_lswitch_lbs_from_lrouter(lr_datapaths, lb_dps_map, lb_group_dps_map);
 }
 
+/*
+ * These functions implements the binding request tracking for a virtual
+ * port which can be used to limit virtual port binding requests
+ * and avoid system overflow.
+ *
+ * Virtual port binding requests must not exceed
+ * VPORT_MAX_BINDING_REQUEST_TRESHOLD within a VPORT_BINDING_TIMEFRAME,
+ * otherwise, this vport must be defined as overflowed and should limit
+ * the binding request in this port for a certain time.
+ */
+#define VPORT_BINDING_TIMEFRAME 10000
+#define VPORT_MAX_BINDING_REQUEST_TRESHOLD 15
+
+static struct hmap tracked_virtual_ports;
+
+struct tracked_virtual_port {
+    struct hmap_node node;
+    /*
+     * Use port name instaed of ovn_port refrence to make
+     * sure that virtual port tracking data will be permanent accross
+     * northd loops and we can keep track the target ports.
+     */
+    char *name;
+    long long int First_bind_in_tframe;
+    size_t Bind_request_cnt;
+};
+
+static struct tracked_virtual_port *
+find_tracked_virtual_port(const char *name) {
+    struct tracked_virtual_port *vport;
+    HMAP_FOR_EACH (vport, node, &tracked_virtual_ports) {
+        if (!strcmp(name, vport->name)) {
+            return vport;
+        }
+    }
+    return NULL;
+}
+
+static void
+add_to_tracked_virtual_ports(const char *name) {
+    struct tracked_virtual_port *vport = find_tracked_virtual_port(name);
+    if (!vport) {
+        vport = xmalloc(sizeof *vport);
+        vport->name = xstrdup(name);
+        vport->First_bind_in_tframe = 0;
+        vport->Bind_request_cnt = 0;
+        hmap_insert(&tracked_virtual_ports, &vport->node,
+                                            hash_string(name, 0));
+    }
+}
+
+static void
+remove_from_tracked_virtual_ports(const char *name) {
+    struct tracked_virtual_port *vport = find_tracked_virtual_port(name);
+    if (vport) {
+        free(vport->name);
+        hmap_remove(&tracked_virtual_ports, &vport->node);
+        free(vport);
+    }
+}
+
+void init_tracked_virtual_ports(void) {
+    hmap_init(&tracked_virtual_ports);
+}
+
+void destroy_tracked_virtual_ports(void) {
+    struct tracked_virtual_port *vport;
+    HMAP_FOR_EACH_SAFE (vport, node, &tracked_virtual_ports) {
+        remove_from_tracked_virtual_ports(vport->name);
+    }
+    hmap_destroy(&tracked_virtual_ports);
+}
+
 /* Syncs the SB port binding for the ovn_port 'op' of a logical switch port.
  * Caller should make sure that the OVN SB IDL txn is not NULL.  Presently it
  * only syncs the nat column of port binding corresponding to the 'op->nbsp' */
@@ -4163,6 +4236,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
                               op, queue_id_bitmap,
                               &active_ha_chassis_grps);
         sbrec_port_binding_set_logical_port(op->sb, op->key);
+        if (!strcmp(op->sb->type, "virtual")) {
+            add_to_tracked_virtual_ports(op->sb->logical_port);
+        }
         ovs_list_remove(&op->list);
     }
 
@@ -4170,6 +4246,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
     if (!ovs_list_is_empty(&sb_only)) {
         LIST_FOR_EACH_SAFE (op, list, &sb_only) {
             ovs_list_remove(&op->list);
+            if (!strcmp(op->sb->type, "virtual")) {
+                remove_from_tracked_virtual_ports(op->sb->logical_port);
+            }
             sbrec_port_binding_delete(op->sb);
             ovn_port_destroy(ports, op);
         }
@@ -4554,6 +4633,12 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn 
*ovnsb_idl_txn,
             if (!op) {
                 goto fail;
             }
+
+            if (!strcmp(new_nbsp->type, "virtual")) {
+                /* Add to virtual port tracking map */
+                add_to_tracked_virtual_ports(op->nbsp->name);
+            }
+
             add_op_to_northd_tracked_ports(&trk_lsps->created, op);
         } else if (ls_port_has_changed(new_nbsp)) {
             /* Existing port updated */
@@ -4614,6 +4699,9 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
             add_op_to_northd_tracked_ports(&trk_lsps->deleted, op);
             hmap_remove(&nd->ls_ports, &op->key_node);
             hmap_remove(&od->ports, &op->dp_node);
+            if (!strcmp(op->sb->type, "virtual")) {
+                remove_from_tracked_virtual_ports(op->sb->logical_port);
+            }
             sbrec_port_binding_delete(op->sb);
             delete_fdb_entry(ni->sbrec_fdb_by_dp_and_port, od->tunnel_key,
                                 op->tunnel_key);
diff --git a/northd/northd.h b/northd/northd.h
index d4a8d75ab..5129f4afe 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -789,4 +789,6 @@ is_vxlan_mode(const struct smap *nb_options,
 
 uint32_t get_ovn_max_dp_key_local(bool _vxlan_mode);
 
+void init_tracked_virtual_ports(void);
+void destroy_tracked_virtual_ports(void);
 #endif /* NORTHD_H */
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index d71114f35..e58abdbcd 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -891,6 +891,8 @@ main(int argc, char *argv[])
     /* Initialize incremental processing engine for ovn-northd */
     inc_proc_northd_init(&ovnnb_idl_loop, &ovnsb_idl_loop);
 
+    init_tracked_virtual_ports();
+
     unsigned int ovnnb_cond_seqno = UINT_MAX;
     unsigned int ovnsb_cond_seqno = UINT_MAX;
 
@@ -1079,6 +1081,7 @@ main(int argc, char *argv[])
         stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec());
     }
     inc_proc_northd_cleanup();
+    destroy_tracked_virtual_ports();
 
     ovsdb_idl_loop_destroy(&ovnnb_idl_loop);
     ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
-- 
2.34.3

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

Reply via email to