@@ -187,6 +187,24 @@ northd_nb_logical_switch_handler(struct engine_node *node,
return true;
}
+bool
+northd_sb_port_binding_handler(struct engine_node *node,
+ void *data)
+{
+ struct northd_data *nd = data;
+
+ struct northd_input input_data;
+
+ northd_get_input_data(node, &input_data);
+
+ if (!northd_handle_sb_port_binding_changes(
+ input_data.sbrec_port_binding_table, &nd->ls_ports)) {
+ return false;
+ }
+
+ return true;
+}
+
void
*en_northd_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
@@ -16,5 +16,6 @@ void en_northd_cleanup(void *data);
void en_northd_clear_tracked_data(void *data);
bool northd_nb_nb_global_handler(struct engine_node *, void *data OVS_UNUSED);
bool northd_nb_logical_switch_handler(struct engine_node *, void *data);
+bool northd_sb_port_binding_handler(struct engine_node *, void *data);
#endif /* EN_NORTHD_H */
@@ -143,10 +143,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
{
/* Define relationships between nodes where first argument is dependent
* on the second argument */
- engine_add_input(&en_northd, &en_nb_nb_global,
- northd_nb_nb_global_handler);
- engine_add_input(&en_northd, &en_nb_logical_switch,
- northd_nb_logical_switch_handler);
engine_add_input(&en_northd, &en_nb_port_group, NULL);
engine_add_input(&en_northd, &en_nb_load_balancer, NULL);
engine_add_input(&en_northd, &en_nb_load_balancer_group, NULL);
@@ -163,7 +159,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_northd, &en_sb_mirror, NULL);
engine_add_input(&en_northd, &en_sb_meter, NULL);
engine_add_input(&en_northd, &en_sb_datapath_binding, NULL);
- engine_add_input(&en_northd, &en_sb_port_binding, NULL);
engine_add_input(&en_northd, &en_sb_mac_binding, NULL);
engine_add_input(&en_northd, &en_sb_dns, NULL);
engine_add_input(&en_northd, &en_sb_ha_chassis_group, NULL);
@@ -174,6 +169,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL);
engine_add_input(&en_northd, &en_sb_chassis_template_var, NULL);
+ engine_add_input(&en_northd, &en_sb_port_binding,
+ northd_sb_port_binding_handler);
+ engine_add_input(&en_northd, &en_nb_nb_global,
+ northd_nb_nb_global_handler);
+ engine_add_input(&en_northd, &en_nb_logical_switch,
+ northd_nb_logical_switch_handler);
+
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);
@@ -5116,6 +5116,58 @@ fail:
return false;
}
+bool
+northd_handle_sb_port_binding_changes(
+ const struct sbrec_port_binding_table *sbrec_port_binding_table,
+ struct hmap *ls_ports)
+{
+ const struct sbrec_port_binding *pb;
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+ SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (pb, sbrec_port_binding_table) {
+ struct ovn_port *op = ovn_port_find(ls_ports, pb->logical_port);
+ if (op && !op->lsp_can_be_inc_processed) {
+ return false;
+ }
+ if (sbrec_port_binding_is_new(pb)) {
+ /* Most likely the PB was created by northd and this is the
+ * notification of that trasaction. So we just update the sb
+ * pointer in northd data. Fallback to recompute otherwise. */
+ if (!op) {
+ VLOG_WARN_RL(&rl, "A port-binding for %s is created but the "
+ "LSP is not found.", pb->logical_port);
+ return false;
+ }
+ op->sb = pb;
+ } else if (sbrec_port_binding_is_deleted(pb)) {
+ /* Most likely the PB was deleted by northd and this is the
+ * notification of that transaction, and we can ignore in this
+ * case. Fallback to recompute otherwise, to avoid dangling
+ * sb idl pointers and other unexpected behavior. */
+ if (op) {
+ VLOG_WARN_RL(&rl, "A port-binding for %s is deleted but the "
+ "LSP still exists.", pb->logical_port);
+ return false;
+ }
+ } else {
+ /* The PB is updated, most likely because of binding/unbinding
+ * to/from a chassis, and we can ignore the change (updating NB
+ * "up" will be handled in the engine node "sync_from_sb").
+ * Fallback to recompute for anything unexpected. */
+ if (!op) {
+ VLOG_WARN_RL(&rl, "A port-binding for %s is updated but the "
+ "LSP is not found.", pb->logical_port);
+ return false;
+ }
+ if (op->sb != pb) {
+ VLOG_WARN_RL(&rl, "A port-binding for %s is updated with a new"
+ "IDL row, which is unusual.", pb->logical_port);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
struct multicast_group {
const char *name;
uint16_t key; /* OVN_MIN_MULTICAST...OVN_MAX_MULTICAST. */
@@ -340,6 +340,8 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn,
struct tracked_ls_changes *,
struct lflow_input *, struct hmap *lflows);
+bool northd_handle_sb_port_binding_changes(
+ const struct sbrec_port_binding_table *, struct hmap *ls_ports);
void build_bfd_table(struct ovsdb_idl_txn *ovnsb_txn,
const struct nbrec_bfd_table *,
@@ -9504,30 +9504,30 @@ OVS_WAIT_UNTIL([test `as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=hv lsp-add ls0 lsp0-1 -- lsp-set-addresses lsp0-1 "aa:aa:aa:00:00:01 192.168.0.11"
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [3
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [0
])
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [5
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [2
])
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=hv lsp-add ls0 lsp0-2 -- lsp-set-addresses lsp0-2 "aa:aa:aa:00:00:02 192.168.0.12"
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [3
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [0
])
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [5
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [2
])
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=hv lsp-del lsp0-1
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [1
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [0
])
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [2
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [1
])
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=hv lsp-set-addresses lsp0-2 "aa:aa:aa:00:00:88 192.168.0.88"
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [1
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd recompute], [0], [0
])
-AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [2
+AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow recompute], [0], [1
])
# No change, no recompute