aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c40
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/node.c31
3 files changed, 49 insertions, 23 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index e7c608631276..8c794c1dd531 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -125,6 +125,11 @@ bool tipc_link_is_reset(struct tipc_link *l)
125 return l->state & (LINK_RESET | LINK_FAILINGOVER | LINK_ESTABLISHING); 125 return l->state & (LINK_RESET | LINK_FAILINGOVER | LINK_ESTABLISHING);
126} 126}
127 127
128bool tipc_link_is_establishing(struct tipc_link *l)
129{
130 return l->state == LINK_ESTABLISHING;
131}
132
128bool tipc_link_is_synching(struct tipc_link *l) 133bool tipc_link_is_synching(struct tipc_link *l)
129{ 134{
130 return l->state == LINK_SYNCHING; 135 return l->state == LINK_SYNCHING;
@@ -321,14 +326,15 @@ int tipc_link_fsm_evt(struct tipc_link *l, int evt)
321 switch (evt) { 326 switch (evt) {
322 case LINK_ESTABLISH_EVT: 327 case LINK_ESTABLISH_EVT:
323 l->state = LINK_ESTABLISHED; 328 l->state = LINK_ESTABLISHED;
324 rc |= TIPC_LINK_UP_EVT;
325 break; 329 break;
326 case LINK_FAILOVER_BEGIN_EVT: 330 case LINK_FAILOVER_BEGIN_EVT:
327 l->state = LINK_FAILINGOVER; 331 l->state = LINK_FAILINGOVER;
328 break; 332 break;
329 case LINK_PEER_RESET_EVT:
330 case LINK_RESET_EVT: 333 case LINK_RESET_EVT:
334 l->state = LINK_RESET;
335 break;
331 case LINK_FAILURE_EVT: 336 case LINK_FAILURE_EVT:
337 case LINK_PEER_RESET_EVT:
332 case LINK_SYNCH_BEGIN_EVT: 338 case LINK_SYNCH_BEGIN_EVT:
333 case LINK_FAILOVER_END_EVT: 339 case LINK_FAILOVER_END_EVT:
334 break; 340 break;
@@ -1091,9 +1097,9 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
1091 return tipc_link_proto_rcv(l, skb, xmitq); 1097 return tipc_link_proto_rcv(l, skb, xmitq);
1092 1098
1093 if (unlikely(!link_is_up(l))) { 1099 if (unlikely(!link_is_up(l))) {
1094 rc = tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); 1100 if (l->state == LINK_ESTABLISHING)
1095 if (!link_is_up(l)) 1101 rc = TIPC_LINK_UP_EVT;
1096 goto drop; 1102 goto drop;
1097 } 1103 }
1098 1104
1099 /* Don't send probe at next timeout expiration */ 1105 /* Don't send probe at next timeout expiration */
@@ -1338,6 +1344,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1338 u16 peers_tol = msg_link_tolerance(hdr); 1344 u16 peers_tol = msg_link_tolerance(hdr);
1339 u16 peers_prio = msg_linkprio(hdr); 1345 u16 peers_prio = msg_linkprio(hdr);
1340 u16 rcv_nxt = l->rcv_nxt; 1346 u16 rcv_nxt = l->rcv_nxt;
1347 int mtyp = msg_type(hdr);
1341 char *if_name; 1348 char *if_name;
1342 int rc = 0; 1349 int rc = 0;
1343 1350
@@ -1347,7 +1354,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1347 if (link_own_addr(l) > msg_prevnode(hdr)) 1354 if (link_own_addr(l) > msg_prevnode(hdr))
1348 l->net_plane = msg_net_plane(hdr); 1355 l->net_plane = msg_net_plane(hdr);
1349 1356
1350 switch (msg_type(hdr)) { 1357 switch (mtyp) {
1351 case RESET_MSG: 1358 case RESET_MSG:
1352 1359
1353 /* Ignore duplicate RESET with old session number */ 1360 /* Ignore duplicate RESET with old session number */
@@ -1374,12 +1381,14 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1374 if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) 1381 if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI))
1375 l->priority = peers_prio; 1382 l->priority = peers_prio;
1376 1383
1377 if (msg_type(hdr) == RESET_MSG) { 1384 /* ACTIVATE_MSG serves as PEER_RESET if link is already down */
1378 rc |= tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); 1385 if ((mtyp == RESET_MSG) || !link_is_up(l))
1379 } else if (!link_is_up(l)) { 1386 rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT);
1380 tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); 1387
1381 rc |= tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); 1388 /* ACTIVATE_MSG takes up link if it was already locally reset */
1382 } 1389 if ((mtyp == ACTIVATE_MSG) && (l->state == LINK_ESTABLISHING))
1390 rc = TIPC_LINK_UP_EVT;
1391
1383 l->peer_session = msg_session(hdr); 1392 l->peer_session = msg_session(hdr);
1384 l->peer_bearer_id = msg_bearer_id(hdr); 1393 l->peer_bearer_id = msg_bearer_id(hdr);
1385 if (l->mtu > msg_max_pkt(hdr)) 1394 if (l->mtu > msg_max_pkt(hdr))
@@ -1396,9 +1405,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1396 l->stats.recv_states++; 1405 l->stats.recv_states++;
1397 if (msg_probe(hdr)) 1406 if (msg_probe(hdr))
1398 l->stats.recv_probes++; 1407 l->stats.recv_probes++;
1399 rc = tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); 1408
1400 if (!link_is_up(l)) 1409 if (!link_is_up(l)) {
1410 if (l->state == LINK_ESTABLISHING)
1411 rc = TIPC_LINK_UP_EVT;
1401 break; 1412 break;
1413 }
1402 1414
1403 /* Send NACK if peer has sent pkts we haven't received yet */ 1415 /* Send NACK if peer has sent pkts we haven't received yet */
1404 if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l)) 1416 if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l))
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 7a1ad4294b7a..d42dfc0e7bf5 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -217,6 +217,7 @@ int tipc_link_fsm_evt(struct tipc_link *l, int evt);
217void tipc_link_reset_fragments(struct tipc_link *l_ptr); 217void tipc_link_reset_fragments(struct tipc_link *l_ptr);
218bool tipc_link_is_up(struct tipc_link *l); 218bool tipc_link_is_up(struct tipc_link *l);
219bool tipc_link_is_reset(struct tipc_link *l); 219bool tipc_link_is_reset(struct tipc_link *l);
220bool tipc_link_is_establishing(struct tipc_link *l);
220bool tipc_link_is_synching(struct tipc_link *l); 221bool tipc_link_is_synching(struct tipc_link *l);
221bool tipc_link_is_failingover(struct tipc_link *l); 222bool tipc_link_is_failingover(struct tipc_link *l);
222bool tipc_link_is_blocked(struct tipc_link *l); 223bool tipc_link_is_blocked(struct tipc_link *l);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 703875fd6cde..656b5791f1a5 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -317,7 +317,11 @@ static void __tipc_node_link_up(struct tipc_node *n, int bearer_id,
317 struct tipc_link *ol = node_active_link(n, 0); 317 struct tipc_link *ol = node_active_link(n, 0);
318 struct tipc_link *nl = n->links[bearer_id].link; 318 struct tipc_link *nl = n->links[bearer_id].link;
319 319
320 if (!nl || !tipc_link_is_up(nl)) 320 if (!nl)
321 return;
322
323 tipc_link_fsm_evt(nl, LINK_ESTABLISH_EVT);
324 if (!tipc_link_is_up(nl))
321 return; 325 return;
322 326
323 n->working_links++; 327 n->working_links++;
@@ -437,17 +441,26 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
437static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) 441static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
438{ 442{
439 struct tipc_link_entry *le = &n->links[bearer_id]; 443 struct tipc_link_entry *le = &n->links[bearer_id];
444 struct tipc_link *l = le->link;
440 struct tipc_media_addr *maddr; 445 struct tipc_media_addr *maddr;
441 struct sk_buff_head xmitq; 446 struct sk_buff_head xmitq;
442 447
448 if (!l)
449 return;
450
443 __skb_queue_head_init(&xmitq); 451 __skb_queue_head_init(&xmitq);
444 452
445 tipc_node_lock(n); 453 tipc_node_lock(n);
446 __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); 454 if (!tipc_link_is_establishing(l)) {
447 if (delete && le->link) { 455 __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr);
448 kfree(le->link); 456 if (delete) {
449 le->link = NULL; 457 kfree(l);
450 n->link_cnt--; 458 le->link = NULL;
459 n->link_cnt--;
460 }
461 } else {
462 /* Defuse pending tipc_node_link_up() */
463 tipc_link_fsm_evt(l, LINK_RESET_EVT);
451 } 464 }
452 tipc_node_unlock(n); 465 tipc_node_unlock(n);
453 466
@@ -579,7 +592,7 @@ void tipc_node_check_dest(struct net *net, u32 onode,
579 memcpy(&le->maddr, maddr, sizeof(*maddr)); 592 memcpy(&le->maddr, maddr, sizeof(*maddr));
580exit: 593exit:
581 tipc_node_unlock(n); 594 tipc_node_unlock(n);
582 if (reset) 595 if (reset && !tipc_link_is_reset(l))
583 tipc_node_link_down(n, b->identity, false); 596 tipc_node_link_down(n, b->identity, false);
584 tipc_node_put(n); 597 tipc_node_put(n);
585} 598}
@@ -686,10 +699,10 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt)
686 break; 699 break;
687 case SELF_ESTABL_CONTACT_EVT: 700 case SELF_ESTABL_CONTACT_EVT:
688 case PEER_LOST_CONTACT_EVT: 701 case PEER_LOST_CONTACT_EVT:
689 break;
690 case NODE_SYNCH_END_EVT: 702 case NODE_SYNCH_END_EVT:
691 case NODE_SYNCH_BEGIN_EVT:
692 case NODE_FAILOVER_BEGIN_EVT: 703 case NODE_FAILOVER_BEGIN_EVT:
704 break;
705 case NODE_SYNCH_BEGIN_EVT:
693 case NODE_FAILOVER_END_EVT: 706 case NODE_FAILOVER_END_EVT:
694 default: 707 default:
695 goto illegal_evt; 708 goto illegal_evt;