From: Numan Siddique <[email protected]> For every a given load balancer group 'A', northd engine data maintains a bitmap of datapaths associated to this lb group. So when lb group 'A' gets associated to a logical switch 's1', the bitmap index of 's1' is set in its bitmap.
In order to handle the load balancer group changes incrementally for a logical switch, we need to set and clear the bitmap bits accordingly. And this patch does it. Signed-off-by: Numan Siddique <[email protected]> --- northd/en-lb-data.c | 126 ++++++++++++++++++++++++++++++-------------- northd/en-lb-data.h | 6 ++- northd/en-northd.c | 13 ++++- northd/northd.c | 64 ++++++++++++++++++---- northd/northd.h | 3 +- tests/ovn-northd.at | 27 ++++++++-- 6 files changed, 182 insertions(+), 57 deletions(-) diff --git a/northd/en-lb-data.c b/northd/en-lb-data.c index a835ac58d9..ebc7a186cd 100644 --- a/northd/en-lb-data.c +++ b/northd/en-lb-data.c @@ -38,12 +38,12 @@ static void lb_data_destroy(struct ed_type_lb_data *); static void build_lbs(const struct nbrec_load_balancer_table *, const struct nbrec_load_balancer_group_table *, struct hmap *lbs, struct hmap *lb_groups); -static void build_od_lb_info(const struct nbrec_logical_switch_table *, - struct hmap *od_lb_info); -static struct od_lb_data *find_od_lb_data(struct hmap *od_lb_info, +static void build_od_lb_map(const struct nbrec_logical_switch_table *, + struct hmap *od_lb_map); +static struct od_lb_data *find_od_lb_data(struct hmap *od_lb_map, const struct uuid *od_uuid); static void destroy_od_lb_data(struct od_lb_data *od_lb_data); -static struct od_lb_data *create_od_lb_data(struct hmap *od_lb_info, +static struct od_lb_data *create_od_lb_data(struct hmap *od_lb_map, const struct uuid *od_uuid); static struct ovn_lb_group *create_lb_group( @@ -62,6 +62,7 @@ static inline struct crupdated_lb_group * static inline void add_deleted_lb_group_to_tracked_data( struct ovn_lb_group *, struct tracked_lb_data *); static bool is_ls_lbs_changed(const struct nbrec_logical_switch *nbs); +static bool is_ls_lbgrps_changed(const struct nbrec_logical_switch *nbs); /* 'lb_data' engine node manages the NB load balancers and load balancer * groups. For each NB LB, it creates 'struct ovn_northd_lb' and @@ -93,7 +94,7 @@ en_lb_data_run(struct engine_node *node, void *data) lb_data->tracked = false; build_lbs(nb_lb_table, nb_lbg_table, &lb_data->lbs, &lb_data->lb_groups); - build_od_lb_info(nb_ls_table, &lb_data->od_lb_info); + build_od_lb_map(nb_ls_table, &lb_data->ls_lb_map); engine_set_node_state(node, EN_UPDATED); } @@ -265,50 +266,79 @@ lb_data_logical_switch_handler(struct engine_node *node, void *data) NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH_TRACKED (nbs, nb_ls_table) { if (nbrec_logical_switch_is_deleted(nbs)) { struct od_lb_data *od_lb_data = - find_od_lb_data(&lb_data->od_lb_info, &nbs->header_.uuid); + find_od_lb_data(&lb_data->ls_lb_map, &nbs->header_.uuid); if (od_lb_data) { - hmap_remove(&lb_data->od_lb_info, &od_lb_data->hmap_node); + hmap_remove(&lb_data->ls_lb_map, &od_lb_data->hmap_node); destroy_od_lb_data(od_lb_data); } } else { - if (!is_ls_lbs_changed(nbs)) { + if (!is_ls_lbs_changed(nbs) && !is_ls_lbgrps_changed(nbs)) { continue; } struct crupdated_od_lb_data *codlb = xzalloc(sizeof *codlb); codlb->od_uuid = nbs->header_.uuid; uuidset_init(&codlb->assoc_lbs); + uuidset_init(&codlb->assoc_lbgrps); struct od_lb_data *od_lb_data = - find_od_lb_data(&lb_data->od_lb_info, &nbs->header_.uuid); + find_od_lb_data(&lb_data->ls_lb_map, &nbs->header_.uuid); if (!od_lb_data) { - od_lb_data = create_od_lb_data(&lb_data->od_lb_info, + od_lb_data = create_od_lb_data(&lb_data->ls_lb_map, &nbs->header_.uuid); } - struct uuidset *pre_lb_uuids = od_lb_data->lbs; - od_lb_data->lbs = xzalloc(sizeof *od_lb_data->lbs); - uuidset_init(od_lb_data->lbs); - - for (size_t i = 0; i < nbs->n_load_balancer; i++) { - const struct uuid *lb_uuid = - &nbs->load_balancer[i]->header_.uuid; - uuidset_insert(od_lb_data->lbs, lb_uuid); + if (is_ls_lbs_changed(nbs)) { + struct uuidset *pre_lb_uuids = od_lb_data->lbs; + od_lb_data->lbs = xzalloc(sizeof *od_lb_data->lbs); + uuidset_init(od_lb_data->lbs); + + for (size_t i = 0; i < nbs->n_load_balancer; i++) { + const struct uuid *lb_uuid = + &nbs->load_balancer[i]->header_.uuid; + uuidset_insert(od_lb_data->lbs, lb_uuid); + + if (!uuidset_find_and_delete(pre_lb_uuids, + lb_uuid)) { + /* Add this lb to the tracked data. */ + uuidset_insert(&codlb->assoc_lbs, lb_uuid); + changed = true; + } + } - if (!uuidset_find_and_delete(pre_lb_uuids, - lb_uuid)) { - /* Add this lb to the tracked data. */ - uuidset_insert(&codlb->assoc_lbs, lb_uuid); + if (!uuidset_is_empty(pre_lb_uuids)) { + trk_lb_data->has_dissassoc_lbs_from_od = true; changed = true; } - } - if (!uuidset_is_empty(pre_lb_uuids)) { - trk_lb_data->has_dissassoc_lbs_from_od = true; - changed = true; + uuidset_destroy(pre_lb_uuids); + free(pre_lb_uuids); } - uuidset_destroy(pre_lb_uuids); - free(pre_lb_uuids); + if (is_ls_lbgrps_changed(nbs)) { + struct uuidset *pre_lbgrp_uuids = od_lb_data->lbgrps; + od_lb_data->lbgrps = xzalloc(sizeof *od_lb_data->lbgrps); + uuidset_init(od_lb_data->lbgrps); + for (size_t i = 0; i < nbs->n_load_balancer_group; i++) { + const struct uuid *lbg_uuid = + &nbs->load_balancer_group[i]->header_.uuid; + uuidset_insert(od_lb_data->lbgrps, lbg_uuid); + + if (!uuidset_find_and_delete(pre_lbgrp_uuids, + lbg_uuid)) { + /* Add this lb group to the tracked data. */ + uuidset_insert(&codlb->assoc_lbgrps, lbg_uuid); + changed = true; + } + } + + if (!uuidset_is_empty(pre_lbgrp_uuids)) { + trk_lb_data->has_dissassoc_lbgrps_from_od = true; + changed = true; + } + + uuidset_destroy(pre_lbgrp_uuids); + free(pre_lbgrp_uuids); + } ovs_list_insert(&trk_lb_data->crupdated_ls_lbs, &codlb->list_node); } @@ -326,7 +356,7 @@ lb_data_init(struct ed_type_lb_data *lb_data) { hmap_init(&lb_data->lbs); hmap_init(&lb_data->lb_groups); - hmap_init(&lb_data->od_lb_info); + hmap_init(&lb_data->ls_lb_map); struct tracked_lb_data *trk_lb_data = &lb_data->tracked_lb_data; hmapx_init(&trk_lb_data->crupdated_lbs); @@ -352,10 +382,10 @@ lb_data_destroy(struct ed_type_lb_data *lb_data) hmap_destroy(&lb_data->lb_groups); struct od_lb_data *od_lb_data; - HMAP_FOR_EACH_POP (od_lb_data, hmap_node, &lb_data->od_lb_info) { + HMAP_FOR_EACH_POP (od_lb_data, hmap_node, &lb_data->ls_lb_map) { destroy_od_lb_data(od_lb_data); } - hmap_destroy(&lb_data->od_lb_info); + hmap_destroy(&lb_data->ls_lb_map); destroy_tracked_data(lb_data); hmapx_destroy(&lb_data->tracked_lb_data.crupdated_lbs); @@ -399,43 +429,49 @@ create_lb_group(const struct nbrec_load_balancer_group *nbrec_lb_group, } static void -build_od_lb_info(const struct nbrec_logical_switch_table *nbrec_ls_table, - struct hmap *od_lb_info) +build_od_lb_map(const struct nbrec_logical_switch_table *nbrec_ls_table, + struct hmap *ls_lb_map) { const struct nbrec_logical_switch *nbrec_ls; NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (nbrec_ls, nbrec_ls_table) { - if (!nbrec_ls->n_load_balancer) { + if (!nbrec_ls->n_load_balancer && !nbrec_ls->n_load_balancer_group) { continue; } struct od_lb_data *od_lb_data = - create_od_lb_data(od_lb_info, &nbrec_ls->header_.uuid); + create_od_lb_data(ls_lb_map, &nbrec_ls->header_.uuid); for (size_t i = 0; i < nbrec_ls->n_load_balancer; i++) { uuidset_insert(od_lb_data->lbs, &nbrec_ls->load_balancer[i]->header_.uuid); } + for (size_t i = 0; i < nbrec_ls->n_load_balancer_group; i++) { + uuidset_insert(od_lb_data->lbgrps, + &nbrec_ls->load_balancer_group[i]->header_.uuid); + } } } static struct od_lb_data * -create_od_lb_data(struct hmap *od_lb_info, const struct uuid *od_uuid) +create_od_lb_data(struct hmap *od_lb_map, const struct uuid *od_uuid) { struct od_lb_data *od_lb_data = xzalloc(sizeof *od_lb_data); od_lb_data->od_uuid = *od_uuid; od_lb_data->lbs = xzalloc(sizeof *od_lb_data->lbs); + od_lb_data->lbgrps = xzalloc(sizeof *od_lb_data->lbgrps); uuidset_init(od_lb_data->lbs); + uuidset_init(od_lb_data->lbgrps); - hmap_insert(od_lb_info, &od_lb_data->hmap_node, + hmap_insert(od_lb_map, &od_lb_data->hmap_node, uuid_hash(&od_lb_data->od_uuid)); return od_lb_data; } static struct od_lb_data * -find_od_lb_data(struct hmap *od_lb_info, const struct uuid *od_uuid) +find_od_lb_data(struct hmap *od_lb_map, const struct uuid *od_uuid) { struct od_lb_data *od_lb_data; HMAP_FOR_EACH_WITH_HASH (od_lb_data, hmap_node, uuid_hash(od_uuid), - od_lb_info) { + od_lb_map) { if (uuid_equals(&od_lb_data->od_uuid, od_uuid)) { return od_lb_data; } @@ -448,7 +484,9 @@ static void destroy_od_lb_data(struct od_lb_data *od_lb_data) { uuidset_destroy(od_lb_data->lbs); + uuidset_destroy(od_lb_data->lbgrps); free(od_lb_data->lbs); + free(od_lb_data->lbgrps); free(od_lb_data); } @@ -459,6 +497,7 @@ destroy_tracked_data(struct ed_type_lb_data *lb_data) lb_data->tracked_lb_data.has_health_checks = false; lb_data->tracked_lb_data.has_dissassoc_lbs_from_lb_grops = false; lb_data->tracked_lb_data.has_dissassoc_lbs_from_od = false; + lb_data->tracked_lb_data.has_dissassoc_lbgrps_from_od = false; struct hmapx_node *node; HMAPX_FOR_EACH_SAFE (node, &lb_data->tracked_lb_data.deleted_lbs) { @@ -486,7 +525,7 @@ destroy_tracked_data(struct ed_type_lb_data *lb_data) &lb_data->tracked_lb_data.crupdated_ls_lbs) { ovs_list_remove(&codlb->list_node); uuidset_destroy(&codlb->assoc_lbs); - + uuidset_destroy(&codlb->assoc_lbgrps); free(codlb); } } @@ -537,3 +576,10 @@ is_ls_lbs_changed(const struct nbrec_logical_switch *nbs) { || nbrec_logical_switch_is_updated(nbs, NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER)); } + +static bool +is_ls_lbgrps_changed(const struct nbrec_logical_switch *nbs) { + return ((nbrec_logical_switch_is_new(nbs) && nbs->n_load_balancer_group) + || nbrec_logical_switch_is_updated(nbs, + NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER_GROUP)); +} diff --git a/northd/en-lb-data.h b/northd/en-lb-data.h index 4b2fdf770c..6269e9b548 100644 --- a/northd/en-lb-data.h +++ b/northd/en-lb-data.h @@ -26,6 +26,7 @@ struct crupdated_od_lb_data { struct uuid od_uuid; struct uuidset assoc_lbs; + struct uuidset assoc_lbgrps; }; struct tracked_lb_data { @@ -53,6 +54,9 @@ struct tracked_lb_data { /* Indicates if a lb was disassociated from a logical switch. */ bool has_dissassoc_lbs_from_od; + + /* Indicates if a lb group was disassociated from a logical switch. */ + bool has_dissassoc_lbgrps_from_od; }; /* struct which maintains the data of the engine node lb_data. */ @@ -62,7 +66,7 @@ struct ed_type_lb_data { /* hmap of load balancer groups. hmap node is 'struct ovn_lb_group *' */ struct hmap lb_groups; - struct hmap od_lb_info; + struct hmap ls_lb_map; /* tracked data*/ bool tracked; diff --git a/northd/en-northd.c b/northd/en-northd.c index 9d1838a1a4..0c2810b5d7 100644 --- a/northd/en-northd.c +++ b/northd/en-northd.c @@ -236,6 +236,14 @@ northd_lb_data_handler_pre_od(struct engine_node *node, void *data) return false; } + if (lb_data->tracked_lb_data.has_dissassoc_lbs_from_lb_grops) { + return false; + } + + if (lb_data->tracked_lb_data.has_dissassoc_lbgrps_from_od) { + return false; + } + struct northd_data *nd = data; if (!northd_handle_lb_data_changes_pre_od(&lb_data->tracked_lb_data, @@ -258,12 +266,15 @@ northd_lb_data_handler_post_od(struct engine_node *node, void *data) ovs_assert(lb_data->tracked); ovs_assert(!lb_data->tracked_lb_data.has_dissassoc_lbs_from_od); + ovs_assert(!lb_data->tracked_lb_data.has_dissassoc_lbgrps_from_od); + ovs_assert(!lb_data->tracked_lb_data.has_dissassoc_lbs_from_lb_grops); struct northd_data *nd = data; if (!northd_handle_lb_data_changes_post_od(&lb_data->tracked_lb_data, &nd->ls_datapaths, - &nd->lb_datapaths_map)) { + &nd->lb_datapaths_map, + &nd->lb_group_datapaths_map)) { return false; } diff --git a/northd/northd.c b/northd/northd.c index 1612e80719..9c6ce0a142 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -5035,6 +5035,7 @@ ls_port_create(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *ls_ports, * Presently supports i-p for the below changes: * - logical switch ports. * - load balancers. + * - load balancer groups. */ static bool ls_changes_can_be_handled( @@ -5045,7 +5046,8 @@ ls_changes_can_be_handled( for (col = 0; col < NBREC_LOGICAL_SWITCH_N_COLUMNS; col++) { if (nbrec_logical_switch_is_updated(ls, col)) { if (col == NBREC_LOGICAL_SWITCH_COL_PORTS || - col == NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER) { + col == NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER || + col == NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER_GROUP) { continue; } return false; @@ -5076,12 +5078,6 @@ ls_changes_can_be_handled( return false; } } - for (size_t i = 0; i < ls->n_load_balancer_group; i++) { - if (nbrec_load_balancer_group_row_get_seqno(ls->load_balancer_group[i], - OVSDB_IDL_CHANGE_MODIFY) > 0) { - return false; - } - } for (size_t i = 0; i < ls->n_qos_rules; i++) { if (nbrec_qos_row_get_seqno(ls->qos_rules[i], OVSDB_IDL_CHANGE_MODIFY) > 0) { @@ -5277,7 +5273,11 @@ fail: /* Return true if changes are handled incrementally, false otherwise. * When there are any changes, try to track what's exactly changed and set * northd_data->change_tracked accordingly: change tracked - true, otherwise, - * false. */ + * false. + * + * Note: Changes to load balancer and load balancer groups associated with + * the logical switches are handled separately in the lb_data change handlers. + * */ bool northd_handle_ls_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct northd_input *ni, @@ -5481,13 +5481,16 @@ northd_handle_lb_data_changes_pre_od(struct tracked_lb_data *trk_lb_data, bool northd_handle_lb_data_changes_post_od(struct tracked_lb_data *trk_lb_data, struct ovn_datapaths *ls_datapaths, - struct hmap *lb_datapaths_map) + struct hmap *lb_datapaths_map, + struct hmap *lb_group_datapaths_map) { ovs_assert(!trk_lb_data->has_health_checks); + ovs_assert(!trk_lb_data->has_dissassoc_lbs_from_lb_grops); struct ovn_northd_lb *lb; struct hmapx_node *hmapx_node; struct ovn_lb_datapaths *lb_dps; + struct ovn_lb_group_datapaths *lbgrp_dps; struct ovn_datapath *od; struct crupdated_od_lb_data *codlb; @@ -5502,6 +5505,22 @@ northd_handle_lb_data_changes_post_od(struct tracked_lb_data *trk_lb_data, ovn_lb_datapaths_add_ls(lb_dps, 1, &od); } + UUIDSET_FOR_EACH (uuidnode, &codlb->assoc_lbgrps) { + lbgrp_dps = ovn_lb_group_datapaths_find(lb_group_datapaths_map, + &uuidnode->uuid); + ovs_assert(lbgrp_dps); + ovn_lb_group_datapaths_add_ls(lbgrp_dps, 1, &od); + + /* Associate all the lbs of the lbgrp to the datapath 'od' */ + for (size_t j = 0; j < lbgrp_dps->lb_group->n_lbs; j++) { + const struct uuid *lb_uuid + = &lbgrp_dps->lb_group->lbs[j]->nlb->header_.uuid; + lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid); + ovs_assert(lb_dps); + ovn_lb_datapaths_add_ls(lb_dps, 1, &od); + } + } + /* Re-evaluate 'od->has_lb_vip' */ init_lb_for_datapath(od); } @@ -5521,6 +5540,33 @@ northd_handle_lb_data_changes_post_od(struct tracked_lb_data *trk_lb_data, } } + struct ovn_lb_group *lbgrp; + struct crupdated_lb_group *crupdated_lbg; + HMAPX_FOR_EACH (hmapx_node, &trk_lb_data->crupdated_lb_groups) { + crupdated_lbg = hmapx_node->data; + lbgrp = crupdated_lbg->lbg; + const struct uuid *lb_uuid = &lbgrp->uuid; + + lbgrp_dps = ovn_lb_group_datapaths_find(lb_group_datapaths_map, + lb_uuid); + ovs_assert(lbgrp_dps); + + struct hmapx_node *hnode; + HMAPX_FOR_EACH (hnode, &crupdated_lbg->assoc_lbs) { + lb = hnode->data; + lb_uuid = &lb->nlb->header_.uuid; + lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid); + ovs_assert(lb_dps); + for (size_t i = 0; i < lbgrp_dps->n_ls; i++) { + od = lbgrp_dps->ls[i]; + ovn_lb_datapaths_add_ls(lb_dps, 1, &od); + + /* Re-evaluate 'od->has_lb_vip' */ + init_lb_for_datapath(od); + } + } + } + return true; } diff --git a/northd/northd.h b/northd/northd.h index 0ed7215356..a51b42bcd5 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -357,7 +357,8 @@ bool northd_handle_lb_data_changes_pre_od(struct tracked_lb_data *, struct hmap *lb_group_datapaths_map); bool northd_handle_lb_data_changes_post_od(struct tracked_lb_data *, struct ovn_datapaths *ls_datapaths, - struct hmap *lb_datapaths_map); + struct hmap *lb_datapaths_map, + struct hmap *lb_group_datapaths_map); void build_bfd_table(struct ovsdb_idl_txn *ovnsb_txn, const struct nbrec_bfd_table *, diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 5a8acd4e93..a7b47333c4 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2141,6 +2141,18 @@ check ovn-nbctl --wait=sb sync AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl ]) +# Now associate vip again to lb4 and then delete it. +check ovn-nbctl set load_balancer $lb4 vips:"10.0.0.13"="10.0.0.6" +check ovn-nbctl --wait=sb sync +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl + table=1 (ls_out_pre_lb ), priority=100 , match=(ip), action=(reg0[[2]] = 1; next;) +]) + +check ovn-nbctl lb-del $lb4 +check ovn-nbctl --wait=sb sync +AT_CHECK([ovn-sbctl lflow-list | grep "ls_out_pre_lb.*priority=100" | grep reg0 | sort], [0], [dnl +]) + AT_CLEANUP ]) @@ -9841,20 +9853,24 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl add logical_switch sw0 load_balancer_group $lbg1_uuid -check_engine_stats recompute recompute +check_engine_stats norecompute recompute +CHECK_NO_CHANGE_AFTER_RECOMPUTE -# Update lb and this should result in recompute +# Update lb and this should not result in northd recompute check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl --wait=sb set load_balancer . options:bar=foo -check_engine_stats recompute recompute +check_engine_stats norecompute recompute +CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl clear logical_switch sw0 load_balancer_group check_engine_stats recompute recompute +CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl add logical_router lr0 load_balancer_group $lbg1_uuid check_engine_stats recompute recompute +CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl clear logical_router lr0 load_balancer_group @@ -9863,7 +9879,8 @@ check_engine_stats recompute recompute # Add back lb group to logical switch and then delete it. check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl add logical_switch sw0 load_balancer_group $lbg1_uuid -check_engine_stats recompute recompute +check_engine_stats norecompute recompute +CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl clear logical_switch sw0 load_balancer_group -- \ @@ -9896,7 +9913,7 @@ check_engine_stats norecompute recompute check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl set logical_switch sw0 load_balancer_group=$lbg1_uuid -check_engine_stats recompute recompute +check_engine_stats norecompute recompute CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats -- 2.40.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
