Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Kernel Selection Algorithm Modifications

Code Block
static inline int
lnet_get_peer_net_health(struct lnet_peer_net *lpn)
{
	/*
	 * The peer net is highest health value of all lpnis in the peer
	 * This is a value which will be maintained when the lpni health
	 * value is updated.
	 */
	return lpn->lpn_health;
}


/*
 * select an NI from the Nets with highest priority
 */
struct lnet_ni *
lnet_find_best_ni_on_local_net(struct lnet_peer *peer, int md_cpt)
{
...
	/*
	 * All criteria are defaulted at the beginning of the loop such that
	 * the first peer_net is selected and then overwritten if there is a 
	 * better peer_net found
	 */
	list_for_each_entry(peer_net, &peer->lp_peer_nets, lpn_peer_nets) {
	...
		struct lnet_net *net;


_peer_nets) {
	...
		struct lnet_net *net;


		best_peer_net = peer_net;

		/* get the the health of a peer net */
		peer_net_health = lnet_get_peer_net_health(peer_net);
		if (peer_net_health < best_peer_net_health)
			continue;
		else if (peer_net_health > best_peer_net_health)
			best_peer_net_health = peer_net_health;
			
		/* consider only highest priority peer_net */
		peer_net_prio = peer_net->lpn_priority;
		else if (peer_net_prio > best_peer_net_prio)
			continue;
		else if (peer_net_prio < best_peer_net_prio)
			peer_net_prio = best_peer_net_prio;
		net = lnet_get_net_locked(peer_net->lpn_net_id);
		if (!best_net)
			continue

		net_prio = net->net_priority;
		/*
		 * look only at the Nets with the highest priority and disregard
		 * nets which have lower priority. Nets with equal priority are
		 * examined and the best_ni is selected from amongst them.
		 */
		net_prio = net->net_priority;
		 equal priority are
		 * examined and the best_ni is selected from amongst them.
		 */
		net_health = lnet_get_local_net_health(net)
		if (net_health < best_net_health)
			continue;
		else if (net_health > best_net_health)
			best_net_health = net_health;
		else if (net_prio > best_net_prio)
			continue;
		else if (net_prio < best_net_prio) {
			best_net_prio = net_prio;


			best_ninet = NULL;net
	...
	}
	if (!best_net || !best_peer_net)
		goto fail;


	best_ni = lnet_find_best_ni_on_spec_net(best_niNULL, peer,
											    best_peer_net, md_cpt, false);
	...
	}
...
}

/*
 * select the NI with the highest priority 
 */
static struct lnet_ni *
lnet_get_best_ni(struct lnet_net *local_net, struct lnet_ni *best_ni,
				 struct lnet_peer *peer, struct lnet_peer_net *peer_net,
				 int md_cpt)
{
...
	ni_prio = ni->ni_priority;

	if (ni_fatal) {
		continue;
	} else if (ni_healthv < best_healthv) {
		continue;
	} else if (ni_healthv > best_healthv) {
		best_healthv = ni_healthv;
		if (distance < shortest_distance)
			shortest_distance = distance;
	/*
	 * if this NI is lower in priority than the one already set then discard it
 	 * otherwise use it and set the best priority so far to this NI's.
	 */
	} else if ni_prio > best_ni_prio) {
		continue;
	} else if (ni_prio < best_ni_prio)
		best_ni_prio = ni_prio;
	}

...
}

/*
 * When a UDSP rule associates local NIs with remote NIs, the list of local NIs NIDs
 * is flattened to a list in the associated peer_NI. When selecting a peer NI, the
 * peer NI with the corresponding preferred local NI is selected.
 */
bool
lnet_peer_is_pref_nid_locked(struct lnet_peer_ni *lpni, lnet_nid_t nid)
{
...
}

/*
 * select the peer NI with the highest priority first and then check
 * if it's preferred.
 */ 
static struct lnet_peer_ni *
lnet_select_peer_ni(struct lnet_send_data *sd, struct lnet_peer *peer,
					struct lnet_peer_net *peer_net)
{
...
	ni_is_pref = lnet_peer_is_pref_nid_locked(lpni, best_ni->ni_nid);

	lpni_prio = lpni->lpni_priority;

	if (lpni_healthv < best_lpni_healthv)
		continue;
	/*
	 * select the NI with the highest priority.
	 */
	else if lpni_prio > best_lpni_prio)
		continue;
	else if (lpni_prio < best_lpni_prio)
		best_lpni_prio = lpni_prio;
	/*
	 * select the NI which has the best_ni's NID in its preferred list
	 */
	else if (!preferred && ni_is_pref)
		preferred = true;
...
} 


static int
lnet_handle_find_routed_path(struct lnet_send_data *sd,
							 lnet_nid_t dst_nid,
							 struct lnet_peer_ni **gw_lpni,
							 struct lnet_peer **gw_peer)
{
...
	lpni = lnet_find_peer_ni_locked(dst_nid);
	peer = lpni->lpni_net->lpn_peer;
	list_for_each_entry(peer_net, &peer->lp_peer_nets, lpn_peer_nets) {
		peer_net_priority = peer_net->lpn_priority;
		if (peer_net_priority > peer_net_best_priority)
			continue;
		else if (peer_net_priority < peer_net_best_priority)
			peer_net_best_priority = peer_net_priority;
		lpni = NULL;
		while ((lpni = lnet_get_next_peer_ni_locked(peer, peer_net, lpni)) {
			/* find best gw for this lpni */
			lpni_prio = lpni->lpni_priority;
			if (lpni_prio > lpni_best_prio)
				continue;
			else if (lpni_prio < lpni_best_prio)
				lpni_best_prio = lpni_prio;


			/*
			 * lnet_find_route_locked will be changed to consider the list of
			 * gw NIDs on the lpni
			 */
			gw = lnet_find_route_locked(NULL, lpni, sd->sd_rtr_nid);
			...
			/*
			 * if gw is MR then select best_NI. Increment the sequence number of
			 * the gw NI for Round Robin selection.
		 	 */
			...
		}
	}
...
}

...