tipc: introduce link entry structure to struct tipc_node

struct 'tipc_node' currently contains two arrays for link attributes,
one for the link pointers, and one for the usable link MTUs.

We now group those into a new struct 'tipc_link_entry', and intoduce
one single array consisting of such enties. Apart from being a cosmetic
improvement, this is a starting point for the strict master-slave
relation between node and link that we will introduce in the following
commits.

Reviewed-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 0b1d61a..db46e5d 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -224,126 +224,119 @@
  *
  * Link becomes active (alone or shared) or standby, depending on its priority.
  */
-void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
+void tipc_node_link_up(struct tipc_node *n, int bearer_id)
 {
-	struct tipc_link **active = &n_ptr->active_links[0];
+	struct tipc_link_entry **actv = &n->active_links[0];
+	struct tipc_link_entry *le = &n->links[bearer_id];
+	struct tipc_link *l = le->link;
 
-	n_ptr->working_links++;
-	n_ptr->action_flags |= TIPC_NOTIFY_LINK_UP;
-	n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;
+	/* Leave room for tunnel header when returning 'mtu' to users: */
+	n->links[bearer_id].mtu = l->mtu - INT_H_SIZE;
+
+	n->working_links++;
+	n->action_flags |= TIPC_NOTIFY_LINK_UP;
+	n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
 
 	pr_debug("Established link <%s> on network plane %c\n",
-		 l_ptr->name, l_ptr->net_plane);
+		 l->name, l->net_plane);
 
-	if (!active[0]) {
-		active[0] = active[1] = l_ptr;
-		node_established_contact(n_ptr);
-		goto exit;
+	/* No active links ? => take both active slots */
+	if (!actv[0]) {
+		actv[0] = le;
+		actv[1] = le;
+		node_established_contact(n);
+		return;
 	}
-	if (l_ptr->priority < active[0]->priority) {
-		pr_debug("New link <%s> becomes standby\n", l_ptr->name);
-		goto exit;
+	if (l->priority < actv[0]->link->priority) {
+		pr_debug("New link <%s> becomes standby\n", l->name);
+		return;
 	}
-	tipc_link_dup_queue_xmit(active[0], l_ptr);
-	if (l_ptr->priority == active[0]->priority) {
-		active[0] = l_ptr;
-		goto exit;
+	tipc_link_dup_queue_xmit(actv[0]->link, l);
+
+	/* Take one active slot if applicable */
+	if (l->priority == actv[0]->link->priority) {
+		actv[0] = le;
+		return;
 	}
-	pr_debug("Old link <%s> becomes standby\n", active[0]->name);
-	if (active[1] != active[0])
-		pr_debug("Old link <%s> becomes standby\n", active[1]->name);
-	active[0] = active[1] = l_ptr;
-exit:
-	/* Leave room for changeover header when returning 'mtu' to users: */
-	n_ptr->act_mtus[0] = active[0]->mtu - INT_H_SIZE;
-	n_ptr->act_mtus[1] = active[1]->mtu - INT_H_SIZE;
+	/* Higher prio than current active? => take both active slots */
+	pr_debug("Old l <%s> becomes standby\n", actv[0]->link->name);
+	if (actv[1] != actv[0])
+		pr_debug("Old link <%s> now standby\n", actv[1]->link->name);
+	actv[0] = le;
+	actv[1] = le;
 }
 
 /**
- * node_select_active_links - select active link
+ * node_select_active_links - select which working links should be active
  */
-static void node_select_active_links(struct tipc_node *n_ptr)
+static void node_select_active_links(struct tipc_node *n)
 {
-	struct tipc_link **active = &n_ptr->active_links[0];
-	u32 i;
-	u32 highest_prio = 0;
+	struct tipc_link_entry **actv = &n->active_links[0];
+	struct tipc_link *l;
+	u32 b, highest = 0;
 
-	active[0] = active[1] = NULL;
+	actv[0] = NULL;
+	actv[1] = NULL;
 
-	for (i = 0; i < MAX_BEARERS; i++) {
-		struct tipc_link *l_ptr = n_ptr->links[i];
-
-		if (!l_ptr || !tipc_link_is_up(l_ptr) ||
-		    (l_ptr->priority < highest_prio))
+	for (b = 0; b < MAX_BEARERS; b++) {
+		l = n->links[b].link;
+		if (!l || !tipc_link_is_up(l) || (l->priority < highest))
 			continue;
-
-		if (l_ptr->priority > highest_prio) {
-			highest_prio = l_ptr->priority;
-			active[0] = active[1] = l_ptr;
-		} else {
-			active[1] = l_ptr;
+		if (l->priority > highest) {
+			highest = l->priority;
+			actv[0] = &n->links[b];
+			actv[1] = &n->links[b];
+			continue;
 		}
+		actv[1] = &n->links[b];
 	}
 }
 
 /**
  * tipc_node_link_down - handle loss of link
  */
-void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
+void tipc_node_link_down(struct tipc_node *n, int bearer_id)
 {
-	struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id);
-	struct tipc_link **active;
+	struct tipc_link_entry **actv = &n->active_links[0];
+	struct tipc_link_entry *le = &n->links[bearer_id];
+	struct tipc_link *l = le->link;
 
-	n_ptr->working_links--;
-	n_ptr->action_flags |= TIPC_NOTIFY_LINK_DOWN;
-	n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;
+	n->working_links--;
+	n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
+	n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
 
-	if (!tipc_link_is_active(l_ptr)) {
+	if (!tipc_link_is_active(l)) {
 		pr_debug("Lost standby link <%s> on network plane %c\n",
-			 l_ptr->name, l_ptr->net_plane);
+			 l->name, l->net_plane);
 		return;
 	}
 	pr_debug("Lost link <%s> on network plane %c\n",
-		 l_ptr->name, l_ptr->net_plane);
+		 l->name, l->net_plane);
 
-	active = &n_ptr->active_links[0];
-	if (active[0] == l_ptr)
-		active[0] = active[1];
-	if (active[1] == l_ptr)
-		active[1] = active[0];
-	if (active[0] == l_ptr)
-		node_select_active_links(n_ptr);
-	if (tipc_node_is_up(n_ptr))
-		tipc_link_failover_send_queue(l_ptr);
+	/* Resdistribute active slots if applicable */
+	if (actv[0] == le)
+		actv[0] = actv[1];
+	if (actv[1] == le)
+		actv[1] = actv[0];
+
+	/* Last link of this priority? => select other ones if available */
+	if (actv[0] == le)
+		node_select_active_links(n);
+
+	if (tipc_node_is_up(n))
+		tipc_link_failover_send_queue(l);
 	else
-		node_lost_contact(n_ptr);
-
-	/* Leave room for changeover header when returning 'mtu' to users: */
-	if (active[0]) {
-		n_ptr->act_mtus[0] = active[0]->mtu - INT_H_SIZE;
-		n_ptr->act_mtus[1] = active[1]->mtu - INT_H_SIZE;
-		return;
-	}
-	/* Loopback link went down? No fragmentation needed from now on. */
-	if (n_ptr->addr == tn->own_addr) {
-		n_ptr->act_mtus[0] = MAX_MSG_SIZE;
-		n_ptr->act_mtus[1] = MAX_MSG_SIZE;
-	}
+		node_lost_contact(n);
 }
 
-int tipc_node_active_links(struct tipc_node *n_ptr)
+bool tipc_node_is_up(struct tipc_node *n)
 {
-	return n_ptr->active_links[0] != NULL;
-}
-
-int tipc_node_is_up(struct tipc_node *n_ptr)
-{
-	return tipc_node_active_links(n_ptr);
+	return n->active_links[0];
 }
 
 void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 {
-	n_ptr->links[l_ptr->bearer_id] = l_ptr;
+	n_ptr->links[l_ptr->bearer_id].link = l_ptr;
 	n_ptr->link_cnt++;
 }
 
@@ -352,9 +345,9 @@
 	int i;
 
 	for (i = 0; i < MAX_BEARERS; i++) {
-		if (l_ptr != n_ptr->links[i])
+		if (l_ptr != n_ptr->links[i].link)
 			continue;
-		n_ptr->links[i] = NULL;
+		n_ptr->links[i].link = NULL;
 		n_ptr->link_cnt--;
 	}
 }
@@ -396,7 +389,7 @@
 
 	/* Abort any ongoing link failover */
 	for (i = 0; i < MAX_BEARERS; i++) {
-		struct tipc_link *l_ptr = n_ptr->links[i];
+		struct tipc_link *l_ptr = n_ptr->links[i].link;
 		if (!l_ptr)
 			continue;
 		l_ptr->flags &= ~LINK_FAILINGOVER;
@@ -453,7 +446,7 @@
 		goto exit;
 
 	tipc_node_lock(node);
-	link = node->links[bearer_id];
+	link = node->links[bearer_id].link;
 	if (link) {
 		strncpy(linkname, link->name, len);
 		err = 0;