Improve code efficiency of load-balancer unreachable_ips flows processing when datapath_groups are enabled. We can avoid to perform a flow lookup for each ovn_port in build_lflows_for_unreachable_vips() since lflows only depends on vips (match and action filters). Using this approach (with datapath_groups enabled) we reduced ovn-northd loop time from 12s to 8s (running a production ovn-nb db):
ovn-master: ---------- Statistics for 'ovnnb_db_run' Total samples: 97 Maximum: 12596 msec Minimum: 12324 msec 95th percentile: 12549.921348 msec Short term average: 12438.001085 msec Long term average: 12407.350781 msec ovn-master + flow rework: ------------------------- Statistics for 'ovnnb_db_run' Total samples: 97 Maximum: 8853 msec Minimum: 8533 msec 95th percentile: 8697.718376 msec Short term average: 8608.222669 msec Long term average: 8623.947235 msec ovn-nbctl lr-list | wc -l 121 ovn-nbctl ls-list | wc -l 241 ovn-nbctl lb-list | wc -l 47077 ovn-sbctl dump-flows |wc -l 9852935 Acked-by: Mark Michelson <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> --- northd/ovn-northd.c | 60 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index f4b5a4a61..6c453c450 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -4362,7 +4362,7 @@ static struct hashrow_locks lflow_locks; /* Adds a row with the specified contents to the Logical_Flow table. * Version to use when locking is required. */ -static void +static struct ovn_lflow * do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, uint32_t hash, enum ovn_stage stage, uint16_t priority, const char *match, const char *actions, const char *io_port, @@ -4378,7 +4378,7 @@ do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, actions, ctrl_meter, hash); if (old_lflow) { hmapx_add(&old_lflow->od_group, od); - return; + return old_lflow; } } @@ -4397,10 +4397,11 @@ do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, } else { hmap_insert_fast(lflow_map, &lflow->hmap_node, hash); } + return lflow; } /* Adds a row with the specified contents to the Logical_Flow table. */ -static void +static struct ovn_lflow * ovn_lflow_add_at_with_hash(struct hmap *lflow_map, struct ovn_datapath *od, enum ovn_stage stage, uint16_t priority, const char *match, const char *actions, @@ -4408,16 +4409,21 @@ ovn_lflow_add_at_with_hash(struct hmap *lflow_map, struct ovn_datapath *od, const struct ovsdb_idl_row *stage_hint, const char *where, uint32_t hash) { + struct ovn_lflow *lflow; + ovs_assert(ovn_stage_to_datapath_type(stage) == ovn_datapath_get_type(od)); if (use_logical_dp_groups && use_parallel_build) { lock_hash_row(&lflow_locks, hash); - do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, - actions, io_port, stage_hint, where, ctrl_meter); + lflow = do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, + actions, io_port, stage_hint, where, + ctrl_meter); unlock_hash_row(&lflow_locks, hash); } else { - do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, - actions, io_port, stage_hint, where, ctrl_meter); + lflow = do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, + actions, io_port, stage_hint, where, + ctrl_meter); } + return lflow; } static void @@ -9441,6 +9447,26 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb *lb, ds_destroy(&defrag_actions); } +static bool +ovn_dp_group_update_with_reference(struct ovn_lflow *lflow_ref, + struct ovn_datapath *od, + uint32_t hash) +{ + if (!use_logical_dp_groups || !lflow_ref) { + return false; + } + + if (use_parallel_build) { + lock_hash_row(&lflow_locks, hash); + hmapx_add(&lflow_ref->od_group, od); + unlock_hash_row(&lflow_locks, hash); + } else { + hmapx_add(&lflow_ref->od_group, od); + } + + return true; +} + static void build_lflows_for_unreachable_vips(struct ovn_northd_lb *lb, struct ovn_lb_vip *lb_vip, @@ -9450,6 +9476,7 @@ build_lflows_for_unreachable_vips(struct ovn_northd_lb *lb, { static const char *action = "outport = _MC_flood; output;"; bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip); + struct ovn_lflow *lflow_ref = NULL; ovs_be32 ipv4_addr; ds_clear(match); @@ -9495,11 +9522,20 @@ build_lflows_for_unreachable_vips(struct ovn_northd_lb *lb, (!ipv4 && lrouter_port_ipv6_reachable(op, &lb_vip->vip))) { continue; } - ovn_lflow_add_at_with_hash(lflows, peer->od, - S_SWITCH_IN_L2_LKUP, 90, - ds_cstr(match), action, - NULL, NULL, &peer->nbsp->header_, - OVS_SOURCE_LOCATOR, hash); + + if (ovn_dp_group_update_with_reference(lflow_ref, od, hash)) { + /* if we are running dp_groups, we do not need to run full + * lookup since lflow just depends on the vip and not on + * the ovn_port. + */ + continue; + } + lflow_ref = ovn_lflow_add_at_with_hash(lflows, peer->od, + S_SWITCH_IN_L2_LKUP, 90, + ds_cstr(match), action, + NULL, NULL, + &peer->nbsp->header_, + OVS_SOURCE_LOCATOR, hash); } } } -- 2.31.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
