aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2006-06-26 02:52:50 -0400
committerDavid S. Miller <davem@davemloft.net>2006-06-26 02:52:50 -0400
commit5392d646886d8f1ae01be69c10600b8df5284c41 (patch)
tree38f6c38498dc7f1632cc04a50098b82037307e44
parenta10bd924a421e0e5d5bb9640735b9317b8e473b5 (diff)
[TIPC]: Fixed link switchover bugs
Incorporates several related fixes: - switchover now occurs when switching from an active link to a standby link - failure of a standby link no longer initiates switchover - links now display correct # of received packtes following reactivation Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Per Liden <per.liden@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/link.c30
-rw-r--r--net/tipc/node.c7
-rw-r--r--net/tipc/node.h2
3 files changed, 31 insertions, 8 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index d7668b8abb2d..d64658053746 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -690,6 +690,7 @@ void tipc_link_reset(struct link *l_ptr)
690 struct sk_buff *buf; 690 struct sk_buff *buf;
691 u32 prev_state = l_ptr->state; 691 u32 prev_state = l_ptr->state;
692 u32 checkpoint = l_ptr->next_in_no; 692 u32 checkpoint = l_ptr->next_in_no;
693 int was_active_link = tipc_link_is_active(l_ptr);
693 694
694 msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); 695 msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
695 696
@@ -711,7 +712,7 @@ void tipc_link_reset(struct link *l_ptr)
711 tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); 712 tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
712 dbg_link_dump(); 713 dbg_link_dump();
713#endif 714#endif
714 if (tipc_node_has_active_links(l_ptr->owner) && 715 if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&
715 l_ptr->owner->permit_changeover) { 716 l_ptr->owner->permit_changeover) {
716 l_ptr->reset_checkpoint = checkpoint; 717 l_ptr->reset_checkpoint = checkpoint;
717 l_ptr->exp_msg_count = START_CHANGEOVER; 718 l_ptr->exp_msg_count = START_CHANGEOVER;
@@ -754,7 +755,7 @@ void tipc_link_reset(struct link *l_ptr)
754 755
755static void link_activate(struct link *l_ptr) 756static void link_activate(struct link *l_ptr)
756{ 757{
757 l_ptr->next_in_no = 1; 758 l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
758 tipc_node_link_up(l_ptr->owner, l_ptr); 759 tipc_node_link_up(l_ptr->owner, l_ptr);
759 tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); 760 tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
760 link_send_event(tipc_cfg_link_event, l_ptr, 1); 761 link_send_event(tipc_cfg_link_event, l_ptr, 1);
@@ -2303,12 +2304,18 @@ void tipc_link_tunnel(struct link *l_ptr,
2303 u32 length = msg_size(msg); 2304 u32 length = msg_size(msg);
2304 2305
2305 tunnel = l_ptr->owner->active_links[selector & 1]; 2306 tunnel = l_ptr->owner->active_links[selector & 1];
2306 if (!tipc_link_is_up(tunnel)) 2307 if (!tipc_link_is_up(tunnel)) {
2308 warn("Link changeover error, "
2309 "tunnel link no longer available\n");
2307 return; 2310 return;
2311 }
2308 msg_set_size(tunnel_hdr, length + INT_H_SIZE); 2312 msg_set_size(tunnel_hdr, length + INT_H_SIZE);
2309 buf = buf_acquire(length + INT_H_SIZE); 2313 buf = buf_acquire(length + INT_H_SIZE);
2310 if (!buf) 2314 if (!buf) {
2315 warn("Link changeover error, "
2316 "unable to send tunnel msg\n");
2311 return; 2317 return;
2318 }
2312 memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); 2319 memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE);
2313 memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); 2320 memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length);
2314 dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); 2321 dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane);
@@ -2328,19 +2335,23 @@ void tipc_link_changeover(struct link *l_ptr)
2328 u32 msgcount = l_ptr->out_queue_size; 2335 u32 msgcount = l_ptr->out_queue_size;
2329 struct sk_buff *crs = l_ptr->first_out; 2336 struct sk_buff *crs = l_ptr->first_out;
2330 struct link *tunnel = l_ptr->owner->active_links[0]; 2337 struct link *tunnel = l_ptr->owner->active_links[0];
2331 int split_bundles = tipc_node_has_redundant_links(l_ptr->owner);
2332 struct tipc_msg tunnel_hdr; 2338 struct tipc_msg tunnel_hdr;
2339 int split_bundles;
2333 2340
2334 if (!tunnel) 2341 if (!tunnel)
2335 return; 2342 return;
2336 2343
2337 if (!l_ptr->owner->permit_changeover) 2344 if (!l_ptr->owner->permit_changeover) {
2345 warn("Link changeover error, "
2346 "peer did not permit changeover\n");
2338 return; 2347 return;
2348 }
2339 2349
2340 msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, 2350 msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
2341 ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); 2351 ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
2342 msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); 2352 msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
2343 msg_set_msgcnt(&tunnel_hdr, msgcount); 2353 msg_set_msgcnt(&tunnel_hdr, msgcount);
2354 dbg("Link changeover requires %u tunnel messages\n", msgcount);
2344 2355
2345 if (!l_ptr->first_out) { 2356 if (!l_ptr->first_out) {
2346 struct sk_buff *buf; 2357 struct sk_buff *buf;
@@ -2360,6 +2371,9 @@ void tipc_link_changeover(struct link *l_ptr)
2360 return; 2371 return;
2361 } 2372 }
2362 2373
2374 split_bundles = (l_ptr->owner->active_links[0] !=
2375 l_ptr->owner->active_links[1]);
2376
2363 while (crs) { 2377 while (crs) {
2364 struct tipc_msg *msg = buf_msg(crs); 2378 struct tipc_msg *msg = buf_msg(crs);
2365 2379
@@ -2497,11 +2511,13 @@ static int link_recv_changeover_msg(struct link **l_ptr,
2497 dest_link->name); 2511 dest_link->name);
2498 tipc_link_reset(dest_link); 2512 tipc_link_reset(dest_link);
2499 dest_link->exp_msg_count = msg_count; 2513 dest_link->exp_msg_count = msg_count;
2514 dbg("Expecting %u tunnelled messages\n", msg_count);
2500 if (!msg_count) 2515 if (!msg_count)
2501 goto exit; 2516 goto exit;
2502 } else if (dest_link->exp_msg_count == START_CHANGEOVER) { 2517 } else if (dest_link->exp_msg_count == START_CHANGEOVER) {
2503 msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); 2518 msg_dbg(tunnel_msg, "BLK/FIRST/<REC<");
2504 dest_link->exp_msg_count = msg_count; 2519 dest_link->exp_msg_count = msg_count;
2520 dbg("Expecting %u tunnelled messages\n", msg_count);
2505 if (!msg_count) 2521 if (!msg_count)
2506 goto exit; 2522 goto exit;
2507 } 2523 }
@@ -2509,6 +2525,8 @@ static int link_recv_changeover_msg(struct link **l_ptr,
2509 /* Receive original message */ 2525 /* Receive original message */
2510 2526
2511 if (dest_link->exp_msg_count == 0) { 2527 if (dest_link->exp_msg_count == 0) {
2528 warn("Link switchover error, "
2529 "got too many tunnelled messages\n");
2512 msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); 2530 msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<");
2513 dbg_print_link(dest_link, "LINK:"); 2531 dbg_print_link(dest_link, "LINK:");
2514 goto exit; 2532 goto exit;
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 5f097547d3e3..ce9678efa98a 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -125,6 +125,8 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
125{ 125{
126 struct link **active = &n_ptr->active_links[0]; 126 struct link **active = &n_ptr->active_links[0];
127 127
128 n_ptr->working_links++;
129
128 info("Established link <%s> on network plane %c\n", 130 info("Established link <%s> on network plane %c\n",
129 l_ptr->name, l_ptr->b_ptr->net_plane); 131 l_ptr->name, l_ptr->b_ptr->net_plane);
130 132
@@ -185,6 +187,8 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
185{ 187{
186 struct link **active; 188 struct link **active;
187 189
190 n_ptr->working_links--;
191
188 if (!tipc_link_is_active(l_ptr)) { 192 if (!tipc_link_is_active(l_ptr)) {
189 info("Lost standby link <%s> on network plane %c\n", 193 info("Lost standby link <%s> on network plane %c\n",
190 l_ptr->name, l_ptr->b_ptr->net_plane); 194 l_ptr->name, l_ptr->b_ptr->net_plane);
@@ -214,8 +218,7 @@ int tipc_node_has_active_links(struct node *n_ptr)
214 218
215int tipc_node_has_redundant_links(struct node *n_ptr) 219int tipc_node_has_redundant_links(struct node *n_ptr)
216{ 220{
217 return (tipc_node_has_active_links(n_ptr) && 221 return (n_ptr->working_links > 1);
218 (n_ptr->active_links[0] != n_ptr->active_links[1]));
219} 222}
220 223
221static int tipc_node_has_active_routes(struct node *n_ptr) 224static int tipc_node_has_active_routes(struct node *n_ptr)
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 781126e084ae..a07cc79ea637 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -51,6 +51,7 @@
51 * @nsub: list of "node down" subscriptions monitoring node 51 * @nsub: list of "node down" subscriptions monitoring node
52 * @active_links: pointers to active links to node 52 * @active_links: pointers to active links to node
53 * @links: pointers to all links to node 53 * @links: pointers to all links to node
54 * @working_links: number of working links to node (both active and standby)
54 * @link_cnt: number of links to node 55 * @link_cnt: number of links to node
55 * @permit_changeover: non-zero if node has redundant links to this system 56 * @permit_changeover: non-zero if node has redundant links to this system
56 * @routers: bitmap (used for multicluster communication) 57 * @routers: bitmap (used for multicluster communication)
@@ -76,6 +77,7 @@ struct node {
76 struct link *active_links[2]; 77 struct link *active_links[2];
77 struct link *links[MAX_BEARERS]; 78 struct link *links[MAX_BEARERS];
78 int link_cnt; 79 int link_cnt;
80 int working_links;
79 int permit_changeover; 81 int permit_changeover;
80 u32 routers[512/32]; 82 u32 routers[512/32];
81 int last_router; 83 int last_router;