diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-07-16 16:54:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-20 23:41:14 -0400 |
commit | 9d13ec65ede775f896c3da1cfa35283afe2f796c (patch) | |
tree | 34ac0c21607481a2377b3201c3fe58c3f6ac7947 /net | |
parent | 6acc23266054a9969737b435fa012f87465dbc50 (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.c | 2 | ||||
-rw-r--r-- | net/tipc/discover.c | 2 | ||||
-rw-r--r-- | net/tipc/link.c | 60 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 2 | ||||
-rw-r--r-- | net/tipc/node.c | 163 | ||||
-rw-r--r-- | net/tipc/node.h | 50 |
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 | ||
133 | static struct tipc_link *tipc_parallel_link(struct tipc_link *l) | 133 | static 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 | ||
150 | int tipc_link_is_active(struct tipc_link *l_ptr) | 152 | int 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, | |||
1522 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr) | 1525 | void 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 | */ |
227 | void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 227 | void 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); |
256 | exit: | 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 | */ |
265 | static void node_select_active_links(struct tipc_node *n_ptr) | 272 | static 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 | */ |
292 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 298 | void 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 | ||
334 | int 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 | ||
339 | int tipc_node_is_up(struct tipc_node *n_ptr) | 332 | bool 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 | ||
344 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 337 | void 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 | ||
92 | struct 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); | |||
142 | void tipc_node_stop(struct net *net); | 145 | void tipc_node_stop(struct net *net); |
143 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 146 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
144 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 147 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
145 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 148 | void tipc_node_link_down(struct tipc_node *n_ptr, int bearer_id); |
146 | void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 149 | void tipc_node_link_up(struct tipc_node *n_ptr, int bearer_id); |
147 | int tipc_node_active_links(struct tipc_node *n_ptr); | 150 | bool tipc_node_is_up(struct tipc_node *n); |
148 | int tipc_node_is_up(struct tipc_node *n_ptr); | ||
149 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, | 151 | int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 node, |
150 | char *linkname, size_t len); | 152 | char *linkname, size_t len); |
151 | void tipc_node_unlock(struct tipc_node *node); | 153 | void 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 | ||
168 | static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) | 170 | static 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)) { | 179 | static 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 | ||