Commit 5392d646886d8f1ae01be69c10600b8df5284c41
Committed by
David S. Miller
1 parent
a10bd924a4
Exists in
master
and in
39 other branches
[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>
Showing 3 changed files with 31 additions and 8 deletions Side-by-side Diff
net/tipc/link.c
... | ... | @@ -690,6 +690,7 @@ |
690 | 690 | struct sk_buff *buf; |
691 | 691 | u32 prev_state = l_ptr->state; |
692 | 692 | u32 checkpoint = l_ptr->next_in_no; |
693 | + int was_active_link = tipc_link_is_active(l_ptr); | |
693 | 694 | |
694 | 695 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); |
695 | 696 | |
... | ... | @@ -711,7 +712,7 @@ |
711 | 712 | tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); |
712 | 713 | dbg_link_dump(); |
713 | 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 | 716 | l_ptr->owner->permit_changeover) { |
716 | 717 | l_ptr->reset_checkpoint = checkpoint; |
717 | 718 | l_ptr->exp_msg_count = START_CHANGEOVER; |
... | ... | @@ -754,7 +755,7 @@ |
754 | 755 | |
755 | 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 | 759 | tipc_node_link_up(l_ptr->owner, l_ptr); |
759 | 760 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); |
760 | 761 | link_send_event(tipc_cfg_link_event, l_ptr, 1); |
761 | 762 | |
762 | 763 | |
763 | 764 | |
... | ... | @@ -2303,12 +2304,18 @@ |
2303 | 2304 | u32 length = msg_size(msg); |
2304 | 2305 | |
2305 | 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 | 2310 | return; |
2311 | + } | |
2308 | 2312 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); |
2309 | 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 | 2317 | return; |
2318 | + } | |
2312 | 2319 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); |
2313 | 2320 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); |
2314 | 2321 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); |
2315 | 2322 | |
2316 | 2323 | |
2317 | 2324 | |
2318 | 2325 | |
... | ... | @@ -2328,19 +2335,23 @@ |
2328 | 2335 | u32 msgcount = l_ptr->out_queue_size; |
2329 | 2336 | struct sk_buff *crs = l_ptr->first_out; |
2330 | 2337 | struct link *tunnel = l_ptr->owner->active_links[0]; |
2331 | - int split_bundles = tipc_node_has_redundant_links(l_ptr->owner); | |
2332 | 2338 | struct tipc_msg tunnel_hdr; |
2339 | + int split_bundles; | |
2333 | 2340 | |
2334 | 2341 | if (!tunnel) |
2335 | 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 | 2347 | return; |
2348 | + } | |
2339 | 2349 | |
2340 | 2350 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2341 | 2351 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); |
2342 | 2352 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2343 | 2353 | msg_set_msgcnt(&tunnel_hdr, msgcount); |
2354 | + dbg("Link changeover requires %u tunnel messages\n", msgcount); | |
2344 | 2355 | |
2345 | 2356 | if (!l_ptr->first_out) { |
2346 | 2357 | struct sk_buff *buf; |
... | ... | @@ -2360,6 +2371,9 @@ |
2360 | 2371 | return; |
2361 | 2372 | } |
2362 | 2373 | |
2374 | + split_bundles = (l_ptr->owner->active_links[0] != | |
2375 | + l_ptr->owner->active_links[1]); | |
2376 | + | |
2363 | 2377 | while (crs) { |
2364 | 2378 | struct tipc_msg *msg = buf_msg(crs); |
2365 | 2379 | |
2366 | 2380 | |
... | ... | @@ -2497,11 +2511,13 @@ |
2497 | 2511 | dest_link->name); |
2498 | 2512 | tipc_link_reset(dest_link); |
2499 | 2513 | dest_link->exp_msg_count = msg_count; |
2514 | + dbg("Expecting %u tunnelled messages\n", msg_count); | |
2500 | 2515 | if (!msg_count) |
2501 | 2516 | goto exit; |
2502 | 2517 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { |
2503 | 2518 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); |
2504 | 2519 | dest_link->exp_msg_count = msg_count; |
2520 | + dbg("Expecting %u tunnelled messages\n", msg_count); | |
2505 | 2521 | if (!msg_count) |
2506 | 2522 | goto exit; |
2507 | 2523 | } |
... | ... | @@ -2509,6 +2525,8 @@ |
2509 | 2525 | /* Receive original message */ |
2510 | 2526 | |
2511 | 2527 | if (dest_link->exp_msg_count == 0) { |
2528 | + warn("Link switchover error, " | |
2529 | + "got too many tunnelled messages\n"); | |
2512 | 2530 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); |
2513 | 2531 | dbg_print_link(dest_link, "LINK:"); |
2514 | 2532 | goto exit; |
net/tipc/node.c
... | ... | @@ -125,6 +125,8 @@ |
125 | 125 | { |
126 | 126 | struct link **active = &n_ptr->active_links[0]; |
127 | 127 | |
128 | + n_ptr->working_links++; | |
129 | + | |
128 | 130 | info("Established link <%s> on network plane %c\n", |
129 | 131 | l_ptr->name, l_ptr->b_ptr->net_plane); |
130 | 132 | |
... | ... | @@ -185,6 +187,8 @@ |
185 | 187 | { |
186 | 188 | struct link **active; |
187 | 189 | |
190 | + n_ptr->working_links--; | |
191 | + | |
188 | 192 | if (!tipc_link_is_active(l_ptr)) { |
189 | 193 | info("Lost standby link <%s> on network plane %c\n", |
190 | 194 | l_ptr->name, l_ptr->b_ptr->net_plane); |
... | ... | @@ -214,8 +218,7 @@ |
214 | 218 | |
215 | 219 | int tipc_node_has_redundant_links(struct node *n_ptr) |
216 | 220 | { |
217 | - return (tipc_node_has_active_links(n_ptr) && | |
218 | - (n_ptr->active_links[0] != n_ptr->active_links[1])); | |
221 | + return (n_ptr->working_links > 1); | |
219 | 222 | } |
220 | 223 | |
221 | 224 | static int tipc_node_has_active_routes(struct node *n_ptr) |
net/tipc/node.h
... | ... | @@ -51,6 +51,7 @@ |
51 | 51 | * @nsub: list of "node down" subscriptions monitoring node |
52 | 52 | * @active_links: pointers to active links to node |
53 | 53 | * @links: pointers to all links to node |
54 | + * @working_links: number of working links to node (both active and standby) | |
54 | 55 | * @link_cnt: number of links to node |
55 | 56 | * @permit_changeover: non-zero if node has redundant links to this system |
56 | 57 | * @routers: bitmap (used for multicluster communication) |
... | ... | @@ -76,6 +77,7 @@ |
76 | 77 | struct link *active_links[2]; |
77 | 78 | struct link *links[MAX_BEARERS]; |
78 | 79 | int link_cnt; |
80 | + int working_links; | |
79 | 81 | int permit_changeover; |
80 | 82 | u32 routers[512/32]; |
81 | 83 | int last_router; |