[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>
This commit is contained in:
Allan Stephens 2006-06-25 23:52:50 -07:00 committed by David S. Miller
parent a10bd924a4
commit 5392d64688
3 changed files with 31 additions and 8 deletions

View File

@ -690,6 +690,7 @@ void tipc_link_reset(struct link *l_ptr)
struct sk_buff *buf;
u32 prev_state = l_ptr->state;
u32 checkpoint = l_ptr->next_in_no;
int was_active_link = tipc_link_is_active(l_ptr);
msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
@ -711,7 +712,7 @@ void tipc_link_reset(struct link *l_ptr)
tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
dbg_link_dump();
#endif
if (tipc_node_has_active_links(l_ptr->owner) &&
if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&
l_ptr->owner->permit_changeover) {
l_ptr->reset_checkpoint = checkpoint;
l_ptr->exp_msg_count = START_CHANGEOVER;
@ -754,7 +755,7 @@ void tipc_link_reset(struct link *l_ptr)
static void link_activate(struct link *l_ptr)
{
l_ptr->next_in_no = 1;
l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
tipc_node_link_up(l_ptr->owner, l_ptr);
tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
link_send_event(tipc_cfg_link_event, l_ptr, 1);
@ -2303,12 +2304,18 @@ void tipc_link_tunnel(struct link *l_ptr,
u32 length = msg_size(msg);
tunnel = l_ptr->owner->active_links[selector & 1];
if (!tipc_link_is_up(tunnel))
if (!tipc_link_is_up(tunnel)) {
warn("Link changeover error, "
"tunnel link no longer available\n");
return;
}
msg_set_size(tunnel_hdr, length + INT_H_SIZE);
buf = buf_acquire(length + INT_H_SIZE);
if (!buf)
if (!buf) {
warn("Link changeover error, "
"unable to send tunnel msg\n");
return;
}
memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE);
memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length);
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)
u32 msgcount = l_ptr->out_queue_size;
struct sk_buff *crs = l_ptr->first_out;
struct link *tunnel = l_ptr->owner->active_links[0];
int split_bundles = tipc_node_has_redundant_links(l_ptr->owner);
struct tipc_msg tunnel_hdr;
int split_bundles;
if (!tunnel)
return;
if (!l_ptr->owner->permit_changeover)
if (!l_ptr->owner->permit_changeover) {
warn("Link changeover error, "
"peer did not permit changeover\n");
return;
}
msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
msg_set_msgcnt(&tunnel_hdr, msgcount);
dbg("Link changeover requires %u tunnel messages\n", msgcount);
if (!l_ptr->first_out) {
struct sk_buff *buf;
@ -2360,6 +2371,9 @@ void tipc_link_changeover(struct link *l_ptr)
return;
}
split_bundles = (l_ptr->owner->active_links[0] !=
l_ptr->owner->active_links[1]);
while (crs) {
struct tipc_msg *msg = buf_msg(crs);
@ -2497,11 +2511,13 @@ static int link_recv_changeover_msg(struct link **l_ptr,
dest_link->name);
tipc_link_reset(dest_link);
dest_link->exp_msg_count = msg_count;
dbg("Expecting %u tunnelled messages\n", msg_count);
if (!msg_count)
goto exit;
} else if (dest_link->exp_msg_count == START_CHANGEOVER) {
msg_dbg(tunnel_msg, "BLK/FIRST/<REC<");
dest_link->exp_msg_count = msg_count;
dbg("Expecting %u tunnelled messages\n", msg_count);
if (!msg_count)
goto exit;
}
@ -2509,6 +2525,8 @@ static int link_recv_changeover_msg(struct link **l_ptr,
/* Receive original message */
if (dest_link->exp_msg_count == 0) {
warn("Link switchover error, "
"got too many tunnelled messages\n");
msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<");
dbg_print_link(dest_link, "LINK:");
goto exit;

View File

@ -125,6 +125,8 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
{
struct link **active = &n_ptr->active_links[0];
n_ptr->working_links++;
info("Established link <%s> on network plane %c\n",
l_ptr->name, l_ptr->b_ptr->net_plane);
@ -185,6 +187,8 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
{
struct link **active;
n_ptr->working_links--;
if (!tipc_link_is_active(l_ptr)) {
info("Lost standby link <%s> on network plane %c\n",
l_ptr->name, l_ptr->b_ptr->net_plane);
@ -214,8 +218,7 @@ int tipc_node_has_active_links(struct node *n_ptr)
int tipc_node_has_redundant_links(struct node *n_ptr)
{
return (tipc_node_has_active_links(n_ptr) &&
(n_ptr->active_links[0] != n_ptr->active_links[1]));
return (n_ptr->working_links > 1);
}
static int tipc_node_has_active_routes(struct node *n_ptr)

View File

@ -51,6 +51,7 @@
* @nsub: list of "node down" subscriptions monitoring node
* @active_links: pointers to active links to node
* @links: pointers to all links to node
* @working_links: number of working links to node (both active and standby)
* @link_cnt: number of links to node
* @permit_changeover: non-zero if node has redundant links to this system
* @routers: bitmap (used for multicluster communication)
@ -76,6 +77,7 @@ struct node {
struct link *active_links[2];
struct link *links[MAX_BEARERS];
int link_cnt;
int working_links;
int permit_changeover;
u32 routers[512/32];
int last_router;