- rc = lnet_nid2peer_locked(&lp, dst_nid, cpt);
- /* lp has ref on src_ni; lose mine */
- lnet_ni_decref_locked(src_ni, cpt);
- if (rc != 0) {
- lnet_net_unlock(cpt);
- LCONSOLE_WARN("Error %d finding peer %s\n", rc,
- libcfs_nid2str(dst_nid));
- /* ENOMEM or shutting down */
- return rc;
- }
- LASSERT (lp->lp_ni == src_ni);
- } else {
-#ifndef __KERNEL__
+ /* best ni could be set because src_nid was provided */
+ if (!best_ni) {
+ best_ni = lnet_net2ni_locked(best_lpni->lpni_net->net_id, cpt);
+ if (!best_ni) {
+ lnet_net_unlock(cpt);
+ 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;
+ }
+ }
+ }
+
+ /*
+ * if we already found a best_ni because src_nid is specified and
+ * best_lpni because we are replying to a message then just send
+ * the message
+ */
+ if (best_ni && best_lpni)
+ goto send;
+
+ /*
+ * If we already found a best_ni because src_nid is specified then
+ * pick the peer then send the message
+ */
+ if (best_ni)
+ goto pick_peer;
+
+ /*
+ * pick the best_ni by going through all the possible networks of
+ * that peer and see which local NI is best suited to talk to that
+ * peer.
+ *
+ * Locally connected networks will always be preferred over
+ * a routed network. If there are only routed paths to the peer,
+ * then the best route is chosen. If all routes are equal then
+ * they are used in round robin.
+ */
+ list_for_each_entry(peer_net, &peer->lp_peer_nets, lpn_on_peer_list) {
+ if (!lnet_is_peer_net_healthy_locked(peer_net))
+ continue;
+
+ local_net = lnet_get_net_locked(peer_net->lpn_net_id);
+ if (!local_net && !routing && !local_found) {
+ struct lnet_peer_ni *net_gw;
+
+ lpni = list_entry(peer_net->lpn_peer_nis.next,
+ struct lnet_peer_ni,
+ lpni_on_peer_net_list);
+
+ net_gw = lnet_find_route_locked(NULL,
+ lpni->lpni_nid,
+ rtr_nid);
+ if (!net_gw)
+ continue;
+
+ if (best_gw) {
+ /*
+ * lnet_find_route_locked() call
+ * will return the best_Gw on the
+ * lpni->lpni_nid network.
+ * However, best_gw and net_gw can
+ * be on different networks.
+ * Therefore need to compare them
+ * to pick the better of either.
+ */
+ if (lnet_compare_peers(best_gw, net_gw) > 0)
+ continue;
+ if (best_gw->lpni_gw_seq <= net_gw->lpni_gw_seq)
+ continue;
+ }
+ best_gw = net_gw;
+ final_dst = lpni;
+
+ routing2 = true;
+ } else {
+ best_gw = NULL;
+ final_dst = NULL;
+ routing2 = false;
+ local_found = true;
+ }
+
+ /*
+ * a gw on this network is found, but there could be
+ * other better gateways on other networks. So don't pick
+ * the best_ni until we determine the best_gw.
+ */
+ if (best_gw)
+ continue;
+
+ /* if no local_net found continue */
+ if (!local_net)
+ continue;
+
+ /*
+ * Iterate through the NIs in this local Net and select
+ * the NI to send from. The selection is determined by
+ * these 3 criterion in the following priority:
+ * 1. NUMA
+ * 2. NI available credits
+ * 3. Round Robin
+ */
+ best_ni = lnet_get_best_ni(local_net, best_ni, md_cpt);
+ }
+
+ if (!best_ni && !best_gw) {