aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c98
1 files changed, 58 insertions, 40 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index c052437a7cfa..35a2da688db1 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -79,19 +79,49 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
79/* 79/*
80 * Out-of-range value for link session numbers 80 * Out-of-range value for link session numbers
81 */ 81 */
82#define INVALID_SESSION 0x10000 82#define WILDCARD_SESSION 0x10000
83 83
84/* 84/* State value stored in 'failover_pkts'
85 * Link state events:
86 */ 85 */
87#define STARTING_EVT 856384768 /* link processing trigger */ 86#define FIRST_FAILOVER 0xffffu
88#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */
89#define SILENCE_EVT 560817u /* timer dicovered silence from peer */
90 87
91/* 88/* Link FSM states and events:
92 * State value stored in 'failover_pkts'
93 */ 89 */
94#define FIRST_FAILOVER 0xffffu 90enum {
91 WORKING_WORKING,
92 WORKING_UNKNOWN,
93 RESET_RESET,
94 RESET_UNKNOWN
95};
96
97enum {
98 PEER_RESET_EVT = RESET_MSG,
99 ACTIVATE_EVT = ACTIVATE_MSG,
100 TRAFFIC_EVT, /* Any other valid msg from peer */
101 SILENCE_EVT /* Peer was silent during last timer interval*/
102};
103
104/* Link FSM state checking routines
105 */
106static int link_working_working(struct tipc_link *l)
107{
108 return l->state == WORKING_WORKING;
109}
110
111static int link_working_unknown(struct tipc_link *l)
112{
113 return l->state == WORKING_UNKNOWN;
114}
115
116static int link_reset_unknown(struct tipc_link *l)
117{
118 return l->state == RESET_UNKNOWN;
119}
120
121static int link_reset_reset(struct tipc_link *l)
122{
123 return l->state == RESET_RESET;
124}
95 125
96static void link_handle_out_of_seq_msg(struct tipc_link *link, 126static void link_handle_out_of_seq_msg(struct tipc_link *link,
97 struct sk_buff *skb); 127 struct sk_buff *skb);
@@ -268,7 +298,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
268 /* note: peer i/f name is updated by reset/activate message */ 298 /* note: peer i/f name is updated by reset/activate message */
269 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); 299 memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
270 l_ptr->owner = n_ptr; 300 l_ptr->owner = n_ptr;
271 l_ptr->peer_session = INVALID_SESSION; 301 l_ptr->peer_session = WILDCARD_SESSION;
272 l_ptr->bearer_id = b_ptr->identity; 302 l_ptr->bearer_id = b_ptr->identity;
273 link_set_supervision_props(l_ptr, b_ptr->tolerance); 303 link_set_supervision_props(l_ptr, b_ptr->tolerance);
274 l_ptr->state = RESET_UNKNOWN; 304 l_ptr->state = RESET_UNKNOWN;
@@ -297,8 +327,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
297 link_reset_statistics(l_ptr); 327 link_reset_statistics(l_ptr);
298 tipc_node_attach_link(n_ptr, l_ptr); 328 tipc_node_attach_link(n_ptr, l_ptr);
299 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr); 329 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr);
300 link_state_event(l_ptr, STARTING_EVT); 330 link_set_timer(l_ptr, l_ptr->keepalive_intv);
301
302 return l_ptr; 331 return l_ptr;
303} 332}
304 333
@@ -311,7 +340,6 @@ void tipc_link_delete(struct tipc_link *l)
311 tipc_link_reset(l); 340 tipc_link_reset(l);
312 if (del_timer(&l->timer)) 341 if (del_timer(&l->timer))
313 tipc_link_put(l); 342 tipc_link_put(l);
314 l->flags |= LINK_STOPPED;
315 /* Delete link now, or when timer is finished: */ 343 /* Delete link now, or when timer is finished: */
316 tipc_link_reset_fragments(l); 344 tipc_link_reset_fragments(l);
317 tipc_node_detach_link(l->owner, l); 345 tipc_node_detach_link(l->owner, l);
@@ -438,7 +466,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
438 msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff)); 466 msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff));
439 467
440 /* Link is down, accept any session */ 468 /* Link is down, accept any session */
441 l_ptr->peer_session = INVALID_SESSION; 469 l_ptr->peer_session = WILDCARD_SESSION;
442 470
443 /* Prepare for renewed mtu size negotiation */ 471 /* Prepare for renewed mtu size negotiation */
444 l_ptr->mtu = l_ptr->advertised_mtu; 472 l_ptr->mtu = l_ptr->advertised_mtu;
@@ -452,7 +480,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
452 tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr); 480 tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr);
453 481
454 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) { 482 if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
455 l_ptr->flags |= LINK_FAILINGOVER; 483 l_ptr->exec_mode = TIPC_LINK_BLOCKED;
456 l_ptr->failover_checkpt = l_ptr->rcv_nxt; 484 l_ptr->failover_checkpt = l_ptr->rcv_nxt;
457 pl->failover_pkts = FIRST_FAILOVER; 485 pl->failover_pkts = FIRST_FAILOVER;
458 pl->failover_checkpt = l_ptr->rcv_nxt; 486 pl->failover_checkpt = l_ptr->rcv_nxt;
@@ -496,21 +524,14 @@ static void link_activate(struct tipc_link *link)
496static void link_state_event(struct tipc_link *l_ptr, unsigned int event) 524static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
497{ 525{
498 struct tipc_link *other; 526 struct tipc_link *other;
499 unsigned long timer_intv = l_ptr->keepalive_intv;
500
501 if (l_ptr->flags & LINK_STOPPED)
502 return;
503
504 if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
505 return; /* Not yet. */
506 527
507 if (l_ptr->flags & LINK_FAILINGOVER) 528 if (l_ptr->exec_mode == TIPC_LINK_BLOCKED)
508 return; 529 return;
509 530
510 switch (l_ptr->state) { 531 switch (l_ptr->state) {
511 case WORKING_WORKING: 532 case WORKING_WORKING:
512 switch (event) { 533 switch (event) {
513 case TRAFFIC_MSG_EVT: 534 case TRAFFIC_EVT:
514 case ACTIVATE_MSG: 535 case ACTIVATE_MSG:
515 l_ptr->silent_intv_cnt = 0; 536 l_ptr->silent_intv_cnt = 0;
516 break; 537 break;
@@ -538,7 +559,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
538 break; 559 break;
539 case WORKING_UNKNOWN: 560 case WORKING_UNKNOWN:
540 switch (event) { 561 switch (event) {
541 case TRAFFIC_MSG_EVT: 562 case TRAFFIC_EVT:
542 case ACTIVATE_MSG: 563 case ACTIVATE_MSG:
543 l_ptr->state = WORKING_WORKING; 564 l_ptr->state = WORKING_WORKING;
544 l_ptr->silent_intv_cnt = 0; 565 l_ptr->silent_intv_cnt = 0;
@@ -576,7 +597,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
576 break; 597 break;
577 case RESET_UNKNOWN: 598 case RESET_UNKNOWN:
578 switch (event) { 599 switch (event) {
579 case TRAFFIC_MSG_EVT: 600 case TRAFFIC_EVT:
580 break; 601 break;
581 case ACTIVATE_MSG: 602 case ACTIVATE_MSG:
582 other = node_active_link(l_ptr->owner, 0); 603 other = node_active_link(l_ptr->owner, 0);
@@ -593,10 +614,6 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
593 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, 614 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
594 1, 0, 0, 0); 615 1, 0, 0, 0);
595 break; 616 break;
596 case STARTING_EVT:
597 l_ptr->flags |= LINK_STARTED;
598 link_set_timer(l_ptr, timer_intv);
599 break;
600 case SILENCE_EVT: 617 case SILENCE_EVT:
601 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0); 618 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0);
602 break; 619 break;
@@ -606,7 +623,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
606 break; 623 break;
607 case RESET_RESET: 624 case RESET_RESET:
608 switch (event) { 625 switch (event) {
609 case TRAFFIC_MSG_EVT: 626 case TRAFFIC_EVT:
610 case ACTIVATE_MSG: 627 case ACTIVATE_MSG:
611 other = node_active_link(l_ptr->owner, 0); 628 other = node_active_link(l_ptr->owner, 0);
612 if (other && link_working_unknown(other)) 629 if (other && link_working_unknown(other))
@@ -975,7 +992,7 @@ static bool link_synch(struct tipc_link *l)
975 if (skb_queue_len(pl->inputq) > post_synch) 992 if (skb_queue_len(pl->inputq) > post_synch)
976 return false; 993 return false;
977synched: 994synched:
978 l->flags &= ~LINK_SYNCHING; 995 l->exec_mode = TIPC_LINK_OPEN;
979 return true; 996 return true;
980} 997}
981 998
@@ -1091,7 +1108,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1091 } 1108 }
1092 1109
1093 /* Traffic message. Conditionally activate link */ 1110 /* Traffic message. Conditionally activate link */
1094 link_state_event(l_ptr, TRAFFIC_MSG_EVT); 1111 link_state_event(l_ptr, TRAFFIC_EVT);
1095 1112
1096 if (link_working_working(l_ptr)) { 1113 if (link_working_working(l_ptr)) {
1097 /* Re-insert buffer in front of queue */ 1114 /* Re-insert buffer in front of queue */
@@ -1112,7 +1129,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1112 l_ptr->silent_intv_cnt = 0; 1129 l_ptr->silent_intv_cnt = 0;
1113 1130
1114 /* Synchronize with parallel link if applicable */ 1131 /* Synchronize with parallel link if applicable */
1115 if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { 1132 if (unlikely((l_ptr->exec_mode == TIPC_LINK_TUNNEL) &&
1133 !msg_dup(msg))) {
1116 if (!link_synch(l_ptr)) 1134 if (!link_synch(l_ptr))
1117 goto unlock; 1135 goto unlock;
1118 } 1136 }
@@ -1193,7 +1211,7 @@ static void tipc_link_input(struct tipc_link *link, struct sk_buff *skb)
1193 switch (msg_user(msg)) { 1211 switch (msg_user(msg)) {
1194 case TUNNEL_PROTOCOL: 1212 case TUNNEL_PROTOCOL:
1195 if (msg_dup(msg)) { 1213 if (msg_dup(msg)) {
1196 link->flags |= LINK_SYNCHING; 1214 link->exec_mode = TIPC_LINK_TUNNEL;
1197 link->synch_point = msg_seqno(msg_get_wrapped(msg)); 1215 link->synch_point = msg_seqno(msg_get_wrapped(msg));
1198 kfree_skb(skb); 1216 kfree_skb(skb);
1199 break; 1217 break;
@@ -1315,7 +1333,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1315 u16 last_rcv; 1333 u16 last_rcv;
1316 1334
1317 /* Don't send protocol message during link failover */ 1335 /* Don't send protocol message during link failover */
1318 if (l_ptr->flags & LINK_FAILINGOVER) 1336 if (l_ptr->exec_mode == TIPC_LINK_BLOCKED)
1319 return; 1337 return;
1320 1338
1321 /* Abort non-RESET send if communication with node is prohibited */ 1339 /* Abort non-RESET send if communication with node is prohibited */
@@ -1390,7 +1408,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1390 u32 msg_tol; 1408 u32 msg_tol;
1391 struct tipc_msg *msg = buf_msg(buf); 1409 struct tipc_msg *msg = buf_msg(buf);
1392 1410
1393 if (l_ptr->flags & LINK_FAILINGOVER) 1411 if (l_ptr->exec_mode == TIPC_LINK_BLOCKED)
1394 goto exit; 1412 goto exit;
1395 1413
1396 if (l_ptr->net_plane != msg_net_plane(msg)) 1414 if (l_ptr->net_plane != msg_net_plane(msg))
@@ -1401,7 +1419,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1401 1419
1402 case RESET_MSG: 1420 case RESET_MSG:
1403 if (!link_working_unknown(l_ptr) && 1421 if (!link_working_unknown(l_ptr) &&
1404 (l_ptr->peer_session != INVALID_SESSION)) { 1422 (l_ptr->peer_session != WILDCARD_SESSION)) {
1405 if (less_eq(msg_session(msg), l_ptr->peer_session)) 1423 if (less_eq(msg_session(msg), l_ptr->peer_session))
1406 break; /* duplicate or old reset: ignore */ 1424 break; /* duplicate or old reset: ignore */
1407 } 1425 }
@@ -1465,7 +1483,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1465 /* Record reception; force mismatch at next timeout: */ 1483 /* Record reception; force mismatch at next timeout: */
1466 l_ptr->silent_intv_cnt = 0; 1484 l_ptr->silent_intv_cnt = 0;
1467 1485
1468 link_state_event(l_ptr, TRAFFIC_MSG_EVT); 1486 link_state_event(l_ptr, TRAFFIC_EVT);
1469 l_ptr->stats.recv_states++; 1487 l_ptr->stats.recv_states++;
1470 if (link_reset_unknown(l_ptr)) 1488 if (link_reset_unknown(l_ptr))
1471 break; 1489 break;
@@ -1704,7 +1722,7 @@ static bool tipc_link_failover_rcv(struct tipc_link *link,
1704 } 1722 }
1705exit: 1723exit:
1706 if (!link->failover_pkts && pl) 1724 if (!link->failover_pkts && pl)
1707 pl->flags &= ~LINK_FAILINGOVER; 1725 pl->exec_mode = TIPC_LINK_OPEN;
1708 kfree_skb(*skb); 1726 kfree_skb(*skb);
1709 *skb = iskb; 1727 *skb = iskb;
1710 return *skb; 1728 return *skb;