From 7d309d57fd843f101d0d4954c810adbdd4eac632 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Fri, 15 Feb 2019 17:59:40 -0800 Subject: [PATCH] LU-9121 lnet: select best peer and local net Select the healthiest and highest priority peer and local net when sending a message. Test-Parameters: trivial testlist=lnet-selftest,sanity-lnet Signed-off-by: Amir Shehata Change-Id: I42717e7fdc3226c6faa7c59c713f18422e27f2e5 Reviewed-on: https://review.whamcloud.com/34352 Reviewed-by: Chris Horn Reviewed-by: Serguei Smirnov Tested-by: jenkins --- lnet/include/lnet/lib-lnet.h | 1 + lnet/include/lnet/lib-types.h | 3 + lnet/lnet/api-ni.c | 15 +++++ lnet/lnet/lib-move.c | 126 +++++++++++++++++++++++++++++++----------- 4 files changed, 114 insertions(+), 31 deletions(-) diff --git a/lnet/include/lnet/lib-lnet.h b/lnet/include/lnet/lib-lnet.h index eb5dc88..ee7d049 100644 --- a/lnet/include/lnet/lib-lnet.h +++ b/lnet/include/lnet/lib-lnet.h @@ -548,6 +548,7 @@ int lnet_get_rtr_pool_cfg(int idx, struct lnet_ioctl_pool_cfg *pool_cfg); struct lnet_ni *lnet_get_next_ni_locked(struct lnet_net *mynet, struct lnet_ni *prev); struct lnet_ni *lnet_get_ni_idx_locked(int idx); +int lnet_get_net_healthv_locked(struct lnet_net *net); extern int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, struct libcfs_ioctl_hdr __user *uparam); diff --git a/lnet/include/lnet/lib-types.h b/lnet/include/lnet/lib-types.h index 385fcd3..22a1bdd 100644 --- a/lnet/include/lnet/lib-types.h +++ b/lnet/include/lnet/lib-types.h @@ -370,6 +370,9 @@ struct lnet_net { * lnet/include/lnet/nidstr.h */ __u32 net_id; + /* round robin selection */ + __u32 net_seq; + /* total number of CPTs in the array */ __u32 net_ncpts; diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index fea321c..e43ef0c 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -3006,6 +3006,21 @@ lnet_get_ni_idx_locked(int idx) return NULL; } +int lnet_get_net_healthv_locked(struct lnet_net *net) +{ + struct lnet_ni *ni; + int best_healthv = 0; + int healthv; + + list_for_each_entry(ni, &net->net_ni_list, ni_netlist) { + healthv = atomic_read(&ni->ni_healthv); + if (healthv > best_healthv) + best_healthv = healthv; + } + + return best_healthv; +} + struct lnet_ni * lnet_get_next_ni_locked(struct lnet_net *mynet, struct lnet_ni *prev) { diff --git a/lnet/lnet/lib-move.c b/lnet/lnet/lib-move.c index a82dbbe..5757b82 100644 --- a/lnet/lnet/lib-move.c +++ b/lnet/lnet/lib-move.c @@ -1787,11 +1787,24 @@ lnet_handle_send(struct lnet_send_data *sd) __u32 routing = send_case & REMOTE_DST; struct lnet_rsp_tracker *rspt; - /* - * Increment sequence number of the selected peer so that we - * pick the next one in Round Robin. + /* Increment sequence number of the selected peer, peer net, + * local ni and local net so that we pick the next ones + * in Round Robin. */ best_lpni->lpni_seq++; + best_lpni->lpni_peer_net->lpn_seq++; + best_ni->ni_seq++; + best_ni->ni_net->net_seq++; + + CDEBUG(D_NET, "%s NI seq info: [%d:%d:%d:%u] %s LPNI seq info [%d:%d:%d:%u]\n", + libcfs_nid2str(best_ni->ni_nid), + best_ni->ni_seq, best_ni->ni_net->net_seq, + atomic_read(&best_ni->ni_tx_credits), + best_ni->ni_sel_priority, + libcfs_nid2str(best_lpni->lpni_nid), + best_lpni->lpni_seq, best_lpni->lpni_peer_net->lpn_seq, + best_lpni->lpni_txcredits, + best_lpni->lpni_sel_priority); /* * grab a reference on the peer_ni so it sticks around even if @@ -1985,8 +1998,7 @@ struct lnet_ni * lnet_find_best_ni_on_spec_net(struct lnet_ni *cur_best_ni, struct lnet_peer *peer, struct lnet_peer_net *peer_net, - int cpt, - bool incr_seq) + int cpt) { struct lnet_net *local_net; struct lnet_ni *best_ni; @@ -2006,9 +2018,6 @@ lnet_find_best_ni_on_spec_net(struct lnet_ni *cur_best_ni, best_ni = lnet_get_best_ni(local_net, cur_best_ni, peer, peer_net, cpt); - if (incr_seq && best_ni) - best_ni->ni_seq++; - return best_ni; } @@ -2232,8 +2241,7 @@ use_lpn: sd->sd_best_ni = lnet_find_best_ni_on_spec_net(NULL, gw, lnet_peer_get_net_locked(gw, local_lnet), - sd->sd_md_cpt, - true); + sd->sd_md_cpt); if (!sd->sd_best_ni) { CERROR("Internal Error. Expected local ni on %s but non found :%s\n", @@ -2318,9 +2326,19 @@ struct lnet_ni * lnet_find_best_ni_on_local_net(struct lnet_peer *peer, int md_cpt, bool discovery) { - struct lnet_peer_net *peer_net = NULL; + struct lnet_peer_net *lpn = NULL; + struct lnet_peer_net *best_lpn = NULL; + struct lnet_net *net = NULL; + struct lnet_net *best_net = NULL; struct lnet_ni *best_ni = NULL; - int lpn_healthv = 0; + int best_lpn_healthv = 0; + int best_net_healthv = 0; + int net_healthv; + __u32 best_lpn_sel_prio = LNET_MAX_SELECTION_PRIORITY; + __u32 lpn_sel_prio; + __u32 best_net_sel_prio = LNET_MAX_SELECTION_PRIORITY; + __u32 net_sel_prio; + bool exit = false; /* * The peer can have multiple interfaces, some of them can be on @@ -2330,35 +2348,82 @@ lnet_find_best_ni_on_local_net(struct lnet_peer *peer, int md_cpt, */ /* go through all the peer nets and find the best_ni */ - list_for_each_entry(peer_net, &peer->lp_peer_nets, lpn_peer_nets) { + list_for_each_entry(lpn, &peer->lp_peer_nets, lpn_peer_nets) { /* * The peer's list of nets can contain non-local nets. We * want to only examine the local ones. */ - if (!lnet_get_net_locked(peer_net->lpn_net_id)) + net = lnet_get_net_locked(lpn->lpn_net_id); + if (!net) continue; - /* always select the lpn with the best health */ - if (lpn_healthv <= peer_net->lpn_healthv) - lpn_healthv = peer_net->lpn_healthv; - else - continue; - - best_ni = lnet_find_best_ni_on_spec_net(best_ni, peer, peer_net, - md_cpt, false); + lpn_sel_prio = lpn->lpn_sel_priority; + net_healthv = lnet_get_net_healthv_locked(net); + net_sel_prio = net->net_sel_priority; /* * if this is a discovery message and lp_disc_net_id is * specified then use that net to send the discovery on. */ - if (peer->lp_disc_net_id == peer_net->lpn_net_id && - discovery) + if (peer->lp_disc_net_id == lpn->lpn_net_id && + discovery) { + exit = true; + goto select_lpn; + } + + if (!best_lpn) + goto select_lpn; + + /* always select the lpn with the best health */ + if (best_lpn_healthv > lpn->lpn_healthv) + continue; + else if (best_lpn_healthv < lpn->lpn_healthv) + goto select_lpn; + + /* select the preferred peer and local nets */ + if (best_lpn_sel_prio < lpn_sel_prio) + continue; + else if (best_lpn_sel_prio > lpn_sel_prio) + goto select_lpn; + + if (best_net_healthv > net_healthv) + continue; + else if (best_net_healthv < net_healthv) + goto select_lpn; + + if (best_net_sel_prio < net_sel_prio) + continue; + else if (best_net_sel_prio > net_sel_prio) + goto select_lpn; + + if (best_lpn->lpn_seq < lpn->lpn_seq) + continue; + else if (best_lpn->lpn_seq > lpn->lpn_seq) + goto select_lpn; + + /* round robin over the local networks */ + if (best_net->net_seq <= net->net_seq) + continue; + +select_lpn: + best_net_healthv = net_healthv; + best_net_sel_prio = net_sel_prio; + best_lpn_healthv = lpn->lpn_healthv; + best_lpn_sel_prio = lpn_sel_prio; + best_lpn = lpn; + best_net = net; + + if (exit) break; } - if (best_ni) - /* increment sequence number so we can round robin */ - best_ni->ni_seq++; + if (best_lpn) { + /* Select the best NI on the same net as best_lpn chosen + * above + */ + best_ni = lnet_find_best_ni_on_spec_net(NULL, peer, + best_lpn, md_cpt); + } return best_ni; } @@ -2419,7 +2484,7 @@ lnet_select_preferred_best_ni(struct lnet_send_data *sd) best_ni = lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer, sd->sd_best_lpni->lpni_peer_net, - sd->sd_md_cpt, true); + sd->sd_md_cpt); /* If there is no best_ni we don't have a route */ if (!best_ni) { CERROR("no path to %s from net %s\n", @@ -2475,8 +2540,7 @@ lnet_handle_any_local_nmr_dst(struct lnet_send_data *sd) sd->sd_best_ni = lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer, sd->sd_best_lpni->lpni_peer_net, - sd->sd_md_cpt, - true); + sd->sd_md_cpt); if (!sd->sd_best_ni) { CERROR("Unable to forward message to %s. No local NI available\n", libcfs_nid2str(sd->sd_dst_nid)); @@ -2509,7 +2573,7 @@ lnet_handle_any_mr_dsta(struct lnet_send_data *sd) sd->sd_best_ni = lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer, sd->sd_best_lpni->lpni_peer_net, - sd->sd_md_cpt, true); + sd->sd_md_cpt); if (!sd->sd_best_ni) { /* -- 1.8.3.1