diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2006-06-26 02:52:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-06-26 02:52:50 -0400 |
commit | 5392d646886d8f1ae01be69c10600b8df5284c41 (patch) | |
tree | 38f6c38498dc7f1632cc04a50098b82037307e44 /net | |
parent | a10bd924a421e0e5d5bb9640735b9317b8e473b5 (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/tipc/link.c | 30 | ||||
-rw-r--r-- | net/tipc/node.c | 7 | ||||
-rw-r--r-- | net/tipc/node.h | 2 |
3 files changed, 31 insertions, 8 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index d7668b8abb2..d6465805374 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 | ||
755 | static void link_activate(struct link *l_ptr) | 756 | static 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 5f097547d3e..ce9678efa98 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 | ||
215 | int tipc_node_has_redundant_links(struct node *n_ptr) | 219 | int 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 | ||
221 | static int tipc_node_has_active_routes(struct node *n_ptr) | 224 | static int tipc_node_has_active_routes(struct node *n_ptr) |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 781126e084a..a07cc79ea63 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; |