Add new I-P node that will store all the data for intreconnect
learned service monitors. In the future, support for synchronization
of service monitors between ovn deployments will be added,
this node will help us correctly process service monitors that were
learned from the interconnect southbound database.
This node is needed in many ways to create logical flows for service monitors
(arp/nd replays), when ovn-ic creates a flow we need to trigger logical flow
creations for the learned records.
As design choice there is only single lflow_ref for all ic_learned
related logical_flows that makes them not being thread safe and only
main thread can generate them during full recompute of lflow node.
Signed-off-by: Alexandra Rukomoinikova <[email protected]>
---
v1 --> v2: 1) rebased
2) corrected grammatical errors
3) took into account the comment regarding the handler
for the incremental update, I will add it in the fourth patch
4) in this and the next patch, renamed the data structures
related to svc_monitor_map to local_*, so that there is
a clear separation between local and learned structures
throughout the code
---
northd/en-lflow.c | 3 +-
northd/en-northd.c | 54 ++++++++++++++++++++++++++++++--
northd/en-northd.h | 5 +++
northd/inc-proc-northd.c | 13 ++++++++
northd/northd.c | 66 +++++++++++++++++++++++++++++++++++-----
northd/northd.h | 27 ++++++++++++++--
ovn-sb.ovsschema | 5 +--
ovn-sb.xml | 5 +++
8 files changed, 162 insertions(+), 16 deletions(-)
diff --git a/northd/en-lflow.c b/northd/en-lflow.c
index ac8ebba16..e46bba7b9 100644
--- a/northd/en-lflow.c
+++ b/northd/en-lflow.c
@@ -84,7 +84,8 @@ lflow_get_input_data(struct engine_node *node,
lflow_input->ls_stateful_table = &ls_stateful_data->table;
lflow_input->meter_groups = &sync_meters_data->meter_groups;
lflow_input->lb_datapaths_map = &northd_data->lb_datapaths_map;
- lflow_input->svc_monitor_map = &northd_data->svc_monitor_map;
+ lflow_input->local_svc_monitors_map =
+ &northd_data->local_svc_monitors_map;
lflow_input->bfd_ports = &bfd_sync_data->bfd_ports;
lflow_input->route_data = group_ecmp_route_data;
lflow_input->route_tables = &routes_data->route_tables;
diff --git a/northd/en-northd.c b/northd/en-northd.c
index 85db90537..56b25d271 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -41,6 +41,10 @@ static void
northd_get_input_data(struct engine_node *node,
struct northd_input *input_data)
{
+ input_data->nbrec_mirror_by_type_and_sink =
+ engine_ovsdb_node_get_index(
+ engine_get_input("NB_mirror", node),
+ "nbrec_mirror_by_type_and_sink");
input_data->sbrec_chassis_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_chassis", node),
@@ -61,10 +65,10 @@ northd_get_input_data(struct engine_node *node,
engine_ovsdb_node_get_index(
engine_get_input("SB_fdb", node),
"sbrec_fdb_by_dp_and_port");
- input_data->nbrec_mirror_by_type_and_sink =
+ input_data->sbrec_service_monitor_by_learned_type =
engine_ovsdb_node_get_index(
- engine_get_input("NB_mirror", node),
- "nbrec_mirror_by_type_and_sink");
+ engine_get_input("SB_service_monitor", node),
+ "sbrec_service_monitor_by_learned_type");
input_data->nbrec_static_mac_binding_table =
EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node));
@@ -76,6 +80,10 @@ northd_get_input_data(struct engine_node *node,
EN_OVSDB_GET(engine_get_input("NB_mirror_rule", node));
input_data->nbrec_port_group_table =
EN_OVSDB_GET(engine_get_input("NB_port_group", node));
+ input_data->sbrec_service_monitor_by_learned_type =
+ engine_ovsdb_node_get_index(
+ engine_get_input("SB_service_monitor", node),
+ "sbrec_service_monitor_by_learned_type");
input_data->sbrec_port_binding_table =
EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
@@ -119,6 +127,12 @@ northd_get_input_data(struct engine_node *node,
input_data->synced_lrs =
engine_get_input_data("datapath_synced_logical_router", node);
+
+ /* Add Service Monitor data for interconnect learned records. */
+ struct ic_learned_svc_monitors_data *ic_learned_svc_monitors_data =
+ engine_get_input_data("ic_learned_svc_monitors", node);
+ input_data->ic_learned_svc_monitors_map =
+ &ic_learned_svc_monitors_data->ic_learned_svc_monitors_map;
}
enum engine_node_state
@@ -438,6 +452,25 @@ en_bfd_sync_run(struct engine_node *node, void *data)
return new_state;
}
+enum engine_node_state
+en_ic_learned_svc_monitors_run(struct engine_node *node, void *data_)
+{
+ struct ic_learned_svc_monitors_data *data = data_;
+ struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type =
+ engine_ovsdb_node_get_index(
+ engine_get_input("SB_service_monitor", node),
+ "sbrec_service_monitor_by_learned_type");
+
+ ic_learned_svc_monitors_cleanup(data);
+ ic_learned_svc_monitors_init(data);
+
+ build_ic_learned_svc_monitors_map(
+ &data->ic_learned_svc_monitors_map,
+ sbrec_service_monitor_by_learned_type);
+
+ return EN_UPDATED;
+}
+
void
*en_northd_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
@@ -488,6 +521,15 @@ void
return data;
}
+void
+*en_ic_learned_svc_monitors_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ic_learned_svc_monitors_data *data = xzalloc(sizeof *data);
+ ic_learned_svc_monitors_init(data);
+ return data;
+}
+
void
en_northd_cleanup(void *data)
{
@@ -560,3 +602,9 @@ en_bfd_sync_cleanup(void *data)
{
bfd_sync_destroy(data);
}
+
+void
+en_ic_learned_svc_monitors_cleanup(void *data)
+{
+ ic_learned_svc_monitors_cleanup(data);
+}
diff --git a/northd/en-northd.h b/northd/en-northd.h
index 4f744a6c5..7794739b9 100644
--- a/northd/en-northd.h
+++ b/northd/en-northd.h
@@ -54,5 +54,10 @@ bfd_sync_northd_change_handler(struct engine_node *node,
void *data OVS_UNUSED);
enum engine_node_state en_bfd_sync_run(struct engine_node *node, void *data);
void en_bfd_sync_cleanup(void *data OVS_UNUSED);
+void *en_ic_learned_svc_monitors_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED);
+void en_ic_learned_svc_monitors_cleanup(void *data);
+enum engine_node_state
+en_ic_learned_svc_monitors_run(struct engine_node *node, void *data_);
#endif /* EN_NORTHD_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 07e189859..77767bc76 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -187,6 +187,7 @@ static ENGINE_NODE(datapath_logical_switch,
CLEAR_TRACKED_DATA);
static ENGINE_NODE(datapath_sync, CLEAR_TRACKED_DATA);
static ENGINE_NODE(datapath_synced_logical_router, CLEAR_TRACKED_DATA);
static ENGINE_NODE(datapath_synced_logical_switch, CLEAR_TRACKED_DATA);
+static ENGINE_NODE(ic_learned_svc_monitors);
void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
struct ovsdb_idl_loop *sb)
@@ -240,6 +241,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_lb_data, &en_datapath_synced_logical_router,
lb_data_synced_logical_router_handler);
+ engine_add_input(&en_ic_learned_svc_monitors,
+ &en_sb_service_monitor, NULL);
+
engine_add_input(&en_northd, &en_nb_mirror, NULL);
engine_add_input(&en_northd, &en_nb_mirror_rule, NULL);
engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL);
@@ -254,6 +258,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_static_mac_binding, NULL);
engine_add_input(&en_northd, &en_sb_chassis_template_var, NULL);
+ engine_add_input(&en_northd, &en_ic_learned_svc_monitors, NULL);
engine_add_input(&en_northd, &en_sb_fdb, northd_sb_fdb_change_handler);
engine_add_input(&en_northd, &en_global_config,
northd_global_config_handler);
@@ -388,6 +393,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_lflow, &en_multicast_igmp,
lflow_multicast_igmp_handler);
engine_add_input(&en_lflow, &en_sb_acl_id, NULL);
+ engine_add_input(&en_lflow, &en_ic_learned_svc_monitors, NULL);
engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL);
engine_add_input(&en_sync_to_sb_addr_set, &en_lr_stateful, NULL);
@@ -541,6 +547,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
"sbrec_ecmp_nexthop_by_ip_and_port",
sbrec_ecmp_nexthop_by_ip_and_port);
+ struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type
+ = ovsdb_idl_index_create1(sb->idl,
+ &sbrec_service_monitor_col_ic_learned);
+ engine_ovsdb_node_add_index(&en_sb_service_monitor,
+ "sbrec_service_monitor_by_learned_type",
+ sbrec_service_monitor_by_learned_type);
+
struct ed_type_global_config *global_config =
engine_get_internal_data(&en_global_config);
unixctl_command_register("debug/chassis-features-list", "", 0, 0,
diff --git a/northd/northd.c b/northd/northd.c
index 1f89cd32d..fff68be1e 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -10421,6 +10421,34 @@ build_bfd_map(const struct nbrec_bfd_table
*nbrec_bfd_table,
}
}
+void
+build_ic_learned_svc_monitors_map(
+ struct hmap *ic_learned_svc_monitors_map,
+ struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type)
+{
+ struct sbrec_service_monitor *key;
+
+ key = sbrec_service_monitor_index_init_row(
+ sbrec_service_monitor_by_learned_type);
+
+ sbrec_service_monitor_set_ic_learned(key, true);
+
+ const struct sbrec_service_monitor *sbrec_mon;
+ SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sbrec_mon, key,
+ sbrec_service_monitor_by_learned_type) {
+ uint32_t hash = sbrec_mon->port;
+ hash = hash_string(sbrec_mon->ip, hash);
+ hash = hash_string(sbrec_mon->logical_port, hash);
+ struct service_monitor_info *mon_info = xzalloc(sizeof *mon_info);
+ mon_info->sbrec_mon = sbrec_mon;
+ mon_info->required = true;
+ hmap_insert(ic_learned_svc_monitors_map,
+ &mon_info->hmap_node, hash);
+ }
+
+ sbrec_service_monitor_index_destroy_row(key);
+}
+
/* Returns a string of the IP address of the router port 'op' that
* overlaps with 'ip_s". If one is not found, returns NULL.
*
@@ -17945,7 +17973,7 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
lflows,
input_data->meter_groups,
input_data->lb_datapaths_map,
- input_data->svc_monitor_map,
+ input_data->local_svc_monitors_map,
input_data->bfd_ports,
input_data->features,
input_data->svc_monitor_mac,
@@ -18201,12 +18229,12 @@ lflow_handle_northd_lb_changes(struct ovsdb_idl_txn
*ovnsb_txn,
lflow_input->meter_groups,
lflow_input->lr_datapaths,
lflow_input->lr_stateful_table,
- lflow_input->svc_monitor_map,
+ lflow_input->local_svc_monitors_map,
&match, &actions);
build_lswitch_flows_for_lb(lb_dps, lflows,
lflow_input->meter_groups,
lflow_input->ls_datapaths,
- lflow_input->svc_monitor_map,
+ lflow_input->local_svc_monitors_map,
&match, &actions);
ds_destroy(&match);
@@ -18740,7 +18768,7 @@ northd_init(struct northd_data *data)
hmap_init(&data->lb_datapaths_map);
hmap_init(&data->lb_group_datapaths_map);
sset_init(&data->svc_monitor_lsps);
- hmap_init(&data->svc_monitor_map);
+ hmap_init(&data->local_svc_monitors_map);
init_northd_tracked_data(data);
}
@@ -18784,6 +18812,13 @@ bfd_sync_destroy(struct bfd_sync_data *data)
sset_destroy(&data->bfd_ports);
}
+void
+ic_learned_svc_monitors_init(struct ic_learned_svc_monitors_data *data)
+{
+ hmap_init(&data->ic_learned_svc_monitors_map);
+ data->lflow_ref = lflow_ref_create();
+}
+
void
northd_destroy(struct northd_data *data)
{
@@ -18801,10 +18836,10 @@ northd_destroy(struct northd_data *data)
hmap_destroy(&data->lb_group_datapaths_map);
struct service_monitor_info *mon_info;
- HMAP_FOR_EACH_POP (mon_info, hmap_node, &data->svc_monitor_map) {
+ HMAP_FOR_EACH_POP (mon_info, hmap_node, &data->local_svc_monitors_map) {
free(mon_info);
}
- hmap_destroy(&data->svc_monitor_map);
+ hmap_destroy(&data->local_svc_monitors_map);
/* XXX Having to explicitly clean up macam here
* is a bit strange. We don't explicitly initialize
@@ -18839,6 +18874,23 @@ bfd_destroy(struct bfd_data *data)
__bfd_destroy(&data->bfd_connections);
}
+static void
+__ic_learned_svcs_cleanup(struct hmap *ic_learned_svc_monitors_map)
+{
+ struct service_monitor_info *mon_info;
+ HMAP_FOR_EACH_POP (mon_info, hmap_node, ic_learned_svc_monitors_map) {
+ free(mon_info);
+ }
+ hmap_destroy(ic_learned_svc_monitors_map);
+}
+
+void
+ic_learned_svc_monitors_cleanup(struct ic_learned_svc_monitors_data *data)
+{
+ __ic_learned_svcs_cleanup(&data->ic_learned_svc_monitors_map);
+ lflow_ref_destroy(data->lflow_ref);
+}
+
void
route_policies_destroy(struct route_policies_data *data)
{
@@ -18916,7 +18968,7 @@ ovnnb_db_run(struct northd_input *input_data,
&data->lb_datapaths_map,
&data->lb_group_datapaths_map,
&data->svc_monitor_lsps,
- &data->svc_monitor_map);
+ &data->local_svc_monitors_map);
build_lb_count_dps(&data->lb_datapaths_map,
ods_size(&data->ls_datapaths),
ods_size(&data->lr_datapaths));
diff --git a/northd/northd.h b/northd/northd.h
index a3269f681..6922c19e8 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -73,13 +73,17 @@ struct northd_input {
const struct ovn_synced_logical_switch_map *synced_lses;
const struct ovn_synced_logical_router_map *synced_lrs;
+ /* Service Monitor data for interconnect learned records.*/
+ struct hmap *ic_learned_svc_monitors_map;
+
/* Indexes */
+ struct ovsdb_idl_index *nbrec_mirror_by_type_and_sink;
struct ovsdb_idl_index *sbrec_chassis_by_name;
struct ovsdb_idl_index *sbrec_chassis_by_hostname;
struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name;
struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;
struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port;
- struct ovsdb_idl_index *nbrec_mirror_by_type_and_sink;
+ struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type;
};
/* A collection of datapaths. E.g. all logical switch datapaths, or all
@@ -178,7 +182,7 @@ struct northd_data {
struct hmap lb_datapaths_map;
struct hmap lb_group_datapaths_map;
struct sset svc_monitor_lsps;
- struct hmap svc_monitor_map;
+ struct hmap local_svc_monitors_map;
/* Change tracking data. */
struct northd_tracked_data trk_data;
@@ -220,6 +224,11 @@ struct bfd_sync_data {
struct sset bfd_ports;
};
+struct ic_learned_svc_monitors_data {
+ struct hmap ic_learned_svc_monitors_map;
+ struct lflow_ref *lflow_ref;
+};
+
struct lflow_ref;
struct lr_nat_table;
@@ -243,7 +252,6 @@ struct lflow_input {
const struct hmap *lb_datapaths_map;
const struct sset *bfd_ports;
const struct chassis_features *features;
- const struct hmap *svc_monitor_map;
bool ovn_internal_version_changed;
const char *svc_monitor_mac;
const struct sampling_app_table *sampling_apps;
@@ -252,6 +260,9 @@ struct lflow_input {
struct simap *route_tables;
struct hmap *igmp_groups;
struct lflow_ref *igmp_lflow_ref;
+ const struct hmap *local_svc_monitors_map;
+ const struct hmap *ic_learned_svc_monitors_map;
+ struct lflow_ref *ic_learned_svc_monitors_lflow_ref;
};
extern int parallelization_state;
@@ -861,6 +872,11 @@ void bfd_sync_init(struct bfd_sync_data *);
void bfd_sync_swap(struct bfd_sync_data *, struct sset *bfd_ports);
void bfd_sync_destroy(struct bfd_sync_data *);
+void ic_learned_svc_monitors_init(
+ struct ic_learned_svc_monitors_data *data);
+void ic_learned_svc_monitors_cleanup(
+ struct ic_learned_svc_monitors_data *data);
+
struct lflow_table;
struct lr_stateful_tracked_data;
struct ls_stateful_tracked_data;
@@ -913,6 +929,11 @@ void bfd_table_sync(struct ovsdb_idl_txn *, const struct
nbrec_bfd_table *,
struct sset *);
void build_bfd_map(const struct nbrec_bfd_table *,
const struct sbrec_bfd_table *, struct hmap *);
+
+void build_ic_learned_svc_monitors_map(
+ struct hmap *ic_learned_svc_monitors_map,
+ struct ovsdb_idl_index *sbrec_service_monitor_by_learned_type);
+
void run_update_worker_pool(int n_threads);
const struct ovn_datapath *northd_get_datapath_for_port(
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 8123679b7..6efba45bd 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Southbound",
- "version": "21.3.0",
- "cksum": "3714238857 35128",
+ "version": "21.3.1",
+ "cksum": "3962801744 35179",
"tables": {
"SB_Global": {
"columns": {
@@ -525,6 +525,7 @@
"type": {"key": {"type": "string",
"enum": ["set", ["online", "offline", "error"]]},
"min": 0, "max": 1}},
+ "ic_learned": {"type": "boolean"},
"options": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 490394ff8..4d7960afa 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -5024,6 +5024,11 @@ tcp.flags = RST;
The name of the chassis where the logical port is bound.
</column>
+ <column name="ic_learned">
+ Set to true if the service monitor was propagated from another
+ OVN deployment via ovn-ic management.
+ </column>
+
<column name="options" key="interval" type='{"type": "integer"}'>
The interval, in seconds, between service monitor checks.
</column>