}
}
-static int
-lnet_compare_gw_lpnis(struct lnet_peer_ni *p1, struct lnet_peer_ni *p2)
-{
- if (p1->lpni_txqnob < p2->lpni_txqnob)
- return 1;
-
- if (p1->lpni_txqnob > p2->lpni_txqnob)
- return -1;
-
- if (p1->lpni_txcredits > p2->lpni_txcredits)
- return 1;
-
- if (p1->lpni_txcredits < p2->lpni_txcredits)
- return -1;
-
- return 0;
-}
-
static struct lnet_peer_ni *
lnet_select_peer_ni(struct lnet_ni *best_ni, lnet_nid_t dst_nid,
struct lnet_peer *peer,
return NULL;
}
+static int
+lnet_compare_gw_lpnis(struct lnet_peer_ni *lpni1, struct lnet_peer_ni *lpni2)
+{
+ if (lpni1->lpni_txqnob < lpni2->lpni_txqnob)
+ return 1;
+
+ if (lpni1->lpni_txqnob > lpni2->lpni_txqnob)
+ return -1;
+
+ if (lpni1->lpni_txcredits > lpni2->lpni_txcredits)
+ return 1;
+
+ if (lpni1->lpni_txcredits < lpni2->lpni_txcredits)
+ return -1;
+
+ return 0;
+}
+
/* Compare route priorities and hop counts */
static int
lnet_compare_routes(struct lnet_route *r1, struct lnet_route *r2)
static struct lnet_route *
lnet_find_route_locked(struct lnet_remotenet *rnet, __u32 src_net,
+ struct lnet_peer_ni *remote_lpni,
struct lnet_route **prev_route,
struct lnet_peer_ni **gwni)
{
struct lnet_route *last_route;
struct lnet_route *route;
int rc;
+ bool best_rte_is_preferred = false;
+ lnet_nid_t gw_pnid;
CDEBUG(D_NET, "Looking up a route to %s, from %s\n",
libcfs_net2str(rnet->lrn_net), libcfs_net2str(src_net));
list_for_each_entry(route, &rnet->lrn_routes, lr_list) {
if (!lnet_is_route_alive(route))
continue;
+ gw_pnid = route->lr_gateway->lp_primary_nid;
- /*
- * Restrict the selection of the router NI on the src_net
- * provided. If the src_net is LNET_NID_ANY, then select
- * the best interface available.
+ /* no protection on below fields, but it's harmless */
+ if (last_route && (last_route->lr_seq - route->lr_seq < 0))
+ last_route = route;
+
+ /* if the best route found is in the preferred list then
+ * tag it as preferred and use it later on. But if we
+ * didn't find any routes which are on the preferred list
+ * then just use the best route possible.
*/
- if (!best_route) {
+ rc = lnet_peer_is_pref_rtr_locked(remote_lpni, gw_pnid);
+
+ if (!best_route || (rc && !best_rte_is_preferred)) {
+ /* Restrict the selection of the router NI on the
+ * src_net provided. If the src_net is LNET_NID_ANY,
+ * then select the best interface available.
+ */
lpni = lnet_find_best_lpni(NULL, LNET_NID_ANY,
route->lr_gateway,
src_net);
- if (lpni) {
- best_route = last_route = route;
- best_gw_ni = lpni;
- } else {
- CDEBUG(D_NET, "Gateway %s does not have a peer NI on net %s\n",
- libcfs_nid2str(route->lr_gateway->lp_primary_nid),
+ if (!lpni) {
+ CDEBUG(D_NET,
+ "Gateway %s does not have a peer NI on net %s\n",
+ libcfs_nid2str(gw_pnid),
libcfs_net2str(src_net));
+ continue;
}
+ }
+ if (rc && !best_rte_is_preferred) {
+ /* This is the first preferred route we found,
+ * so it beats any route found previously
+ */
+ best_route = route;
+ if (!last_route)
+ last_route = route;
+ best_gw_ni = lpni;
+ best_rte_is_preferred = true;
+ CDEBUG(D_NET, "preferred gw = %s\n",
+ libcfs_nid2str(gw_pnid));
+ continue;
+ } else if ((!rc) && best_rte_is_preferred)
+ /* The best route we found so far is in the preferred
+ * list, so it beats any non-preferred route
+ */
continue;
- }
- /* no protection on below fields, but it's harmless */
- if (last_route->lr_seq - route->lr_seq < 0)
- last_route = route;
+ if (!best_route) {
+ best_route = last_route = route;
+ best_gw_ni = lpni;
+ continue;
+ }
rc = lnet_compare_routes(route, best_route);
if (rc == -1)
continue;
+ /* Restrict the selection of the router NI on the
+ * src_net provided. If the src_net is LNET_NID_ANY,
+ * then select the best interface available.
+ */
lpni = lnet_find_best_lpni(NULL, LNET_NID_ANY,
route->lr_gateway,
src_net);
- /* restrict the lpni on the src_net if specified */
if (!lpni) {
- CDEBUG(D_NET, "Gateway %s does not have a peer NI on net %s\n",
- libcfs_nid2str(route->lr_gateway->lp_primary_nid),
+ CDEBUG(D_NET,
+ "Gateway %s does not have a peer NI on net %s\n",
+ libcfs_nid2str(gw_pnid),
libcfs_net2str(src_net));
continue;
}
lnet_nid_t src_nid = (sd->sd_src_nid != LNET_NID_ANY) ? sd->sd_src_nid :
(sd->sd_best_ni != NULL) ? sd->sd_best_ni->ni_nid :
LNET_NID_ANY;
+ int best_lpn_healthv = 0;
+ __u32 best_lpn_sel_prio = LNET_MAX_SELECTION_PRIORITY;
CDEBUG(D_NET, "using src nid %s for route restriction\n",
libcfs_nid2str(src_nid));
best_rnet = rnet;
}
- if (best_lpn->lpn_seq <= lpn->lpn_seq)
+ /* select the preferred peer net */
+ if (best_lpn_healthv > lpn->lpn_healthv)
continue;
+ else if (best_lpn_healthv < lpn->lpn_healthv)
+ goto use_lpn;
+ if (best_lpn_sel_prio < lpn->lpn_sel_priority)
+ continue;
+ else if (best_lpn_sel_prio > lpn->lpn_sel_priority)
+ goto use_lpn;
+
+ if (best_lpn->lpn_seq <= lpn->lpn_seq)
+ continue;
+use_lpn:
+ best_lpn_healthv = lpn->lpn_healthv;
+ best_lpn_sel_prio = lpn->lpn_sel_priority;
best_lpn = lpn;
best_rnet = rnet;
}
*/
best_route = lnet_find_route_locked(best_rnet,
LNET_NIDNET(src_nid),
+ sd->sd_best_lpni,
&last_route, &gwni);
if (!best_route) {