__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] %s LPNI seq info [%d:%d:%d]\n",
+ libcfs_nid2str(best_ni->ni_nid),
+ best_ni->ni_seq, best_ni->ni_net->net_seq,
+ atomic_read(&best_ni->ni_tx_credits),
+ libcfs_nid2str(best_lpni->lpni_nid),
+ best_lpni->lpni_seq, best_lpni->lpni_peer_net->lpn_seq,
+ best_lpni->lpni_txcredits);
/*
* grab a reference on the peer_ni so it sticks around even if
struct lnet_peer *peer,
struct lnet_peer_net *peer_net,
struct lnet_msg *msg,
- int cpt,
- bool incr_seq)
+ int cpt)
{
struct lnet_net *local_net;
struct lnet_ni *best_ni;
best_ni = lnet_get_best_ni(local_net, cur_best_ni,
peer, peer_net, msg, cpt);
- if (incr_seq && best_ni)
- best_ni->ni_seq++;
-
return best_ni;
}
lpn = gwni->lpni_peer_net;
sd->sd_best_ni = lnet_find_best_ni_on_spec_net(NULL, gw, lpn,
sd->sd_msg,
- 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",
libcfs_net2str(lpn->lpn_net_id),
lnet_find_best_ni_on_local_net(struct lnet_peer *peer, struct lnet_msg *msg,
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;
+ bool exit = false;
/*
* The peer can have multiple interfaces, some of them can be on
*/
/* 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,
- msg, md_cpt, false);
+ net_healthv = lnet_get_net_healthv_locked(net);
/*
* 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)
- break;
+ 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_net_healthv > net_healthv)
+ continue;
+ else if (best_net_healthv < net_healthv)
+ goto select_lpn;
+
+ if (best_lpn->lpn_seq < lpn->lpn_seq)
+ continue;
+ else if (best_lpn->lpn_seq > lpn->lpn_seq)
+ goto select_lpn;
- best_ni = lnet_find_best_ni_on_spec_net(best_ni, peer,
- peer_net, msg, md_cpt,
- false);
+ /* round robin over the local networks */
+ if (best_net->net_seq <= net->net_seq)
+ continue;
+
+select_lpn:
+ best_net_healthv = net_healthv;
+ best_lpn_healthv = lpn->lpn_healthv;
+ 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, msg, md_cpt);
+ }
return best_ni;
}
lnet_select_preferred_best_ni(struct lnet_send_data *sd)
{
struct lnet_ni *best_ni = NULL;
+ struct lnet_peer_ni *best_lpni = sd->sd_best_lpni;
/*
* We must use a consistent source address when sending to a
best_ni = lnet_find_existing_preferred_best_ni(sd->sd_best_lpni,
sd->sd_cpt);
- if (!best_ni)
- best_ni = lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer,
- sd->sd_best_lpni->lpni_peer_net,
- sd->sd_msg,
- sd->sd_md_cpt,
- true);
-
/* If there is no best_ni we don't have a route */
if (!best_ni) {
- CERROR("no path to %s from net %s\n",
- libcfs_nid2str(sd->sd_best_lpni->lpni_nid),
- libcfs_net2str(sd->sd_best_lpni->lpni_net->net_id));
- return -EHOSTUNREACH;
+ best_ni =
+ lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer,
+ sd->sd_best_lpni->lpni_peer_net,
+ sd->sd_msg,
+ 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",
+ libcfs_nid2str(best_lpni->lpni_nid),
+ libcfs_net2str(best_lpni->lpni_net->net_id));
+ return -EHOSTUNREACH;
+ }
}
sd->sd_best_ni = best_ni;
sd->sd_peer,
sd->sd_best_lpni->lpni_peer_net,
sd->sd_msg,
- 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));
sd->sd_best_ni =
lnet_find_best_ni_on_spec_net(NULL, sd->sd_peer,
sd->sd_best_lpni->lpni_peer_net,
- sd->sd_msg, sd->sd_md_cpt,
- true);
+ sd->sd_msg, sd->sd_md_cpt);
if (!sd->sd_best_ni) {
/*