summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-07-16 16:54:19 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-20 23:41:14 -0400
commit9d13ec65ede775f896c3da1cfa35283afe2f796c (patch)
tree34ac0c21607481a2377b3201c3fe58c3f6ac7947 /net
parent6acc23266054a9969737b435fa012f87465dbc50 (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/tipc/bcast.c2
-rw-r--r--net/tipc/discover.c2
-rw-r--r--net/tipc/link.c60
-rw-r--r--net/tipc/name_distr.c2
-rw-r--r--net/tipc/node.c163
-rw-r--r--net/tipc/node.h50
6 files changed, 143 insertions, 136 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index a816382fc8af..59b2f2a538e1 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -413,7 +413,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno)
413 * all nodes in the cluster don't ACK at the same time 413 * all nodes in the cluster don't ACK at the same time
414 */ 414 */
415 if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) { 415 if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) {
416 tipc_link_proto_xmit(node->active_links[node->addr & 1], 416 tipc_link_proto_xmit(node_active_link(node, node->addr),
417 STATE_MSG, 0, 0, 0, 0); 417 STATE_MSG, 0, 0, 0, 0);
418 tn->bcl->stats.sent_acks++; 418 tn->bcl->stats.sent_acks++;
419 } 419 }
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 967e292f53c8..933445337fb4 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -170,7 +170,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
170 return; 170 return;
171 tipc_node_lock(node); 171 tipc_node_lock(node);
172 node->capabilities = caps; 172 node->capabilities = caps;
173 link = node->links[bearer->identity]; 173 link = node->links[bearer->identity].link;
174 174
175 /* Prepare to validate requesting node's signature and media address */ 175 /* Prepare to validate requesting node's signature and media address */
176 sign_match = (signature == node->signature); 176 sign_match = (signature == node->signature);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index eaa9fe54b4ae..03372a7e98df 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -132,9 +132,11 @@ static void tipc_link_put(struct tipc_link *l_ptr)
132 132
133static struct tipc_link *tipc_parallel_link(struct tipc_link *l) 133static struct tipc_link *tipc_parallel_link(struct tipc_link *l)
134{ 134{
135 if (l->owner->active_links[0] != l) 135 struct tipc_node *n = l->owner;
136 return l->owner->active_links[0]; 136
137 return l->owner->active_links[1]; 137 if (node_active_link(n, 0) != l)
138 return node_active_link(n, 0);
139 return node_active_link(n, 1);
138} 140}
139 141
140/* 142/*
@@ -147,10 +149,11 @@ int tipc_link_is_up(struct tipc_link *l_ptr)
147 return link_working_working(l_ptr) || link_working_unknown(l_ptr); 149 return link_working_working(l_ptr) || link_working_unknown(l_ptr);
148} 150}
149 151
150int tipc_link_is_active(struct tipc_link *l_ptr) 152int tipc_link_is_active(struct tipc_link *l)
151{ 153{
152 return (l_ptr->owner->active_links[0] == l_ptr) || 154 struct tipc_node *n = l->owner;
153 (l_ptr->owner->active_links[1] == l_ptr); 155
156 return (node_active_link(n, 0) == l) || (node_active_link(n, 1) == l);
154} 157}
155 158
156/** 159/**
@@ -240,7 +243,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
240 return NULL; 243 return NULL;
241 } 244 }
242 245
243 if (n_ptr->links[b_ptr->identity]) { 246 if (n_ptr->links[b_ptr->identity].link) {
244 tipc_addr_string_fill(addr_string, n_ptr->addr); 247 tipc_addr_string_fill(addr_string, n_ptr->addr);
245 pr_err("Attempt to establish second link on <%s> to %s\n", 248 pr_err("Attempt to establish second link on <%s> to %s\n",
246 b_ptr->name, addr_string); 249 b_ptr->name, addr_string);
@@ -321,7 +324,7 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
321 rcu_read_lock(); 324 rcu_read_lock();
322 list_for_each_entry_rcu(node, &tn->node_list, list) { 325 list_for_each_entry_rcu(node, &tn->node_list, list) {
323 tipc_node_lock(node); 326 tipc_node_lock(node);
324 link = node->links[bearer_id]; 327 link = node->links[bearer_id].link;
325 if (link) 328 if (link)
326 tipc_link_delete(link); 329 tipc_link_delete(link);
327 tipc_node_unlock(node); 330 tipc_node_unlock(node);
@@ -446,7 +449,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
446 if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) 449 if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))
447 return; 450 return;
448 451
449 tipc_node_link_down(l_ptr->owner, l_ptr); 452 tipc_node_link_down(l_ptr->owner, l_ptr->bearer_id);
450 tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr); 453 tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr);
451 454
452 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) { 455 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
@@ -482,7 +485,7 @@ static void link_activate(struct tipc_link *link)
482 link->rcv_nxt = 1; 485 link->rcv_nxt = 1;
483 link->stats.recv_info = 1; 486 link->stats.recv_info = 1;
484 link->silent_intv_cnt = 0; 487 link->silent_intv_cnt = 0;
485 tipc_node_link_up(node, link); 488 tipc_node_link_up(node, link->bearer_id);
486 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); 489 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr);
487} 490}
488 491
@@ -577,7 +580,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
577 case TRAFFIC_MSG_EVT: 580 case TRAFFIC_MSG_EVT:
578 break; 581 break;
579 case ACTIVATE_MSG: 582 case ACTIVATE_MSG:
580 other = l_ptr->owner->active_links[0]; 583 other = node_active_link(l_ptr->owner, 0);
581 if (other && link_working_unknown(other)) 584 if (other && link_working_unknown(other))
582 break; 585 break;
583 l_ptr->state = WORKING_WORKING; 586 l_ptr->state = WORKING_WORKING;
@@ -606,7 +609,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
606 switch (event) { 609 switch (event) {
607 case TRAFFIC_MSG_EVT: 610 case TRAFFIC_MSG_EVT:
608 case ACTIVATE_MSG: 611 case ACTIVATE_MSG:
609 other = l_ptr->owner->active_links[0]; 612 other = node_active_link(l_ptr->owner, 0);
610 if (other && link_working_unknown(other)) 613 if (other && link_working_unknown(other))
611 break; 614 break;
612 l_ptr->state = WORKING_WORKING; 615 l_ptr->state = WORKING_WORKING;
@@ -755,7 +758,7 @@ int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode,
755 node = tipc_node_find(net, dnode); 758 node = tipc_node_find(net, dnode);
756 if (node) { 759 if (node) {
757 tipc_node_lock(node); 760 tipc_node_lock(node);
758 link = node->active_links[selector & 1]; 761 link = node_active_link(node, selector & 1);
759 if (link) 762 if (link)
760 rc = __tipc_link_xmit(net, link, list); 763 rc = __tipc_link_xmit(net, link, list);
761 tipc_node_unlock(node); 764 tipc_node_unlock(node);
@@ -858,9 +861,9 @@ void tipc_link_reset_all(struct tipc_node *node)
858 tipc_addr_string_fill(addr_string, node->addr)); 861 tipc_addr_string_fill(addr_string, node->addr));
859 862
860 for (i = 0; i < MAX_BEARERS; i++) { 863 for (i = 0; i < MAX_BEARERS; i++) {
861 if (node->links[i]) { 864 if (node->links[i].link) {
862 link_print(node->links[i], "Resetting link\n"); 865 link_print(node->links[i].link, "Resetting link\n");
863 tipc_link_reset(node->links[i]); 866 tipc_link_reset(node->links[i].link);
864 } 867 }
865 } 868 }
866 869
@@ -1029,7 +1032,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1029 1032
1030 tipc_node_lock(n_ptr); 1033 tipc_node_lock(n_ptr);
1031 /* Locate unicast link endpoint that should handle message */ 1034 /* Locate unicast link endpoint that should handle message */
1032 l_ptr = n_ptr->links[b_ptr->identity]; 1035 l_ptr = n_ptr->links[b_ptr->identity].link;
1033 if (unlikely(!l_ptr)) 1036 if (unlikely(!l_ptr))
1034 goto unlock; 1037 goto unlock;
1035 1038
@@ -1496,7 +1499,7 @@ static void tipc_link_tunnel_xmit(struct tipc_link *l_ptr,
1496 struct sk_buff *skb; 1499 struct sk_buff *skb;
1497 u32 length = msg_size(msg); 1500 u32 length = msg_size(msg);
1498 1501
1499 tunnel = l_ptr->owner->active_links[selector & 1]; 1502 tunnel = node_active_link(l_ptr->owner, selector & 1);
1500 if (!tipc_link_is_up(tunnel)) { 1503 if (!tipc_link_is_up(tunnel)) {
1501 pr_warn("%stunnel link no longer available\n", link_co_err); 1504 pr_warn("%stunnel link no longer available\n", link_co_err);
1502 return; 1505 return;
@@ -1522,7 +1525,7 @@ static void tipc_link_tunnel_xmit(struct tipc_link *l_ptr,
1522void tipc_link_failover_send_queue(struct tipc_link *l_ptr) 1525void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
1523{ 1526{
1524 int msgcount; 1527 int msgcount;
1525 struct tipc_link *tunnel = l_ptr->owner->active_links[0]; 1528 struct tipc_link *tunnel = node_active_link(l_ptr->owner, 0);
1526 struct tipc_msg tunnel_hdr; 1529 struct tipc_msg tunnel_hdr;
1527 struct sk_buff *skb; 1530 struct sk_buff *skb;
1528 int split_bundles; 1531 int split_bundles;
@@ -1556,8 +1559,8 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr)
1556 return; 1559 return;
1557 } 1560 }
1558 1561
1559 split_bundles = (l_ptr->owner->active_links[0] != 1562 split_bundles = (node_active_link(l_ptr->owner, 0) !=
1560 l_ptr->owner->active_links[1]); 1563 node_active_link(l_ptr->owner, 0));
1561 1564
1562 skb_queue_walk(&l_ptr->transmq, skb) { 1565 skb_queue_walk(&l_ptr->transmq, skb) {
1563 struct tipc_msg *msg = buf_msg(skb); 1566 struct tipc_msg *msg = buf_msg(skb);
@@ -1660,7 +1663,7 @@ static bool tipc_link_failover_rcv(struct tipc_link *link,
1660 if (bearer_id == link->bearer_id) 1663 if (bearer_id == link->bearer_id)
1661 goto exit; 1664 goto exit;
1662 1665
1663 pl = link->owner->links[bearer_id]; 1666 pl = link->owner->links[bearer_id].link;
1664 if (pl && tipc_link_is_up(pl)) 1667 if (pl && tipc_link_is_up(pl))
1665 tipc_link_reset(pl); 1668 tipc_link_reset(pl);
1666 1669
@@ -1743,7 +1746,7 @@ static struct tipc_node *tipc_link_find_owner(struct net *net,
1743 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { 1746 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) {
1744 tipc_node_lock(n_ptr); 1747 tipc_node_lock(n_ptr);
1745 for (i = 0; i < MAX_BEARERS; i++) { 1748 for (i = 0; i < MAX_BEARERS; i++) {
1746 l_ptr = n_ptr->links[i]; 1749 l_ptr = n_ptr->links[i].link;
1747 if (l_ptr && !strcmp(l_ptr->name, link_name)) { 1750 if (l_ptr && !strcmp(l_ptr->name, link_name)) {
1748 *bearer_id = i; 1751 *bearer_id = i;
1749 found_node = n_ptr; 1752 found_node = n_ptr;
@@ -1865,7 +1868,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
1865 1868
1866 tipc_node_lock(node); 1869 tipc_node_lock(node);
1867 1870
1868 link = node->links[bearer_id]; 1871 link = node->links[bearer_id].link;
1869 if (!link) { 1872 if (!link) {
1870 res = -EINVAL; 1873 res = -EINVAL;
1871 goto out; 1874 goto out;
@@ -2055,10 +2058,11 @@ static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
2055 for (i = *prev_link; i < MAX_BEARERS; i++) { 2058 for (i = *prev_link; i < MAX_BEARERS; i++) {
2056 *prev_link = i; 2059 *prev_link = i;
2057 2060
2058 if (!node->links[i]) 2061 if (!node->links[i].link)
2059 continue; 2062 continue;
2060 2063
2061 err = __tipc_nl_add_link(net, msg, node->links[i], NLM_F_MULTI); 2064 err = __tipc_nl_add_link(net, msg,
2065 node->links[i].link, NLM_F_MULTI);
2062 if (err) 2066 if (err)
2063 return err; 2067 return err;
2064 } 2068 }
@@ -2172,7 +2176,7 @@ int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info)
2172 return -EINVAL; 2176 return -EINVAL;
2173 2177
2174 tipc_node_lock(node); 2178 tipc_node_lock(node);
2175 link = node->links[bearer_id]; 2179 link = node->links[bearer_id].link;
2176 if (!link) { 2180 if (!link) {
2177 tipc_node_unlock(node); 2181 tipc_node_unlock(node);
2178 nlmsg_free(msg.skb); 2182 nlmsg_free(msg.skb);
@@ -2227,7 +2231,7 @@ int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info)
2227 2231
2228 tipc_node_lock(node); 2232 tipc_node_lock(node);
2229 2233
2230 link = node->links[bearer_id]; 2234 link = node->links[bearer_id].link;
2231 if (!link) { 2235 if (!link) {
2232 tipc_node_unlock(node); 2236 tipc_node_unlock(node);
2233 return -EINVAL; 2237 return -EINVAL;
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 41e7b7e4dda0..3a1539e96294 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -96,7 +96,7 @@ void named_cluster_distribute(struct net *net, struct sk_buff *skb)
96 dnode = node->addr; 96 dnode = node->addr;
97 if (in_own_node(net, dnode)) 97 if (in_own_node(net, dnode))
98 continue; 98 continue;
99 if (!tipc_node_active_links(node)) 99 if (!tipc_node_is_up(node))
100 continue; 100 continue;
101 oskb = pskb_copy(skb, GFP_ATOMIC); 101 oskb = pskb_copy(skb, GFP_ATOMIC);
102 if (!oskb) 102 if (!oskb)
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 0b1d61a5f853..db46e5d1d156 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -224,126 +224,119 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
224 * 224 *
225 * Link becomes active (alone or shared) or standby, depending on its priority. 225 * Link becomes active (alone or shared) or standby, depending on its priority.
226 */ 226 */
227void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 227void tipc_node_link_up(struct tipc_node *n, int bearer_id)
228{ 228{
229 struct tipc_link **active = &n_ptr->active_links[0]; 229 struct tipc_link_entry **actv = &n->active_links[0];
230 struct tipc_link_entry *le = &n->links[bearer_id];
231 struct tipc_link *l = le->link;
230 232
231 n_ptr->working_links++; 233 /* Leave room for tunnel header when returning 'mtu' to users: */
232 n_ptr->action_flags |= TIPC_NOTIFY_LINK_UP; 234 n->links[bearer_id].mtu = l->mtu - INT_H_SIZE;
233 n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id; 235
236 n->working_links++;
237 n->action_flags |= TIPC_NOTIFY_LINK_UP;
238 n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
234 239
235 pr_debug("Established link <%s> on network plane %c\n", 240 pr_debug("Established link <%s> on network plane %c\n",
236 l_ptr->name, l_ptr->net_plane); 241 l->name, l->net_plane);
237 242
238 if (!active[0]) { 243 /* No active links ? => take both active slots */
239 active[0] = active[1] = l_ptr; 244 if (!actv[0]) {
240 node_established_contact(n_ptr); 245 actv[0] = le;
241 goto exit; 246 actv[1] = le;
247 node_established_contact(n);
248 return;
242 } 249 }
243 if (l_ptr->priority < active[0]->priority) { 250 if (l->priority < actv[0]->link->priority) {
244 pr_debug("New link <%s> becomes standby\n", l_ptr->name); 251 pr_debug("New link <%s> becomes standby\n", l->name);
245 goto exit; 252 return;
246 } 253 }
247 tipc_link_dup_queue_xmit(active[0], l_ptr); 254 tipc_link_dup_queue_xmit(actv[0]->link, l);
248 if (l_ptr->priority == active[0]->priority) { 255
249 active[0] = l_ptr; 256 /* Take one active slot if applicable */
250 goto exit; 257 if (l->priority == actv[0]->link->priority) {
258 actv[0] = le;
259 return;
251 } 260 }
252 pr_debug("Old link <%s> becomes standby\n", active[0]->name); 261 /* Higher prio than current active? => take both active slots */
253 if (active[1] != active[0]) 262 pr_debug("Old l <%s> becomes standby\n", actv[0]->link->name);
254 pr_debug("Old link <%s> becomes standby\n", active[1]->name); 263 if (actv[1] != actv[0])
255 active[0] = active[1] = l_ptr; 264 pr_debug("Old link <%s> now standby\n", actv[1]->link->name);
256exit: 265 actv[0] = le;
257 /* Leave room for changeover header when returning 'mtu' to users: */ 266 actv[1] = le;
258 n_ptr->act_mtus[0] = active[0]->mtu - INT_H_SIZE;
259 n_ptr->act_mtus[1] = active[1]->mtu - INT_H_SIZE;
260} 267}
261 268
262/** 269/**
263 * node_select_active_links - select active link 270 * node_select_active_links - select which working links should be active
264 */ 271 */
265static void node_select_active_links(struct tipc_node *n_ptr) 272static void node_select_active_links(struct tipc_node *n)
266{ 273{
267 struct tipc_link **active = &n_ptr->active_links[0]; 274 struct tipc_link_entry **actv = &n->active_links[0];
268 u32 i; 275 struct tipc_link *l;
269 u32 highest_prio = 0; 276 u32 b, highest = 0;
270 277
271 active[0] = active[1] = NULL; 278 actv[0] = NULL;
272 279 actv[1] = NULL;
273 for (i = 0; i < MAX_BEARERS; i++) {
274 struct tipc_link *l_ptr = n_ptr->links[i];
275 280
276 if (!l_ptr || !tipc_link_is_up(l_ptr) || 281 for (b = 0; b < MAX_BEARERS; b++) {
277 (l_ptr->priority < highest_prio)) 282 l = n->links[b].link;
283 if (!l || !tipc_link_is_up(l) || (l->priority < highest))
284 continue;
285 if (l->priority > highest) {
286 highest = l->priority;
287 actv[0] = &n->links[b];
288 actv[1] = &n->links[b];
278 continue; 289 continue;
279
280 if (l_ptr->priority > highest_prio) {
281 highest_prio = l_ptr->priority;
282 active[0] = active[1] = l_ptr;
283 } else {
284 active[1] = l_ptr;
285 } 290 }
291 actv[1] = &n->links[b];
286 } 292 }
287} 293}
288 294
289/** 295/**
290 * tipc_node_link_down - handle loss of link 296 * tipc_node_link_down - handle loss of link
291 */ 297 */
292void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 298void tipc_node_link_down(struct tipc_node *n, int bearer_id)
293{ 299{
294 struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); 300 struct tipc_link_entry **actv = &n->active_links[0];
295 struct tipc_link **active; 301 struct tipc_link_entry *le = &n->links[bearer_id];
302 struct tipc_link *l = le->link;
296 303
297 n_ptr->working_links--; 304 n->working_links--;
298 n_ptr->action_flags |= TIPC_NOTIFY_LINK_DOWN; 305 n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
299 n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id; 306 n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
300 307
301 if (!tipc_link_is_active(l_ptr)) { 308 if (!tipc_link_is_active(l)) {
302 pr_debug("Lost standby link <%s> on network plane %c\n", 309 pr_debug("Lost standby link <%s> on network plane %c\n",
303 l_ptr->name, l_ptr->net_plane); 310 l->name, l->net_plane);
304 return; 311 return;
305 } 312 }
306 pr_debug("Lost link <%s> on network plane %c\n", 313 pr_debug("Lost link <%s> on network plane %c\n",
307 l_ptr->name, l_ptr->net_plane); 314 l->name, l->net_plane);
308
309 active = &n_ptr->active_links[0];
310 if (active[0] == l_ptr)
311 active[0] = active[1];
312 if (active[1] == l_ptr)
313 active[1] = active[0];
314 if (active[0] == l_ptr)
315 node_select_active_links(n_ptr);
316 if (tipc_node_is_up(n_ptr))
317 tipc_link_failover_send_queue(l_ptr);
318 else
319 node_lost_contact(n_ptr);
320 315
321 /* Leave room for changeover header when returning 'mtu' to users: */ 316 /* Resdistribute active slots if applicable */
322 if (active[0]) { 317 if (actv[0] == le)
323 n_ptr->act_mtus[0] = active[0]->mtu - INT_H_SIZE; 318 actv[0] = actv[1];
324 n_ptr->act_mtus[1] = active[1]->mtu - INT_H_SIZE; 319 if (actv[1] == le)
325 return; 320 actv[1] = actv[0];
326 }
327 /* Loopback link went down? No fragmentation needed from now on. */
328 if (n_ptr->addr == tn->own_addr) {
329 n_ptr->act_mtus[0] = MAX_MSG_SIZE;
330 n_ptr->act_mtus[1] = MAX_MSG_SIZE;
331 }
332}
333 321
334int tipc_node_active_links(struct tipc_node *n_ptr) 322 /* Last link of this priority? => select other ones if available */
335{ 323 if (actv[0] == le)
336 return n_ptr->active_links[0] != NULL; 324 node_select_active_links(n);
325
326 if (tipc_node_is_up(n))
327 tipc_link_failover_send_queue(l);
328 else
329 node_lost_contact(n);
337} 330}
338 331
339int tipc_node_is_up(struct tipc_node *n_ptr) 332bool tipc_node_is_up(struct tipc_node *n)
340{ 333{
341 return tipc_node_active_links(n_ptr); 334 return n->active_links[0];
342} 335}
343 336
344void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 337void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
345{ 338{
346 n_ptr->links[l_ptr->bearer_id] = l_ptr; 339 n_ptr->links[l_ptr->bearer_id].link = l_ptr;
347 n_ptr->link_cnt++; 340 n_ptr->link_cnt++;
348} 341}
349 342
@@ -352,9 +345,9 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
352 int i; 345 int i;
353 346
354 for (i = 0; i < MAX_BEARERS; i++) { 347 for (i = 0; i < MAX_BEARERS; i++) {
355 if (l_ptr != n_ptr->links[i]) 348 if (l_ptr != n_ptr->links[i].link)
356 continue; 349 continue;
357 n_ptr->links[i] = NULL; 350 n_ptr->links[i].link = NULL;
358 n_ptr->link_cnt--; 351 n_ptr->link_cnt--;
359 } 352 }
360} 353}
@@ -396,7 +389,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
396 389
397 /* Abort any ongoing link failover */ 390 /* Abort any ongoing link failover */
398 for (i = 0; i < MAX_BEARERS; i++) { 391 for (i = 0; i < MAX_BEARERS; i++) {
399 struct tipc_link *l_ptr = n_ptr->links[i]; 392 struct tipc_link *l_ptr = n_ptr->links[i].link;
400 if (!l_ptr) 393 if (!l_ptr)
401 continue; 394 continue;
402 l_ptr->flags &= ~LINK_FAILINGOVER; 395 l_ptr->flags &= ~LINK_FAILINGOVER;
@@ -453,7 +446,7 @@ int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr,
453 goto exit; 446 goto exit;
454 447
455 tipc_node_lock(node); 448 tipc_node_lock(node);
456 link = node->links[bearer_id]; 449 link = node->links[bearer_id].link;
457 if (link) { 450 if (link) {
458 strncpy(linkname, link->name, len); 451 strncpy(linkname, link->name, len);
459 err = 0; 452 err = 0;
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 5a834cf142c8..320cea313bdc 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -89,6 +89,11 @@ struct tipc_node_bclink {
89 bool recv_permitted; 89 bool recv_permitted;
90}; 90};
91 91
92struct tipc_link_entry {
93 struct tipc_link *link;
94 u32 mtu;
95};
96
92/** 97/**
93 * struct tipc_node - TIPC node structure 98 * struct tipc_node - TIPC node structure
94 * @addr: network address of node 99 * @addr: network address of node
@@ -98,9 +103,8 @@ struct tipc_node_bclink {
98 * @hash: links to adjacent nodes in unsorted hash chain 103 * @hash: links to adjacent nodes in unsorted hash chain
99 * @inputq: pointer to input queue containing messages for msg event 104 * @inputq: pointer to input queue containing messages for msg event
100 * @namedq: pointer to name table input queue with name table messages 105 * @namedq: pointer to name table input queue with name table messages
101 * @curr_link: the link holding the node lock, if any 106 * @active_links: pointer into links[] array, identifying which links are active
102 * @active_links: pointers to active links to node 107 * @links: array containing references to all links to node
103 * @links: pointers to all links to node
104 * @action_flags: bit mask of different types of node actions 108 * @action_flags: bit mask of different types of node actions
105 * @bclink: broadcast-related info 109 * @bclink: broadcast-related info
106 * @list: links to adjacent nodes in sorted list of cluster's nodes 110 * @list: links to adjacent nodes in sorted list of cluster's nodes
@@ -120,9 +124,8 @@ struct tipc_node {
120 struct hlist_node hash; 124 struct hlist_node hash;
121 struct sk_buff_head *inputq; 125 struct sk_buff_head *inputq;
122 struct sk_buff_head *namedq; 126 struct sk_buff_head *namedq;
123 struct tipc_link *active_links[2]; 127 struct tipc_link_entry *active_links[2];
124 u32 act_mtus[2]; 128 struct tipc_link_entry links[MAX_BEARERS];
125 struct tipc_link *links[MAX_BEARERS];
126 int action_flags; 129 int action_flags;
127 struct tipc_node_bclink bclink; 130 struct tipc_node_bclink bclink;
128 struct list_head list; 131 struct list_head list;
@@ -142,10 +145,9 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr);
142void tipc_node_stop(struct net *net); 145void tipc_node_stop(struct net *net);
143void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); 146void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
144void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); 147void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
145void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); 148void tipc_node_link_down(struct tipc_node *n_ptr, int bearer_id);
146void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); 149void tipc_node_link_up(struct tipc_node *n_ptr, int bearer_id);
147int tipc_node_active_links(struct tipc_node *n_ptr); 150bool tipc_node_is_up(struct tipc_node *n);
148int tipc_node_is_up(struct tipc_node *n_ptr);
149int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, 151int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node,
150 char *linkname, size_t len); 152 char *linkname, size_t len);
151void tipc_node_unlock(struct tipc_node *node); 153void tipc_node_unlock(struct tipc_node *node);
@@ -165,20 +167,28 @@ static inline bool tipc_node_blocked(struct tipc_node *node)
165 TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN)); 167 TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN));
166} 168}
167 169
168static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) 170static inline struct tipc_link *node_active_link(struct tipc_node *n, int sel)
169{ 171{
170 struct tipc_node *node; 172 struct tipc_link_entry *le = n->active_links[sel & 1];
171 u32 mtu;
172 173
173 node = tipc_node_find(net, addr); 174 if (likely(le))
175 return le->link;
176 return NULL;
177}
174 178
175 if (likely(node)) { 179static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector)
176 mtu = node->act_mtus[selector & 1]; 180{
177 tipc_node_put(node); 181 struct tipc_node *n;
178 } else { 182 struct tipc_link_entry *le;
179 mtu = MAX_MSG_SIZE; 183 unsigned int mtu = MAX_MSG_SIZE;
180 }
181 184
185 n = tipc_node_find(net, addr);
186 if (unlikely(!n))
187 return mtu;
188 le = n->active_links[selector & 1];
189 if (likely(le))
190 mtu = le->mtu;
191 tipc_node_put(n);
182 return mtu; 192 return mtu;
183} 193}
184 194