Skip to content

Commit

Permalink
northd: Incremental processing of VIF changes in 'northd' node.
Browse files Browse the repository at this point in the history
This patch introduces a change handler for NB logical_switch within the
'northd' node. It specifically handles cases where logical switch ports
in the tracked logical switches are changed (added/updated/deleted).
Only regular logical switch ports - which are common for VMs/Pods - are
addressed. For other scenarios, it reverts to recompute.

This update avoids recompute in the northd node (especially the
resource-intensive build_ports()) for NB changes of VIF
add/update/delete.  However, it does not eliminate the need for lflow
recompute.

Below are the performance test results simulating an ovn-k8s topology of
500 nodes x 50 lsp per node:

Before:
ovn-nbctl --wait=hv --print-wait-time lsp-del lsp_1_0001_01
    ovn-northd completion:          955ms
ovn-nbctl --wait=hv --print-wait-time lsp-add ls_1_0001 lsp_1_0001_01 -- lsp-set-addresses lsp_1_0001_01 "ff:f1:bb:00:01:01 1.0.1.101" -- lsp-set-port-security lsp_1_0001_01 "ff:f1:bb:00:01:01 1.0.1.101"
    ovn-northd completion:          919ms

After:
ovn-nbctl --wait=hv --print-wait-time lsp-del lsp_1_0001_01
    ovn-northd completion:          776ms
ovn-nbctl --wait=hv --print-wait-time lsp-add ls_1_0001 lsp_1_0001_01 -- lsp-set-addresses lsp_1_0001_01 "ff:f1:bb:00:01:01 1.0.1.101" -- lsp-set-port-security lsp_1_0001_01 "ff:f1:bb:00:01:01 1.0.1.101"
    ovn-northd completion:          773ms

Both addition and deletion show ~20% reduction of ovn-northd completion
time.  Note: the test uses only 1 thread of ovn-northd for flow
recompute. Using multithread should show a larger percentage of
improvement.

Signed-off-by: Han Zhou <hzhou@ovn.org>
Reviewed-by: Ales Musil <amusil@redhat.com>
Acked-by: Numan Siddique <numans@ovn.org>
  • Loading branch information
hzhou8 committed Jun 8, 2023
1 parent 278fb57 commit b337750
Show file tree
Hide file tree
Showing 8 changed files with 685 additions and 127 deletions.
15 changes: 15 additions & 0 deletions lib/ovn-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,21 @@ ovn_allocate_tnlid(struct hmap *set, const char *name, uint32_t min,
return 0;
}

bool
ovn_free_tnlid(struct hmap *tnlids, uint32_t tnlid)
{
uint32_t hash = hash_int(tnlid, 0);
struct tnlid_node *node;
HMAP_FOR_EACH_IN_BUCKET (node, hmap_node, hash, tnlids) {
if (node->tnlid == tnlid) {
hmap_remove(tnlids, &node->hmap_node);
free(node);
return true;
}
}
return false;
}

char *
ovn_chassis_redirect_name(const char *port_name)
{
Expand Down
1 change: 1 addition & 0 deletions lib/ovn-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ bool ovn_add_tnlid(struct hmap *set, uint32_t tnlid);
bool ovn_tnlid_present(struct hmap *tnlids, uint32_t tnlid);
uint32_t ovn_allocate_tnlid(struct hmap *set, const char *name, uint32_t min,
uint32_t max, uint32_t *hint);
bool ovn_free_tnlid(struct hmap *tnlids, uint32_t tnlid);

static inline void
get_unique_lport_key(uint64_t dp_tunnel_key, uint64_t lport_tunnel_key,
Expand Down
130 changes: 86 additions & 44 deletions northd/en-northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,92 +31,103 @@

VLOG_DEFINE_THIS_MODULE(en_northd);

void en_northd_run(struct engine_node *node, void *data)
static void
northd_get_input_data(struct engine_node *node,
struct northd_input *input_data)
{
const struct engine_context *eng_ctx = engine_get_context();

struct northd_input input_data;

northd_destroy(data);
northd_init(data);

input_data.sbrec_chassis_by_name =
input_data->sbrec_chassis_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_chassis", node),
"sbrec_chassis_by_name");
input_data.sbrec_chassis_by_hostname =
input_data->sbrec_chassis_by_hostname =
engine_ovsdb_node_get_index(
engine_get_input("SB_chassis", node),
"sbrec_chassis_by_hostname");
input_data.sbrec_ha_chassis_grp_by_name =
input_data->sbrec_ha_chassis_grp_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_ha_chassis_group", node),
"sbrec_ha_chassis_grp_by_name");
input_data.sbrec_ip_mcast_by_dp =
input_data->sbrec_ip_mcast_by_dp =
engine_ovsdb_node_get_index(
engine_get_input("SB_ip_multicast", node),
"sbrec_ip_mcast_by_dp");
input_data.sbrec_static_mac_binding_by_lport_ip =
input_data->sbrec_static_mac_binding_by_lport_ip =
engine_ovsdb_node_get_index(
engine_get_input("SB_static_mac_binding", node),
"sbrec_static_mac_binding_by_lport_ip");
input_data->sbrec_fdb_by_dp_and_port =
engine_ovsdb_node_get_index(
engine_get_input("SB_fdb", node),
"sbrec_fdb_by_dp_and_port");

input_data.nbrec_nb_global_table =
input_data->nbrec_nb_global_table =
EN_OVSDB_GET(engine_get_input("NB_nb_global", node));
input_data.nbrec_logical_switch_table =
input_data->nbrec_logical_switch_table =
EN_OVSDB_GET(engine_get_input("NB_logical_switch", node));
input_data.nbrec_logical_router_table =
input_data->nbrec_logical_router_table =
EN_OVSDB_GET(engine_get_input("NB_logical_router", node));
input_data.nbrec_load_balancer_table =
input_data->nbrec_load_balancer_table =
EN_OVSDB_GET(engine_get_input("NB_load_balancer", node));
input_data.nbrec_load_balancer_group_table =
input_data->nbrec_load_balancer_group_table =
EN_OVSDB_GET(engine_get_input("NB_load_balancer_group", node));
input_data.nbrec_port_group_table =
input_data->nbrec_port_group_table =
EN_OVSDB_GET(engine_get_input("NB_port_group", node));
input_data.nbrec_meter_table =
input_data->nbrec_meter_table =
EN_OVSDB_GET(engine_get_input("NB_meter", node));
input_data.nbrec_acl_table =
input_data->nbrec_acl_table =
EN_OVSDB_GET(engine_get_input("NB_acl", node));
input_data.nbrec_static_mac_binding_table =
input_data->nbrec_static_mac_binding_table =
EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node));
input_data.nbrec_chassis_template_var_table =
input_data->nbrec_chassis_template_var_table =
EN_OVSDB_GET(engine_get_input("NB_chassis_template_var", node));
input_data.nbrec_mirror_table =
input_data->nbrec_mirror_table =
EN_OVSDB_GET(engine_get_input("NB_mirror", node));

input_data.sbrec_sb_global_table =
input_data->sbrec_sb_global_table =
EN_OVSDB_GET(engine_get_input("SB_sb_global", node));
input_data.sbrec_datapath_binding_table =
input_data->sbrec_datapath_binding_table =
EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node));
input_data.sbrec_port_binding_table =
input_data->sbrec_port_binding_table =
EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
input_data.sbrec_mac_binding_table =
input_data->sbrec_mac_binding_table =
EN_OVSDB_GET(engine_get_input("SB_mac_binding", node));
input_data.sbrec_ha_chassis_group_table =
input_data->sbrec_ha_chassis_group_table =
EN_OVSDB_GET(engine_get_input("SB_ha_chassis_group", node));
input_data.sbrec_chassis_table =
input_data->sbrec_chassis_table =
EN_OVSDB_GET(engine_get_input("SB_chassis", node));
input_data.sbrec_fdb_table =
input_data->sbrec_fdb_table =
EN_OVSDB_GET(engine_get_input("SB_fdb", node));
input_data.sbrec_load_balancer_table =
input_data->sbrec_load_balancer_table =
EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
input_data.sbrec_service_monitor_table =
input_data->sbrec_service_monitor_table =
EN_OVSDB_GET(engine_get_input("SB_service_monitor", node));
input_data.sbrec_port_group_table =
input_data->sbrec_port_group_table =
EN_OVSDB_GET(engine_get_input("SB_port_group", node));
input_data.sbrec_meter_table =
input_data->sbrec_meter_table =
EN_OVSDB_GET(engine_get_input("SB_meter", node));
input_data.sbrec_dns_table =
input_data->sbrec_dns_table =
EN_OVSDB_GET(engine_get_input("SB_dns", node));
input_data.sbrec_ip_multicast_table =
input_data->sbrec_ip_multicast_table =
EN_OVSDB_GET(engine_get_input("SB_ip_multicast", node));
input_data.sbrec_static_mac_binding_table =
input_data->sbrec_static_mac_binding_table =
EN_OVSDB_GET(engine_get_input("SB_static_mac_binding", node));
input_data.sbrec_chassis_template_var_table =
input_data->sbrec_chassis_template_var_table =
EN_OVSDB_GET(engine_get_input("SB_chassis_template_var", node));
input_data.sbrec_mirror_table =
input_data->sbrec_mirror_table =
EN_OVSDB_GET(engine_get_input("SB_mirror", node));
}

void
en_northd_run(struct engine_node *node, void *data)
{
const struct engine_context *eng_ctx = engine_get_context();

struct northd_input input_data;

northd_destroy(data);
northd_init(data);

northd_get_input_data(node, &input_data);
northd_run(&input_data, data,
eng_ctx->ovnnb_idl_txn,
eng_ctx->ovnsb_idl_txn);
Expand Down Expand Up @@ -148,17 +159,48 @@ northd_nb_nb_global_handler(struct engine_node *node,
return true;
}

void *en_northd_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
bool
northd_nb_logical_switch_handler(struct engine_node *node,
void *data)
{
struct northd_data *data = xmalloc(sizeof *data);
const struct engine_context *eng_ctx = engine_get_context();
struct northd_data *nd = data;

struct northd_input input_data;

northd_get_input_data(node, &input_data);

if (!northd_handle_ls_changes(eng_ctx->ovnsb_idl_txn, &input_data, nd)) {
return false;
}

if (nd->change_tracked) {
engine_set_node_state(node, EN_UPDATED);
}

return true;
}

void
*en_northd_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
{
struct northd_data *data = xzalloc(sizeof *data);

northd_init(data);

return data;
}

void en_northd_cleanup(void *data)
void
en_northd_cleanup(void *data)
{
northd_destroy(data);
}

void
en_northd_clear_tracked_data(void *data_)
{
struct northd_data *data = data_;
destroy_northd_data_tracked_changes(data);
}
2 changes: 2 additions & 0 deletions northd/en-northd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ void en_northd_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED);
void *en_northd_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg);
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);

#endif /* EN_NORTHD_H */
12 changes: 10 additions & 2 deletions northd/inc-proc-northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ enum sb_engine_node {

/* Define engine nodes for other nodes. They should be defined as static to
* avoid sparse errors. */
static ENGINE_NODE(northd, "northd");
static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(northd, "northd");
static ENGINE_NODE(lflow, "lflow");
static ENGINE_NODE(mac_binding_aging, "mac_binding_aging");
static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker");
Expand All @@ -143,7 +143,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
* 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, NULL);
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);
Expand Down Expand Up @@ -252,6 +253,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
"sbrec_address_set_by_name",
sbrec_address_set_by_name);

struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port
= ovsdb_idl_index_create2(sb->idl, &sbrec_fdb_col_dp_key,
&sbrec_fdb_col_port_key);
engine_ovsdb_node_add_index(&en_sb_fdb,
"sbrec_fdb_by_dp_and_port",
sbrec_fdb_by_dp_and_port);

struct northd_data *northd_data =
engine_get_internal_data(&en_northd);
unixctl_command_register("debug/chassis-features-list", "", 0, 0,
Expand Down

0 comments on commit b337750

Please sign in to comment.