}
static int
-lnet_compare_peers(struct lnet_peer_ni *p1, struct lnet_peer_ni *p2)
+lnet_compare_gw_lpnis(struct lnet_peer_ni *p1, struct lnet_peer_ni *p2)
{
if (p1->lpni_txqnob < p2->lpni_txqnob)
return 1;
return lnet_select_peer_ni(lni, dst_nid, peer, peer_net);
}
+/* Compare route priorities and hop counts */
static int
-lnet_compare_routes(struct lnet_route *r1, struct lnet_route *r2,
- struct lnet_peer_ni **best_lpni)
+lnet_compare_routes(struct lnet_route *r1, struct lnet_route *r2)
{
int r1_hops = (r1->lr_hops == LNET_UNDEFINED_HOPS) ? 1 : r1->lr_hops;
int r2_hops = (r2->lr_hops == LNET_UNDEFINED_HOPS) ? 1 : r2->lr_hops;
- struct lnet_peer *lp1 = r1->lr_gateway;
- struct lnet_peer *lp2 = r2->lr_gateway;
- struct lnet_peer_ni *lpni1;
- struct lnet_peer_ni *lpni2;
- int rc;
-
- lpni1 = lnet_find_best_lpni_on_net(NULL, LNET_NID_ANY, lp1,
- r1->lr_lnet);
- lpni2 = lnet_find_best_lpni_on_net(NULL, LNET_NID_ANY, lp2,
- r2->lr_lnet);
- LASSERT(lpni1 && lpni2);
- if (r1->lr_priority < r2->lr_priority) {
- *best_lpni = lpni1;
+ if (r1->lr_priority < r2->lr_priority)
return 1;
- }
- if (r1->lr_priority > r2->lr_priority) {
- *best_lpni = lpni2;
+ if (r1->lr_priority > r2->lr_priority)
return -1;
- }
- if (r1_hops < r2_hops) {
- *best_lpni = lpni1;
+ if (r1_hops < r2_hops)
return 1;
- }
- if (r1_hops > r2_hops) {
- *best_lpni = lpni2;
+ if (r1_hops > r2_hops)
return -1;
- }
-
- rc = lnet_compare_peers(lpni1, lpni2);
- if (rc == 1) {
- *best_lpni = lpni1;
- return rc;
- } else if (rc == -1) {
- *best_lpni = lpni2;
- return rc;
- }
- if (r1->lr_seq - r2->lr_seq <= 0) {
- *best_lpni = lpni1;
- return 1;
- }
-
- *best_lpni = lpni2;
- return -1;
+ return 0;
}
static struct lnet_route *
-lnet_find_route_locked(struct lnet_net *net, __u32 remote_net,
+lnet_find_route_locked(struct lnet_remotenet *rnet, __u32 src_net,
struct lnet_route **prev_route,
struct lnet_peer_ni **gwni)
{
- struct lnet_peer_ni *best_gw_ni = NULL;
+ struct lnet_peer_ni *lpni, *best_gw_ni = NULL;
struct lnet_route *best_route;
struct lnet_route *last_route;
- struct lnet_remotenet *rnet;
- struct lnet_peer *lp_best;
struct lnet_route *route;
- struct lnet_peer *lp;
int rc;
+ __u32 restrict_net;
+ __u32 any_net = LNET_NIDNET(LNET_NID_ANY);
- rnet = lnet_find_rnet_locked(remote_net);
- if (rnet == NULL)
- return NULL;
-
- lp_best = NULL;
best_route = last_route = NULL;
list_for_each_entry(route, &rnet->lrn_routes, lr_list) {
- lp = route->lr_gateway;
-
if (!lnet_is_route_alive(route))
continue;
- if (lp_best == NULL) {
- best_route = last_route = route;
- lp_best = lp;
+ /* If the src_net is specified then we need to find an lpni
+ * on that network
+ */
+ restrict_net = src_net == any_net ? route->lr_lnet : src_net;
+ if (!best_route) {
+ lpni = lnet_find_best_lpni_on_net(NULL, LNET_NID_ANY,
+ route->lr_gateway,
+ restrict_net);
+ if (lpni) {
+ best_route = last_route = route;
+ best_gw_ni = lpni;
+ } else
+ CERROR("Gateway %s does not have a peer NI on net %s\n",
+ libcfs_nid2str(route->lr_gateway->lp_primary_nid),
+ libcfs_net2str(restrict_net));
+
+ continue;
}
/* no protection on below fields, but it's harmless */
if (last_route->lr_seq - route->lr_seq < 0)
last_route = route;
- rc = lnet_compare_routes(route, best_route, &best_gw_ni);
- if (rc < 0)
+ rc = lnet_compare_routes(route, best_route);
+ if (rc == -1)
continue;
- best_route = route;
- lp_best = lp;
+ lpni = lnet_find_best_lpni_on_net(NULL, LNET_NID_ANY,
+ route->lr_gateway,
+ restrict_net);
+ if (!lpni) {
+ CERROR("Gateway %s does not have a peer NI on net %s\n",
+ libcfs_nid2str(route->lr_gateway->lp_primary_nid),
+ libcfs_net2str(restrict_net));
+ continue;
+ }
+
+ if (rc == 1) {
+ best_route = route;
+ best_gw_ni = lpni;
+ continue;
+ }
+
+ rc = lnet_compare_gw_lpnis(lpni, best_gw_ni);
+ if (rc == -1)
+ continue;
+
+ if (rc == 1 || route->lr_seq <= best_route->lr_seq) {
+ best_route = route;
+ best_gw_ni = lpni;
+ continue;
+ }
}
*prev_route = last_route;
struct lnet_peer *lp;
struct lnet_peer_net *lpn;
struct lnet_peer_net *best_lpn = NULL;
- struct lnet_remotenet *rnet;
+ struct lnet_remotenet *rnet, *best_rnet = NULL;
struct lnet_route *best_route = NULL;
struct lnet_route *last_route = NULL;
struct lnet_peer_ni *lpni = NULL;
if (!rnet)
continue;
- if (!best_lpn)
+ if (!best_lpn) {
best_lpn = lpn;
+ best_rnet = rnet;
+ }
if (best_lpn->lpn_seq <= lpn->lpn_seq)
continue;
best_lpn = lpn;
+ best_rnet = rnet;
}
if (!best_lpn) {
return -EHOSTUNREACH;
}
- best_route = lnet_find_route_locked(NULL, best_lpn->lpn_net_id,
+ best_route = lnet_find_route_locked(best_rnet,
+ LNET_NIDNET(src_nid),
&last_route, &gwni);
if (!best_route) {
CERROR("no route to %s from %s\n",
again:
/*
- * If we're sending to ourselves then there is no need to go through
- * any selection. We can shortcut the entire process and send over
- * lolnd.
- *
- * However, we make two exceptions to this rule:
- * 1. If the src_nid is specified then our API defines that we must send
- * via that interface.
- * 2. Recovery messages must be sent to the lnet_ni that is being
- * recovered.
+ * If we're being asked to send to the loopback interface, there
+ * is no need to go through any selection. We can just shortcut
+ * the entire process and send over lolnd
*/
send_data.sd_msg = msg;
send_data.sd_cpt = cpt;
- if (src_nid == LNET_NID_ANY && !msg->msg_recovery &&
- lnet_nid2ni_locked(dst_nid, cpt)) {
+ if (LNET_NETTYP(LNET_NIDNET(dst_nid)) == LOLND) {
rc = lnet_handle_lo_send(&send_data);
lnet_net_unlock(cpt);
return rc;
struct lnet_libmd *md, struct lnet_handle_md mdh)
{
s64 timeout_ns;
- bool new_entry = true;
struct lnet_rsp_tracker *local_rspt;
/*
* update the deadline on that one.
*/
lnet_rspt_free(rspt, cpt);
- new_entry = false;
} else {
/* new md */
rspt->rspt_mdh = mdh;
* list in order to expire all the older entries first.
*/
lnet_net_lock(cpt);
- if (!new_entry && !list_empty(&local_rspt->rspt_on_list))
- list_del_init(&local_rspt->rspt_on_list);
- list_add_tail(&local_rspt->rspt_on_list, the_lnet.ln_mt_rstq[cpt]);
+ list_move_tail(&local_rspt->rspt_on_list, the_lnet.ln_mt_rstq[cpt]);
lnet_net_unlock(cpt);
lnet_res_unlock(cpt);
}