aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c344
-rw-r--r--net/tipc/link.h7
2 files changed, 195 insertions, 156 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 657ba91fde41..5d2f9198c6bc 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -88,10 +88,10 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
88/* Link FSM states and events: 88/* Link FSM states and events:
89 */ 89 */
90enum { 90enum {
91 WORKING_WORKING, 91 TIPC_LINK_WORKING,
92 WORKING_UNKNOWN, 92 TIPC_LINK_PROBING,
93 RESET_RESET, 93 TIPC_LINK_RESETTING,
94 RESET_UNKNOWN 94 TIPC_LINK_ESTABLISHING
95}; 95};
96 96
97enum { 97enum {
@@ -103,24 +103,24 @@ enum {
103 103
104/* Link FSM state checking routines 104/* Link FSM state checking routines
105 */ 105 */
106static int link_working_working(struct tipc_link *l) 106static int link_working(struct tipc_link *l)
107{ 107{
108 return l->state == WORKING_WORKING; 108 return l->state == TIPC_LINK_WORKING;
109} 109}
110 110
111static int link_working_unknown(struct tipc_link *l) 111static int link_probing(struct tipc_link *l)
112{ 112{
113 return l->state == WORKING_UNKNOWN; 113 return l->state == TIPC_LINK_PROBING;
114} 114}
115 115
116static int link_reset_unknown(struct tipc_link *l) 116static int link_resetting(struct tipc_link *l)
117{ 117{
118 return l->state == RESET_UNKNOWN; 118 return l->state == TIPC_LINK_RESETTING;
119} 119}
120 120
121static int link_reset_reset(struct tipc_link *l) 121static int link_establishing(struct tipc_link *l)
122{ 122{
123 return l->state == RESET_RESET; 123 return l->state == TIPC_LINK_ESTABLISHING;
124} 124}
125 125
126static void link_handle_out_of_seq_msg(struct tipc_link *link, 126static void link_handle_out_of_seq_msg(struct tipc_link *link,
@@ -140,6 +140,8 @@ static void tipc_link_input(struct tipc_link *l, struct sk_buff *skb);
140static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb); 140static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb);
141static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb); 141static bool tipc_link_failover_rcv(struct tipc_link *l, struct sk_buff **skb);
142static void link_set_timer(struct tipc_link *link, unsigned long time); 142static void link_set_timer(struct tipc_link *link, unsigned long time);
143static void link_activate(struct tipc_link *link);
144
143/* 145/*
144 * Simple link routines 146 * Simple link routines
145 */ 147 */
@@ -179,7 +181,7 @@ int tipc_link_is_up(struct tipc_link *l_ptr)
179{ 181{
180 if (!l_ptr) 182 if (!l_ptr)
181 return 0; 183 return 0;
182 return link_working_working(l_ptr) || link_working_unknown(l_ptr); 184 return link_working(l_ptr) || link_probing(l_ptr);
183} 185}
184 186
185int tipc_link_is_active(struct tipc_link *l) 187int tipc_link_is_active(struct tipc_link *l)
@@ -234,8 +236,11 @@ static void link_timeout(unsigned long data)
234 } 236 }
235 237
236 /* do all other link processing performed on a periodic basis */ 238 /* do all other link processing performed on a periodic basis */
237 if (l_ptr->silent_intv_cnt || tipc_bclink_acks_missing(l_ptr->owner)) 239 if (l_ptr->silent_intv_cnt)
238 link_state_event(l_ptr, SILENCE_EVT); 240 link_state_event(l_ptr, SILENCE_EVT);
241 else if (link_working(l_ptr) && tipc_bclink_acks_missing(l_ptr->owner))
242 tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0);
243
239 l_ptr->silent_intv_cnt++; 244 l_ptr->silent_intv_cnt++;
240 if (skb_queue_len(&l_ptr->backlogq)) 245 if (skb_queue_len(&l_ptr->backlogq))
241 tipc_link_push_packets(l_ptr); 246 tipc_link_push_packets(l_ptr);
@@ -304,7 +309,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
304 l_ptr->peer_session = WILDCARD_SESSION; 309 l_ptr->peer_session = WILDCARD_SESSION;
305 l_ptr->bearer_id = b_ptr->identity; 310 l_ptr->bearer_id = b_ptr->identity;
306 link_set_supervision_props(l_ptr, b_ptr->tolerance); 311 link_set_supervision_props(l_ptr, b_ptr->tolerance);
307 l_ptr->state = RESET_UNKNOWN; 312 l_ptr->state = TIPC_LINK_RESETTING;
308 313
309 l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; 314 l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
310 msg = l_ptr->pmsg; 315 msg = l_ptr->pmsg;
@@ -367,6 +372,134 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
367} 372}
368 373
369/** 374/**
375 * tipc_link_fsm_evt - link finite state machine
376 * @l: pointer to link
377 * @evt: state machine event to be processed
378 * @xmitq: queue to prepend created protocol message, if any
379 */
380static int tipc_link_fsm_evt(struct tipc_link *l, int evt,
381 struct sk_buff_head *xmitq)
382{
383 int mtyp = 0, rc = 0;
384 struct tipc_link *pl;
385 enum {
386 LINK_RESET = 1,
387 LINK_ACTIVATE = (1 << 1),
388 SND_PROBE = (1 << 2),
389 SND_STATE = (1 << 3),
390 SND_RESET = (1 << 4),
391 SND_ACTIVATE = (1 << 5)
392 } actions = 0;
393
394 if (l->exec_mode == TIPC_LINK_BLOCKED)
395 return rc;
396
397 switch (l->state) {
398 case TIPC_LINK_WORKING:
399 switch (evt) {
400 case TRAFFIC_EVT:
401 case ACTIVATE_EVT:
402 break;
403 case SILENCE_EVT:
404 l->state = TIPC_LINK_PROBING;
405 actions |= SND_PROBE;
406 break;
407 case PEER_RESET_EVT:
408 actions |= LINK_RESET | SND_ACTIVATE;
409 break;
410 default:
411 pr_debug("%s%u WORKING\n", link_unk_evt, evt);
412 }
413 break;
414 case TIPC_LINK_PROBING:
415 switch (evt) {
416 case TRAFFIC_EVT:
417 case ACTIVATE_EVT:
418 l->state = TIPC_LINK_WORKING;
419 break;
420 case PEER_RESET_EVT:
421 actions |= LINK_RESET | SND_ACTIVATE;
422 break;
423 case SILENCE_EVT:
424 if (l->silent_intv_cnt <= l->abort_limit) {
425 actions |= SND_PROBE;
426 break;
427 }
428 actions |= LINK_RESET | SND_RESET;
429 break;
430 default:
431 pr_err("%s%u PROBING\n", link_unk_evt, evt);
432 }
433 break;
434 case TIPC_LINK_RESETTING:
435 switch (evt) {
436 case TRAFFIC_EVT:
437 break;
438 case ACTIVATE_EVT:
439 pl = node_active_link(l->owner, 0);
440 if (pl && link_probing(pl))
441 break;
442 actions |= LINK_ACTIVATE;
443 if (l->owner->working_links == 1)
444 tipc_link_sync_xmit(l);
445 break;
446 case PEER_RESET_EVT:
447 l->state = TIPC_LINK_ESTABLISHING;
448 actions |= SND_ACTIVATE;
449 break;
450 case SILENCE_EVT:
451 actions |= SND_RESET;
452 break;
453 default:
454 pr_err("%s%u in RESETTING\n", link_unk_evt, evt);
455 }
456 break;
457 case TIPC_LINK_ESTABLISHING:
458 switch (evt) {
459 case TRAFFIC_EVT:
460 case ACTIVATE_EVT:
461 pl = node_active_link(l->owner, 0);
462 if (pl && link_probing(pl))
463 break;
464 actions |= LINK_ACTIVATE;
465 if (l->owner->working_links == 1)
466 tipc_link_sync_xmit(l);
467 break;
468 case PEER_RESET_EVT:
469 break;
470 case SILENCE_EVT:
471 actions |= SND_ACTIVATE;
472 break;
473 default:
474 pr_err("%s%u ESTABLISHING\n", link_unk_evt, evt);
475 }
476 break;
477 default:
478 pr_err("Unknown link state %u/%u\n", l->state, evt);
479 }
480
481 /* Perform actions as decided by FSM */
482 if (actions & LINK_RESET) {
483 l->exec_mode = TIPC_LINK_BLOCKED;
484 rc |= TIPC_LINK_DOWN_EVT;
485 }
486 if (actions & LINK_ACTIVATE) {
487 l->exec_mode = TIPC_LINK_OPEN;
488 rc |= TIPC_LINK_UP_EVT;
489 }
490 if (actions & (SND_STATE | SND_PROBE))
491 mtyp = STATE_MSG;
492 if (actions & SND_RESET)
493 mtyp = RESET_MSG;
494 if (actions & SND_ACTIVATE)
495 mtyp = ACTIVATE_MSG;
496 if (actions & (SND_PROBE | SND_STATE | SND_RESET | SND_ACTIVATE))
497 tipc_link_build_proto_msg(l, mtyp, actions & SND_PROBE,
498 0, 0, 0, xmitq);
499 return rc;
500}
501
502/**
370 * link_schedule_user - schedule a message sender for wakeup after congestion 503 * link_schedule_user - schedule a message sender for wakeup after congestion
371 * @link: congested link 504 * @link: congested link
372 * @list: message that was attempted sent 505 * @list: message that was attempted sent
@@ -474,9 +607,10 @@ void tipc_link_reset(struct tipc_link *l_ptr)
474 /* Prepare for renewed mtu size negotiation */ 607 /* Prepare for renewed mtu size negotiation */
475 l_ptr->mtu = l_ptr->advertised_mtu; 608 l_ptr->mtu = l_ptr->advertised_mtu;
476 609
477 l_ptr->state = RESET_UNKNOWN; 610 l_ptr->state = TIPC_LINK_RESETTING;
478 611
479 if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) 612 if ((prev_state == TIPC_LINK_RESETTING) ||
613 (prev_state == TIPC_LINK_ESTABLISHING))
480 return; 614 return;
481 615
482 tipc_node_link_down(l_ptr->owner, l_ptr->bearer_id); 616 tipc_node_link_down(l_ptr->owner, l_ptr->bearer_id);
@@ -515,6 +649,8 @@ static void link_activate(struct tipc_link *link)
515 link->rcv_nxt = 1; 649 link->rcv_nxt = 1;
516 link->stats.recv_info = 1; 650 link->stats.recv_info = 1;
517 link->silent_intv_cnt = 0; 651 link->silent_intv_cnt = 0;
652 link->state = TIPC_LINK_WORKING;
653 link->exec_mode = TIPC_LINK_OPEN;
518 tipc_node_link_up(node, link->bearer_id); 654 tipc_node_link_up(node, link->bearer_id);
519 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr); 655 tipc_bearer_add_dest(node->net, link->bearer_id, link->addr);
520} 656}
@@ -524,132 +660,29 @@ static void link_activate(struct tipc_link *link)
524 * @l_ptr: pointer to link 660 * @l_ptr: pointer to link
525 * @event: state machine event to process 661 * @event: state machine event to process
526 */ 662 */
527static void link_state_event(struct tipc_link *l_ptr, unsigned int event) 663static void link_state_event(struct tipc_link *l, unsigned int evt)
528{ 664{
529 struct tipc_link *other; 665 int rc;
666 struct sk_buff_head xmitq;
667 struct sk_buff *skb;
530 668
531 if (l_ptr->exec_mode == TIPC_LINK_BLOCKED) 669 if (l->exec_mode == TIPC_LINK_BLOCKED)
532 return; 670 return;
533 671
534 switch (l_ptr->state) { 672 __skb_queue_head_init(&xmitq);
535 case WORKING_WORKING: 673
536 switch (event) { 674 rc = tipc_link_fsm_evt(l, evt, &xmitq);
537 case TRAFFIC_EVT: 675
538 case ACTIVATE_MSG: 676 if (rc & TIPC_LINK_UP_EVT)
539 l_ptr->silent_intv_cnt = 0; 677 link_activate(l);
540 break; 678
541 case SILENCE_EVT: 679 if (rc & TIPC_LINK_DOWN_EVT)
542 if (!l_ptr->silent_intv_cnt) { 680 tipc_link_reset(l);
543 if (tipc_bclink_acks_missing(l_ptr->owner)) 681
544 tipc_link_proto_xmit(l_ptr, STATE_MSG, 682 skb = __skb_dequeue(&xmitq);
545 0, 0, 0, 0); 683 if (!skb)
546 break; 684 return;
547 } 685 tipc_bearer_send(l->owner->net, l->bearer_id, skb, &l->media_addr);
548 l_ptr->state = WORKING_UNKNOWN;
549 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
550 break;
551 case RESET_MSG:
552 pr_debug("%s<%s>, requested by peer\n",
553 link_rst_msg, l_ptr->name);
554 tipc_link_reset(l_ptr);
555 l_ptr->state = RESET_RESET;
556 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
557 0, 0, 0, 0);
558 break;
559 default:
560 pr_debug("%s%u in WW state\n", link_unk_evt, event);
561 }
562 break;
563 case WORKING_UNKNOWN:
564 switch (event) {
565 case TRAFFIC_EVT:
566 case ACTIVATE_MSG:
567 l_ptr->state = WORKING_WORKING;
568 l_ptr->silent_intv_cnt = 0;
569 break;
570 case RESET_MSG:
571 pr_debug("%s<%s>, requested by peer while probing\n",
572 link_rst_msg, l_ptr->name);
573 tipc_link_reset(l_ptr);
574 l_ptr->state = RESET_RESET;
575 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
576 0, 0, 0, 0);
577 break;
578 case SILENCE_EVT:
579 if (!l_ptr->silent_intv_cnt) {
580 l_ptr->state = WORKING_WORKING;
581 if (tipc_bclink_acks_missing(l_ptr->owner))
582 tipc_link_proto_xmit(l_ptr, STATE_MSG,
583 0, 0, 0, 0);
584 } else if (l_ptr->silent_intv_cnt <
585 l_ptr->abort_limit) {
586 tipc_link_proto_xmit(l_ptr, STATE_MSG,
587 1, 0, 0, 0);
588 } else { /* Link has failed */
589 pr_debug("%s<%s>, peer not responding\n",
590 link_rst_msg, l_ptr->name);
591 tipc_link_reset(l_ptr);
592 l_ptr->state = RESET_UNKNOWN;
593 tipc_link_proto_xmit(l_ptr, RESET_MSG,
594 0, 0, 0, 0);
595 }
596 break;
597 default:
598 pr_err("%s%u in WU state\n", link_unk_evt, event);
599 }
600 break;
601 case RESET_UNKNOWN:
602 switch (event) {
603 case TRAFFIC_EVT:
604 break;
605 case ACTIVATE_MSG:
606 other = node_active_link(l_ptr->owner, 0);
607 if (other && link_working_unknown(other))
608 break;
609 l_ptr->state = WORKING_WORKING;
610 link_activate(l_ptr);
611 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
612 if (l_ptr->owner->working_links == 1)
613 tipc_link_sync_xmit(l_ptr);
614 break;
615 case RESET_MSG:
616 l_ptr->state = RESET_RESET;
617 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
618 1, 0, 0, 0);
619 break;
620 case SILENCE_EVT:
621 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0);
622 break;
623 default:
624 pr_err("%s%u in RU state\n", link_unk_evt, event);
625 }
626 break;
627 case RESET_RESET:
628 switch (event) {
629 case TRAFFIC_EVT:
630 case ACTIVATE_MSG:
631 other = node_active_link(l_ptr->owner, 0);
632 if (other && link_working_unknown(other))
633 break;
634 l_ptr->state = WORKING_WORKING;
635 link_activate(l_ptr);
636 tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0);
637 if (l_ptr->owner->working_links == 1)
638 tipc_link_sync_xmit(l_ptr);
639 break;
640 case RESET_MSG:
641 break;
642 case SILENCE_EVT:
643 tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
644 0, 0, 0, 0);
645 break;
646 default:
647 pr_err("%s%u in RR state\n", link_unk_evt, event);
648 }
649 break;
650 default:
651 pr_err("Unknown link state %u/%u\n", l_ptr->state, event);
652 }
653} 686}
654 687
655/** 688/**
@@ -1102,7 +1135,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1102 link_prepare_wakeup(l_ptr); 1135 link_prepare_wakeup(l_ptr);
1103 1136
1104 /* Process the incoming packet */ 1137 /* Process the incoming packet */
1105 if (unlikely(!link_working_working(l_ptr))) { 1138 if (unlikely(!link_working(l_ptr))) {
1106 if (msg_user(msg) == LINK_PROTOCOL) { 1139 if (msg_user(msg) == LINK_PROTOCOL) {
1107 tipc_link_proto_rcv(l_ptr, skb); 1140 tipc_link_proto_rcv(l_ptr, skb);
1108 link_retrieve_defq(l_ptr, &head); 1141 link_retrieve_defq(l_ptr, &head);
@@ -1113,7 +1146,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1113 /* Traffic message. Conditionally activate link */ 1146 /* Traffic message. Conditionally activate link */
1114 link_state_event(l_ptr, TRAFFIC_EVT); 1147 link_state_event(l_ptr, TRAFFIC_EVT);
1115 1148
1116 if (link_working_working(l_ptr)) { 1149 if (link_working(l_ptr)) {
1117 /* Re-insert buffer in front of queue */ 1150 /* Re-insert buffer in front of queue */
1118 __skb_queue_head(&head, skb); 1151 __skb_queue_head(&head, skb);
1119 skb = NULL; 1152 skb = NULL;
@@ -1122,7 +1155,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1122 goto unlock; 1155 goto unlock;
1123 } 1156 }
1124 1157
1125 /* Link is now in state WORKING_WORKING */ 1158 /* Link is now in state TIPC_LINK_WORKING */
1126 if (unlikely(seq_no != l_ptr->rcv_nxt)) { 1159 if (unlikely(seq_no != l_ptr->rcv_nxt)) {
1127 link_handle_out_of_seq_msg(l_ptr, skb); 1160 link_handle_out_of_seq_msg(l_ptr, skb);
1128 link_retrieve_defq(l_ptr, &head); 1161 link_retrieve_defq(l_ptr, &head);
@@ -1365,16 +1398,15 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1365 switch (msg_type(msg)) { 1398 switch (msg_type(msg)) {
1366 1399
1367 case RESET_MSG: 1400 case RESET_MSG:
1368 if (!link_working_unknown(l_ptr) && 1401 if (!link_probing(l_ptr) &&
1369 (l_ptr->peer_session != WILDCARD_SESSION)) { 1402 (l_ptr->peer_session != WILDCARD_SESSION)) {
1370 if (less_eq(msg_session(msg), l_ptr->peer_session)) 1403 if (less_eq(msg_session(msg), l_ptr->peer_session))
1371 break; /* duplicate or old reset: ignore */ 1404 break; /* duplicate or old reset: ignore */
1372 } 1405 }
1373 1406
1374 if (!msg_redundant_link(msg) && (link_working_working(l_ptr) || 1407 if (!msg_redundant_link(msg) && (link_working(l_ptr) ||
1375 link_working_unknown(l_ptr))) { 1408 link_probing(l_ptr))) {
1376 /* 1409 /* peer has lost contact -- don't allow peer's links
1377 * peer has lost contact -- don't allow peer's links
1378 * to reactivate before we recognize loss & clean up 1410 * to reactivate before we recognize loss & clean up
1379 */ 1411 */
1380 l_ptr->owner->action_flags |= TIPC_WAIT_OWN_LINKS_DOWN; 1412 l_ptr->owner->action_flags |= TIPC_WAIT_OWN_LINKS_DOWN;
@@ -1432,7 +1464,7 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr,
1432 1464
1433 link_state_event(l_ptr, TRAFFIC_EVT); 1465 link_state_event(l_ptr, TRAFFIC_EVT);
1434 l_ptr->stats.recv_states++; 1466 l_ptr->stats.recv_states++;
1435 if (link_reset_unknown(l_ptr)) 1467 if (link_resetting(l_ptr))
1436 break; 1468 break;
1437 1469
1438 if (less_eq(l_ptr->rcv_nxt, msg_next_sent(msg))) 1470 if (less_eq(l_ptr->rcv_nxt, msg_next_sent(msg)))
@@ -1822,14 +1854,14 @@ static void link_print(struct tipc_link *l_ptr, const char *str)
1822 pr_info("%s Link %x<%s>:", str, l_ptr->addr, b_ptr->name); 1854 pr_info("%s Link %x<%s>:", str, l_ptr->addr, b_ptr->name);
1823 rcu_read_unlock(); 1855 rcu_read_unlock();
1824 1856
1825 if (link_working_unknown(l_ptr)) 1857 if (link_probing(l_ptr))
1826 pr_cont(":WU\n"); 1858 pr_cont(":P\n");
1827 else if (link_reset_reset(l_ptr)) 1859 else if (link_establishing(l_ptr))
1828 pr_cont(":RR\n"); 1860 pr_cont(":E\n");
1829 else if (link_reset_unknown(l_ptr)) 1861 else if (link_resetting(l_ptr))
1830 pr_cont(":RU\n"); 1862 pr_cont(":R\n");
1831 else if (link_working_working(l_ptr)) 1863 else if (link_working(l_ptr))
1832 pr_cont(":WW\n"); 1864 pr_cont(":W\n");
1833 else 1865 else
1834 pr_cont("\n"); 1866 pr_cont("\n");
1835} 1867}
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 0509c6de03cd..ef68424f492d 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -58,6 +58,13 @@ enum {
58 TIPC_LINK_TUNNEL 58 TIPC_LINK_TUNNEL
59}; 59};
60 60
61/* Events occurring at packet reception or at timeout
62 */
63enum {
64 TIPC_LINK_UP_EVT = 1,
65 TIPC_LINK_DOWN_EVT = (1 << 1)
66};
67
61/* Starting value for maximum packet size negotiation on unicast links 68/* Starting value for maximum packet size negotiation on unicast links
62 * (unless bearer MTU is less) 69 * (unless bearer MTU is less)
63 */ 70 */