diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/link.c | 40 | ||||
-rw-r--r-- | net/tipc/link.h | 1 | ||||
-rw-r--r-- | net/tipc/node.c | 31 |
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 | ||
128 | bool tipc_link_is_establishing(struct tipc_link *l) | ||
129 | { | ||
130 | return l->state == LINK_ESTABLISHING; | ||
131 | } | ||
132 | |||
128 | bool tipc_link_is_synching(struct tipc_link *l) | 133 | bool 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); | |||
217 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); | 217 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); |
218 | bool tipc_link_is_up(struct tipc_link *l); | 218 | bool tipc_link_is_up(struct tipc_link *l); |
219 | bool tipc_link_is_reset(struct tipc_link *l); | 219 | bool tipc_link_is_reset(struct tipc_link *l); |
220 | bool tipc_link_is_establishing(struct tipc_link *l); | ||
220 | bool tipc_link_is_synching(struct tipc_link *l); | 221 | bool tipc_link_is_synching(struct tipc_link *l); |
221 | bool tipc_link_is_failingover(struct tipc_link *l); | 222 | bool tipc_link_is_failingover(struct tipc_link *l); |
222 | bool tipc_link_is_blocked(struct tipc_link *l); | 223 | bool 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, | |||
437 | static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete) | 441 | static 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)); |
580 | exit: | 593 | exit: |
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; |