diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-07-30 18:24:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-30 20:25:14 -0400 |
commit | 662921cd0a53db4504838dfbb7d996f9e6e94001 (patch) | |
tree | 22093f4240391972cd6bcf879cbdfe963a73bdb1 /net/tipc | |
parent | 5045f7b9009f1455268b98cecbcc271663934c85 (diff) |
tipc: merge link->exec_mode and link->state into one FSM
Until now, we have been handling link failover and synchronization
by using an additional link state variable, "exec_mode". This variable
is not independent of the link FSM state, something causing a risk of
inconsistencies, apart from the fact that it clutters the code.
The conditions are now in place to define a new link FSM that covers
all existing use cases, including failover and synchronization, and
eliminate the "exec_mode" field altogether. The FSM must also support
non-atomic resetting of links, which will be introduced later.
The new link FSM is shown below, with 7 states and 8 events.
Only events leading to state change are shown as edges.
+------------------------------------+
|RESET_EVT |
| |
| +--------------+
| +-----------------| SYNCHING |-----------------+
| |FAILURE_EVT +--------------+ PEER_RESET_EVT|
| | A | |
| | | | |
| | | | |
| | |SYNCH_ |SYNCH_ |
| | |BEGIN_EVT |END_EVT |
| | | | |
| V | V V
| +-------------+ +--------------+ +------------+
| | RESETTING |<---------| ESTABLISHED |--------->| PEER_RESET |
| +-------------+ FAILURE_ +--------------+ PEER_ +------------+
| | EVT | A RESET_EVT |
| | | | |
| | | | |
| | +--------------+ | |
| RESET_EVT| |RESET_EVT |ESTABLISH_EVT |
| | | | |
| | | | |
| V V | |
| +-------------+ +--------------+ RESET_EVT|
+--->| RESET |--------->| ESTABLISHING |<----------------+
+-------------+ PEER_ +--------------+
| A RESET_EVT |
| | |
| | |
|FAILOVER_ |FAILOVER_ |FAILOVER_
|BEGIN_EVT |END_EVT |BEGIN_EVT
| | |
V | |
+-------------+ |
| FAILINGOVER |<----------------+
+-------------+
These changes are fully backwards compatible.
Tested-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/link.c | 350 | ||||
-rw-r--r-- | net/tipc/link.h | 25 | ||||
-rw-r--r-- | net/tipc/node.c | 31 |
3 files changed, 226 insertions, 180 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 9a3ccf910c49..9840b03348e1 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -50,7 +50,6 @@ | |||
50 | */ | 50 | */ |
51 | static const char *link_co_err = "Link tunneling error, "; | 51 | static const char *link_co_err = "Link tunneling error, "; |
52 | static const char *link_rst_msg = "Resetting link "; | 52 | static const char *link_rst_msg = "Resetting link "; |
53 | static const char *link_unk_evt = "Unknown link event "; | ||
54 | 53 | ||
55 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | 54 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { |
56 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | 55 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, |
@@ -85,46 +84,23 @@ static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | |||
85 | */ | 84 | */ |
86 | #define WILDCARD_SESSION 0x10000 | 85 | #define WILDCARD_SESSION 0x10000 |
87 | 86 | ||
88 | /* State value stored in 'failover_pkts' | 87 | /* Link FSM states: |
89 | */ | 88 | */ |
90 | #define FIRST_FAILOVER 0xffffu | ||
91 | |||
92 | /* Link FSM states and events: | ||
93 | */ | ||
94 | enum { | ||
95 | TIPC_LINK_WORKING, | ||
96 | TIPC_LINK_PROBING, | ||
97 | TIPC_LINK_RESETTING, | ||
98 | TIPC_LINK_ESTABLISHING | ||
99 | }; | ||
100 | |||
101 | enum { | 89 | enum { |
102 | PEER_RESET_EVT = RESET_MSG, | 90 | LINK_ESTABLISHED = 0xe, |
103 | ACTIVATE_EVT = ACTIVATE_MSG, | 91 | LINK_ESTABLISHING = 0xe << 4, |
104 | TRAFFIC_EVT, /* Any other valid msg from peer */ | 92 | LINK_RESET = 0x1 << 8, |
105 | SILENCE_EVT /* Peer was silent during last timer interval*/ | 93 | LINK_RESETTING = 0x2 << 12, |
94 | LINK_PEER_RESET = 0xd << 16, | ||
95 | LINK_FAILINGOVER = 0xf << 20, | ||
96 | LINK_SYNCHING = 0xc << 24 | ||
106 | }; | 97 | }; |
107 | 98 | ||
108 | /* Link FSM state checking routines | 99 | /* Link FSM state checking routines |
109 | */ | 100 | */ |
110 | static int link_working(struct tipc_link *l) | 101 | static int link_is_up(struct tipc_link *l) |
111 | { | ||
112 | return l->state == TIPC_LINK_WORKING; | ||
113 | } | ||
114 | |||
115 | static int link_probing(struct tipc_link *l) | ||
116 | { | ||
117 | return l->state == TIPC_LINK_PROBING; | ||
118 | } | ||
119 | |||
120 | static int link_resetting(struct tipc_link *l) | ||
121 | { | 102 | { |
122 | return l->state == TIPC_LINK_RESETTING; | 103 | return l->state & (LINK_ESTABLISHED | LINK_SYNCHING); |
123 | } | ||
124 | |||
125 | static int link_establishing(struct tipc_link *l) | ||
126 | { | ||
127 | return l->state == TIPC_LINK_ESTABLISHING; | ||
128 | } | 104 | } |
129 | 105 | ||
130 | static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | 106 | static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, |
@@ -141,11 +117,29 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb); | |||
141 | /* | 117 | /* |
142 | * Simple non-static link routines (i.e. referenced outside this file) | 118 | * Simple non-static link routines (i.e. referenced outside this file) |
143 | */ | 119 | */ |
144 | int tipc_link_is_up(struct tipc_link *l_ptr) | 120 | bool tipc_link_is_up(struct tipc_link *l) |
145 | { | 121 | { |
146 | if (!l_ptr) | 122 | return link_is_up(l); |
147 | return 0; | 123 | } |
148 | return link_working(l_ptr) || link_probing(l_ptr); | 124 | |
125 | bool tipc_link_is_reset(struct tipc_link *l) | ||
126 | { | ||
127 | return l->state & (LINK_RESET | LINK_FAILINGOVER | LINK_ESTABLISHING); | ||
128 | } | ||
129 | |||
130 | bool tipc_link_is_synching(struct tipc_link *l) | ||
131 | { | ||
132 | return l->state == LINK_SYNCHING; | ||
133 | } | ||
134 | |||
135 | bool tipc_link_is_failingover(struct tipc_link *l) | ||
136 | { | ||
137 | return l->state == LINK_FAILINGOVER; | ||
138 | } | ||
139 | |||
140 | bool tipc_link_is_blocked(struct tipc_link *l) | ||
141 | { | ||
142 | return l->state & (LINK_RESETTING | LINK_PEER_RESET | LINK_FAILINGOVER); | ||
149 | } | 143 | } |
150 | 144 | ||
151 | int tipc_link_is_active(struct tipc_link *l) | 145 | int tipc_link_is_active(struct tipc_link *l) |
@@ -210,7 +204,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
210 | l_ptr->tolerance = b_ptr->tolerance; | 204 | l_ptr->tolerance = b_ptr->tolerance; |
211 | l_ptr->snd_nxt = 1; | 205 | l_ptr->snd_nxt = 1; |
212 | l_ptr->rcv_nxt = 1; | 206 | l_ptr->rcv_nxt = 1; |
213 | l_ptr->state = TIPC_LINK_RESETTING; | 207 | l_ptr->state = LINK_RESET; |
214 | 208 | ||
215 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; | 209 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; |
216 | msg = l_ptr->pmsg; | 210 | msg = l_ptr->pmsg; |
@@ -265,120 +259,159 @@ void tipc_link_build_bcast_sync_msg(struct tipc_link *l, | |||
265 | * tipc_link_fsm_evt - link finite state machine | 259 | * tipc_link_fsm_evt - link finite state machine |
266 | * @l: pointer to link | 260 | * @l: pointer to link |
267 | * @evt: state machine event to be processed | 261 | * @evt: state machine event to be processed |
268 | * @xmitq: queue to prepend created protocol message, if any | ||
269 | */ | 262 | */ |
270 | static int tipc_link_fsm_evt(struct tipc_link *l, int evt, | 263 | int tipc_link_fsm_evt(struct tipc_link *l, int evt) |
271 | struct sk_buff_head *xmitq) | ||
272 | { | 264 | { |
273 | int rc = 0; | 265 | int rc = 0; |
274 | struct tipc_link *pl; | ||
275 | enum { | ||
276 | LINK_RESET = 1, | ||
277 | LINK_ACTIVATE = (1 << 1), | ||
278 | SND_PROBE = (1 << 2), | ||
279 | SND_STATE = (1 << 3), | ||
280 | SND_RESET = (1 << 4), | ||
281 | SND_ACTIVATE = (1 << 5), | ||
282 | SND_BCAST_SYNC = (1 << 6) | ||
283 | } actions = 0; | ||
284 | |||
285 | if (l->exec_mode == TIPC_LINK_BLOCKED) | ||
286 | return rc; | ||
287 | 266 | ||
288 | switch (l->state) { | 267 | switch (l->state) { |
289 | case TIPC_LINK_WORKING: | 268 | case LINK_RESETTING: |
290 | switch (evt) { | 269 | switch (evt) { |
291 | case TRAFFIC_EVT: | 270 | case LINK_PEER_RESET_EVT: |
292 | case ACTIVATE_EVT: | 271 | l->state = LINK_PEER_RESET; |
293 | break; | 272 | break; |
294 | case SILENCE_EVT: | 273 | case LINK_RESET_EVT: |
295 | l->state = TIPC_LINK_PROBING; | 274 | l->state = LINK_RESET; |
296 | actions |= SND_PROBE; | 275 | break; |
276 | case LINK_FAILURE_EVT: | ||
277 | case LINK_FAILOVER_BEGIN_EVT: | ||
278 | case LINK_ESTABLISH_EVT: | ||
279 | case LINK_FAILOVER_END_EVT: | ||
280 | case LINK_SYNCH_BEGIN_EVT: | ||
281 | case LINK_SYNCH_END_EVT: | ||
282 | default: | ||
283 | goto illegal_evt; | ||
284 | } | ||
285 | break; | ||
286 | case LINK_RESET: | ||
287 | switch (evt) { | ||
288 | case LINK_PEER_RESET_EVT: | ||
289 | l->state = LINK_ESTABLISHING; | ||
297 | break; | 290 | break; |
298 | case PEER_RESET_EVT: | 291 | case LINK_FAILOVER_BEGIN_EVT: |
299 | actions |= LINK_RESET | SND_ACTIVATE; | 292 | l->state = LINK_FAILINGOVER; |
293 | case LINK_FAILURE_EVT: | ||
294 | case LINK_RESET_EVT: | ||
295 | case LINK_ESTABLISH_EVT: | ||
296 | case LINK_FAILOVER_END_EVT: | ||
300 | break; | 297 | break; |
298 | case LINK_SYNCH_BEGIN_EVT: | ||
299 | case LINK_SYNCH_END_EVT: | ||
301 | default: | 300 | default: |
302 | pr_debug("%s%u WORKING\n", link_unk_evt, evt); | 301 | goto illegal_evt; |
303 | } | 302 | } |
304 | break; | 303 | break; |
305 | case TIPC_LINK_PROBING: | 304 | case LINK_PEER_RESET: |
306 | switch (evt) { | 305 | switch (evt) { |
307 | case TRAFFIC_EVT: | 306 | case LINK_RESET_EVT: |
308 | case ACTIVATE_EVT: | 307 | l->state = LINK_ESTABLISHING; |
309 | l->state = TIPC_LINK_WORKING; | ||
310 | break; | 308 | break; |
311 | case PEER_RESET_EVT: | 309 | case LINK_PEER_RESET_EVT: |
312 | actions |= LINK_RESET | SND_ACTIVATE; | 310 | case LINK_ESTABLISH_EVT: |
311 | case LINK_FAILURE_EVT: | ||
313 | break; | 312 | break; |
314 | case SILENCE_EVT: | 313 | case LINK_SYNCH_BEGIN_EVT: |
315 | if (l->silent_intv_cnt <= l->abort_limit) { | 314 | case LINK_SYNCH_END_EVT: |
316 | actions |= SND_PROBE; | 315 | case LINK_FAILOVER_BEGIN_EVT: |
317 | break; | 316 | case LINK_FAILOVER_END_EVT: |
318 | } | 317 | default: |
319 | actions |= LINK_RESET | SND_RESET; | 318 | goto illegal_evt; |
319 | } | ||
320 | break; | ||
321 | case LINK_FAILINGOVER: | ||
322 | switch (evt) { | ||
323 | case LINK_FAILOVER_END_EVT: | ||
324 | l->state = LINK_RESET; | ||
320 | break; | 325 | break; |
326 | case LINK_PEER_RESET_EVT: | ||
327 | case LINK_RESET_EVT: | ||
328 | case LINK_ESTABLISH_EVT: | ||
329 | case LINK_FAILURE_EVT: | ||
330 | break; | ||
331 | case LINK_FAILOVER_BEGIN_EVT: | ||
332 | case LINK_SYNCH_BEGIN_EVT: | ||
333 | case LINK_SYNCH_END_EVT: | ||
321 | default: | 334 | default: |
322 | pr_err("%s%u PROBING\n", link_unk_evt, evt); | 335 | goto illegal_evt; |
323 | } | 336 | } |
324 | break; | 337 | break; |
325 | case TIPC_LINK_RESETTING: | 338 | case LINK_ESTABLISHING: |
326 | switch (evt) { | 339 | switch (evt) { |
327 | case TRAFFIC_EVT: | 340 | case LINK_ESTABLISH_EVT: |
341 | l->state = LINK_ESTABLISHED; | ||
342 | rc |= TIPC_LINK_UP_EVT; | ||
328 | break; | 343 | break; |
329 | case ACTIVATE_EVT: | 344 | case LINK_FAILOVER_BEGIN_EVT: |
330 | pl = node_active_link(l->owner, 0); | 345 | l->state = LINK_FAILINGOVER; |
331 | if (pl && link_probing(pl)) | 346 | break; |
332 | break; | 347 | case LINK_PEER_RESET_EVT: |
333 | l->state = TIPC_LINK_WORKING; | 348 | case LINK_RESET_EVT: |
334 | actions |= LINK_ACTIVATE; | 349 | case LINK_FAILURE_EVT: |
335 | if (!l->owner->working_links) | 350 | case LINK_SYNCH_BEGIN_EVT: |
336 | actions |= SND_BCAST_SYNC; | 351 | case LINK_FAILOVER_END_EVT: |
352 | break; | ||
353 | case LINK_SYNCH_END_EVT: | ||
354 | default: | ||
355 | goto illegal_evt; | ||
356 | } | ||
357 | break; | ||
358 | case LINK_ESTABLISHED: | ||
359 | switch (evt) { | ||
360 | case LINK_PEER_RESET_EVT: | ||
361 | l->state = LINK_PEER_RESET; | ||
362 | rc |= TIPC_LINK_DOWN_EVT; | ||
363 | break; | ||
364 | case LINK_FAILURE_EVT: | ||
365 | l->state = LINK_RESETTING; | ||
366 | rc |= TIPC_LINK_DOWN_EVT; | ||
337 | break; | 367 | break; |
338 | case PEER_RESET_EVT: | 368 | case LINK_RESET_EVT: |
339 | l->state = TIPC_LINK_ESTABLISHING; | 369 | l->state = LINK_RESET; |
340 | actions |= SND_ACTIVATE; | ||
341 | break; | 370 | break; |
342 | case SILENCE_EVT: | 371 | case LINK_ESTABLISH_EVT: |
343 | actions |= SND_RESET; | ||
344 | break; | 372 | break; |
373 | case LINK_SYNCH_BEGIN_EVT: | ||
374 | l->state = LINK_SYNCHING; | ||
375 | break; | ||
376 | case LINK_SYNCH_END_EVT: | ||
377 | case LINK_FAILOVER_BEGIN_EVT: | ||
378 | case LINK_FAILOVER_END_EVT: | ||
345 | default: | 379 | default: |
346 | pr_err("%s%u in RESETTING\n", link_unk_evt, evt); | 380 | goto illegal_evt; |
347 | } | 381 | } |
348 | break; | 382 | break; |
349 | case TIPC_LINK_ESTABLISHING: | 383 | case LINK_SYNCHING: |
350 | switch (evt) { | 384 | switch (evt) { |
351 | case TRAFFIC_EVT: | 385 | case LINK_PEER_RESET_EVT: |
352 | case ACTIVATE_EVT: | 386 | l->state = LINK_PEER_RESET; |
353 | pl = node_active_link(l->owner, 0); | 387 | rc |= TIPC_LINK_DOWN_EVT; |
354 | if (pl && link_probing(pl)) | 388 | break; |
355 | break; | 389 | case LINK_FAILURE_EVT: |
356 | l->state = TIPC_LINK_WORKING; | 390 | l->state = LINK_RESETTING; |
357 | actions |= LINK_ACTIVATE; | 391 | rc |= TIPC_LINK_DOWN_EVT; |
358 | if (!l->owner->working_links) | ||
359 | actions |= SND_BCAST_SYNC; | ||
360 | break; | 392 | break; |
361 | case PEER_RESET_EVT: | 393 | case LINK_RESET_EVT: |
394 | l->state = LINK_RESET; | ||
362 | break; | 395 | break; |
363 | case SILENCE_EVT: | 396 | case LINK_ESTABLISH_EVT: |
364 | actions |= SND_ACTIVATE; | 397 | case LINK_SYNCH_BEGIN_EVT: |
365 | break; | 398 | break; |
399 | case LINK_SYNCH_END_EVT: | ||
400 | l->state = LINK_ESTABLISHED; | ||
401 | break; | ||
402 | case LINK_FAILOVER_BEGIN_EVT: | ||
403 | case LINK_FAILOVER_END_EVT: | ||
366 | default: | 404 | default: |
367 | pr_err("%s%u ESTABLISHING\n", link_unk_evt, evt); | 405 | goto illegal_evt; |
368 | } | 406 | } |
369 | break; | 407 | break; |
370 | default: | 408 | default: |
371 | pr_err("Unknown link state %u/%u\n", l->state, evt); | 409 | pr_err("Unknown FSM state %x in %s\n", l->state, l->name); |
372 | } | ||
373 | |||
374 | /* Perform actions as decided by FSM */ | ||
375 | if (actions & LINK_RESET) { | ||
376 | l->exec_mode = TIPC_LINK_BLOCKED; | ||
377 | rc = TIPC_LINK_DOWN_EVT; | ||
378 | } | 410 | } |
379 | if (actions & LINK_ACTIVATE) | 411 | return rc; |
380 | rc = TIPC_LINK_UP_EVT; | 412 | illegal_evt: |
381 | 413 | pr_err("Illegal FSM event %x in state %x on link %s\n", | |
414 | evt, l->state, l->name); | ||
382 | return rc; | 415 | return rc; |
383 | } | 416 | } |
384 | 417 | ||
@@ -432,12 +465,11 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) | |||
432 | bool xmit = false; | 465 | bool xmit = false; |
433 | bool prb = false; | 466 | bool prb = false; |
434 | 467 | ||
435 | if (l->exec_mode == TIPC_LINK_BLOCKED) | ||
436 | return rc; | ||
437 | |||
438 | link_profile_stats(l); | 468 | link_profile_stats(l); |
439 | 469 | ||
440 | if (l->state == TIPC_LINK_WORKING) { | 470 | switch (l->state) { |
471 | case LINK_ESTABLISHED: | ||
472 | case LINK_SYNCHING: | ||
441 | if (!l->silent_intv_cnt) { | 473 | if (!l->silent_intv_cnt) { |
442 | if (tipc_bclink_acks_missing(l->owner)) | 474 | if (tipc_bclink_acks_missing(l->owner)) |
443 | xmit = true; | 475 | xmit = true; |
@@ -445,17 +477,26 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) | |||
445 | xmit = true; | 477 | xmit = true; |
446 | prb = true; | 478 | prb = true; |
447 | } else { | 479 | } else { |
448 | l->exec_mode = TIPC_LINK_BLOCKED; | 480 | rc |= tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
449 | rc |= TIPC_LINK_DOWN_EVT; | ||
450 | } | 481 | } |
451 | l->silent_intv_cnt++; | 482 | l->silent_intv_cnt++; |
452 | } else if (l->state == TIPC_LINK_RESETTING) { | 483 | break; |
484 | case LINK_RESET: | ||
453 | xmit = true; | 485 | xmit = true; |
454 | mtyp = RESET_MSG; | 486 | mtyp = RESET_MSG; |
455 | } else if (l->state == TIPC_LINK_ESTABLISHING) { | 487 | break; |
488 | case LINK_ESTABLISHING: | ||
456 | xmit = true; | 489 | xmit = true; |
457 | mtyp = ACTIVATE_MSG; | 490 | mtyp = ACTIVATE_MSG; |
491 | break; | ||
492 | case LINK_RESETTING: | ||
493 | case LINK_PEER_RESET: | ||
494 | case LINK_FAILINGOVER: | ||
495 | break; | ||
496 | default: | ||
497 | break; | ||
458 | } | 498 | } |
499 | |||
459 | if (xmit) | 500 | if (xmit) |
460 | tipc_link_build_proto_msg(l, mtyp, prb, 0, 0, 0, xmitq); | 501 | tipc_link_build_proto_msg(l, mtyp, prb, 0, 0, 0, xmitq); |
461 | 502 | ||
@@ -559,7 +600,7 @@ void tipc_link_reset(struct tipc_link *l) | |||
559 | { | 600 | { |
560 | struct tipc_node *owner = l->owner; | 601 | struct tipc_node *owner = l->owner; |
561 | 602 | ||
562 | l->state = TIPC_LINK_RESETTING; | 603 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
563 | 604 | ||
564 | /* Link is down, accept any session */ | 605 | /* Link is down, accept any session */ |
565 | l->peer_session = WILDCARD_SESSION; | 606 | l->peer_session = WILDCARD_SESSION; |
@@ -902,8 +943,7 @@ static int tipc_link_retransm(struct tipc_link *l, int retransm, | |||
902 | l->stale_count = 1; | 943 | l->stale_count = 1; |
903 | } else if (++l->stale_count > 100) { | 944 | } else if (++l->stale_count > 100) { |
904 | link_retransmit_failure(l, skb); | 945 | link_retransmit_failure(l, skb); |
905 | l->exec_mode = TIPC_LINK_BLOCKED; | 946 | return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
906 | return TIPC_LINK_DOWN_EVT; | ||
907 | } | 947 | } |
908 | skb_queue_walk(&l->transmq, skb) { | 948 | skb_queue_walk(&l->transmq, skb) { |
909 | if (!retransm) | 949 | if (!retransm) |
@@ -1002,25 +1042,23 @@ static int tipc_link_input(struct tipc_link *l, struct sk_buff *skb) | |||
1002 | l->stats.recv_bundled += msg_msgcnt(hdr); | 1042 | l->stats.recv_bundled += msg_msgcnt(hdr); |
1003 | while (tipc_msg_extract(skb, &iskb, &pos)) | 1043 | while (tipc_msg_extract(skb, &iskb, &pos)) |
1004 | tipc_data_input(l, iskb); | 1044 | tipc_data_input(l, iskb); |
1005 | return rc; | 1045 | return 0; |
1006 | } else if (usr == MSG_FRAGMENTER) { | 1046 | } else if (usr == MSG_FRAGMENTER) { |
1007 | l->stats.recv_fragments++; | 1047 | l->stats.recv_fragments++; |
1008 | if (tipc_buf_append(reasm_skb, &skb)) { | 1048 | if (tipc_buf_append(reasm_skb, &skb)) { |
1009 | l->stats.recv_fragmented++; | 1049 | l->stats.recv_fragmented++; |
1010 | tipc_data_input(l, skb); | 1050 | tipc_data_input(l, skb); |
1011 | } else if (!*reasm_skb) { | 1051 | } else if (!*reasm_skb) { |
1012 | l->exec_mode = TIPC_LINK_BLOCKED; | 1052 | return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
1013 | l->state = TIPC_LINK_RESETTING; | ||
1014 | rc = TIPC_LINK_DOWN_EVT; | ||
1015 | } | 1053 | } |
1016 | return rc; | 1054 | return 0; |
1017 | } else if (usr == BCAST_PROTOCOL) { | 1055 | } else if (usr == BCAST_PROTOCOL) { |
1018 | tipc_link_sync_rcv(node, skb); | 1056 | tipc_link_sync_rcv(node, skb); |
1019 | return rc; | 1057 | return 0; |
1020 | } | 1058 | } |
1021 | drop: | 1059 | drop: |
1022 | kfree_skb(skb); | 1060 | kfree_skb(skb); |
1023 | return rc; | 1061 | return 0; |
1024 | } | 1062 | } |
1025 | 1063 | ||
1026 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked) | 1064 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 acked) |
@@ -1068,9 +1106,9 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1068 | continue; | 1106 | continue; |
1069 | } | 1107 | } |
1070 | 1108 | ||
1071 | if (unlikely(!link_working(l))) { | 1109 | if (unlikely(!link_is_up(l))) { |
1072 | rc = tipc_link_fsm_evt(l, TRAFFIC_EVT, xmitq); | 1110 | rc = tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); |
1073 | if (!link_working(l)) { | 1111 | if (!link_is_up(l)) { |
1074 | kfree_skb(__skb_dequeue(arrvq)); | 1112 | kfree_skb(__skb_dequeue(arrvq)); |
1075 | return rc; | 1113 | return rc; |
1076 | } | 1114 | } |
@@ -1192,7 +1230,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
1192 | int node_up = l->owner->bclink.recv_permitted; | 1230 | int node_up = l->owner->bclink.recv_permitted; |
1193 | 1231 | ||
1194 | /* Don't send protocol message during reset or link failover */ | 1232 | /* Don't send protocol message during reset or link failover */ |
1195 | if (l->exec_mode == TIPC_LINK_BLOCKED) | 1233 | if (tipc_link_is_blocked(l)) |
1196 | return; | 1234 | return; |
1197 | 1235 | ||
1198 | msg_set_type(hdr, mtyp); | 1236 | msg_set_type(hdr, mtyp); |
@@ -1302,7 +1340,6 @@ tnl: | |||
1302 | tnl->drop_point = l->rcv_nxt; | 1340 | tnl->drop_point = l->rcv_nxt; |
1303 | tnl->failover_reasm_skb = l->reasm_buf; | 1341 | tnl->failover_reasm_skb = l->reasm_buf; |
1304 | l->reasm_buf = NULL; | 1342 | l->reasm_buf = NULL; |
1305 | l->exec_mode = TIPC_LINK_BLOCKED; | ||
1306 | } | 1343 | } |
1307 | } | 1344 | } |
1308 | 1345 | ||
@@ -1323,7 +1360,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1323 | char *if_name; | 1360 | char *if_name; |
1324 | int rc = 0; | 1361 | int rc = 0; |
1325 | 1362 | ||
1326 | if (l->exec_mode == TIPC_LINK_BLOCKED) | 1363 | if (tipc_link_is_blocked(l)) |
1327 | goto exit; | 1364 | goto exit; |
1328 | 1365 | ||
1329 | if (link_own_addr(l) > msg_prevnode(hdr)) | 1366 | if (link_own_addr(l) > msg_prevnode(hdr)) |
@@ -1337,6 +1374,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1337 | (l->peer_session != WILDCARD_SESSION)) | 1374 | (l->peer_session != WILDCARD_SESSION)) |
1338 | break; | 1375 | break; |
1339 | /* fall thru' */ | 1376 | /* fall thru' */ |
1377 | |||
1340 | case ACTIVATE_MSG: | 1378 | case ACTIVATE_MSG: |
1341 | 1379 | ||
1342 | /* Complete own link name with peer's interface name */ | 1380 | /* Complete own link name with peer's interface name */ |
@@ -1355,13 +1393,20 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1355 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) | 1393 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) |
1356 | l->priority = peers_prio; | 1394 | l->priority = peers_prio; |
1357 | 1395 | ||
1396 | if (msg_type(hdr) == RESET_MSG) { | ||
1397 | rc |= tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); | ||
1398 | } else if (!link_is_up(l)) { | ||
1399 | tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); | ||
1400 | rc |= tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); | ||
1401 | } | ||
1358 | l->peer_session = msg_session(hdr); | 1402 | l->peer_session = msg_session(hdr); |
1359 | l->peer_bearer_id = msg_bearer_id(hdr); | 1403 | l->peer_bearer_id = msg_bearer_id(hdr); |
1360 | rc = tipc_link_fsm_evt(l, msg_type(hdr), xmitq); | ||
1361 | if (l->mtu > msg_max_pkt(hdr)) | 1404 | if (l->mtu > msg_max_pkt(hdr)) |
1362 | l->mtu = msg_max_pkt(hdr); | 1405 | l->mtu = msg_max_pkt(hdr); |
1363 | break; | 1406 | break; |
1407 | |||
1364 | case STATE_MSG: | 1408 | case STATE_MSG: |
1409 | |||
1365 | /* Update own tolerance if peer indicates a non-zero value */ | 1410 | /* Update own tolerance if peer indicates a non-zero value */ |
1366 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) | 1411 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) |
1367 | l->tolerance = peers_tol; | 1412 | l->tolerance = peers_tol; |
@@ -1370,11 +1415,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1370 | l->stats.recv_states++; | 1415 | l->stats.recv_states++; |
1371 | if (msg_probe(hdr)) | 1416 | if (msg_probe(hdr)) |
1372 | l->stats.recv_probes++; | 1417 | l->stats.recv_probes++; |
1373 | rc = tipc_link_fsm_evt(l, TRAFFIC_EVT, xmitq); | 1418 | rc = tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); |
1374 | if (!tipc_link_is_up(l)) | 1419 | if (!link_is_up(l)) |
1375 | break; | 1420 | break; |
1376 | 1421 | ||
1377 | /* Has peer sent packets we haven't received yet ? */ | 1422 | /* Send NACK if peer has sent pkts we haven't received yet */ |
1378 | if (more(peers_snd_nxt, l->rcv_nxt)) | 1423 | if (more(peers_snd_nxt, l->rcv_nxt)) |
1379 | rcvgap = peers_snd_nxt - l->rcv_nxt; | 1424 | rcvgap = peers_snd_nxt - l->rcv_nxt; |
1380 | if (rcvgap || (msg_probe(hdr))) | 1425 | if (rcvgap || (msg_probe(hdr))) |
@@ -1387,6 +1432,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1387 | rc = tipc_link_retransm(l, nacked_gap, xmitq); | 1432 | rc = tipc_link_retransm(l, nacked_gap, xmitq); |
1388 | l->stats.recv_nacks++; | 1433 | l->stats.recv_nacks++; |
1389 | } | 1434 | } |
1435 | |||
1390 | tipc_link_advance_backlog(l, xmitq); | 1436 | tipc_link_advance_backlog(l, xmitq); |
1391 | if (unlikely(!skb_queue_empty(&l->wakeupq))) | 1437 | if (unlikely(!skb_queue_empty(&l->wakeupq))) |
1392 | link_prepare_wakeup(l); | 1438 | link_prepare_wakeup(l); |
@@ -1463,19 +1509,7 @@ static void link_print(struct tipc_link *l, const char *str) | |||
1463 | u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt; | 1509 | u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt; |
1464 | u16 tail = l->snd_nxt - 1; | 1510 | u16 tail = l->snd_nxt - 1; |
1465 | 1511 | ||
1466 | pr_info("%s Link <%s>:", str, l->name); | 1512 | pr_info("%s Link <%s> state %x\n", str, l->name, l->state); |
1467 | |||
1468 | if (link_probing(l)) | ||
1469 | pr_cont(":P\n"); | ||
1470 | else if (link_establishing(l)) | ||
1471 | pr_cont(":E\n"); | ||
1472 | else if (link_resetting(l)) | ||
1473 | pr_cont(":R\n"); | ||
1474 | else if (link_working(l)) | ||
1475 | pr_cont(":W\n"); | ||
1476 | else | ||
1477 | pr_cont("\n"); | ||
1478 | |||
1479 | pr_info("XMTQ: %u [%u-%u], BKLGQ: %u, SNDNX: %u, RCVNX: %u\n", | 1513 | pr_info("XMTQ: %u [%u-%u], BKLGQ: %u, SNDNX: %u, RCVNX: %u\n", |
1480 | skb_queue_len(&l->transmq), head, tail, | 1514 | skb_queue_len(&l->transmq), head, tail, |
1481 | skb_queue_len(&l->backlogq), l->snd_nxt, l->rcv_nxt); | 1515 | skb_queue_len(&l->backlogq), l->snd_nxt, l->rcv_nxt); |
diff --git a/net/tipc/link.h b/net/tipc/link.h index b317c4df9079..39b8c4c5121e 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -49,13 +49,17 @@ | |||
49 | */ | 49 | */ |
50 | #define INVALID_LINK_SEQ 0x10000 | 50 | #define INVALID_LINK_SEQ 0x10000 |
51 | 51 | ||
52 | 52 | /* Link FSM events: | |
53 | /* Link endpoint receive states | ||
54 | */ | 53 | */ |
55 | enum { | 54 | enum { |
56 | TIPC_LINK_OPEN, | 55 | LINK_ESTABLISH_EVT = 0xec1ab1e, |
57 | TIPC_LINK_BLOCKED, | 56 | LINK_PEER_RESET_EVT = 0x9eed0e, |
58 | TIPC_LINK_TUNNEL | 57 | LINK_FAILURE_EVT = 0xfa110e, |
58 | LINK_RESET_EVT = 0x10ca1d0e, | ||
59 | LINK_FAILOVER_BEGIN_EVT = 0xfa110bee, | ||
60 | LINK_FAILOVER_END_EVT = 0xfa110ede, | ||
61 | LINK_SYNCH_BEGIN_EVT = 0xc1ccbee, | ||
62 | LINK_SYNCH_END_EVT = 0xc1ccede | ||
59 | }; | 63 | }; |
60 | 64 | ||
61 | /* Events returned from link at packet reception or at timeout | 65 | /* Events returned from link at packet reception or at timeout |
@@ -120,7 +124,6 @@ struct tipc_stats { | |||
120 | * @pmsg: convenience pointer to "proto_msg" field | 124 | * @pmsg: convenience pointer to "proto_msg" field |
121 | * @priority: current link priority | 125 | * @priority: current link priority |
122 | * @net_plane: current link network plane ('A' through 'H') | 126 | * @net_plane: current link network plane ('A' through 'H') |
123 | * @exec_mode: transmit/receive mode for link endpoint instance | ||
124 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) | 127 | * @backlog_limit: backlog queue congestion thresholds (indexed by importance) |
125 | * @exp_msg_count: # of tunnelled messages expected during link changeover | 128 | * @exp_msg_count: # of tunnelled messages expected during link changeover |
126 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset | 129 | * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset |
@@ -155,7 +158,7 @@ struct tipc_link { | |||
155 | u32 tolerance; | 158 | u32 tolerance; |
156 | unsigned long keepalive_intv; | 159 | unsigned long keepalive_intv; |
157 | u32 abort_limit; | 160 | u32 abort_limit; |
158 | int state; | 161 | u32 state; |
159 | u32 silent_intv_cnt; | 162 | u32 silent_intv_cnt; |
160 | struct { | 163 | struct { |
161 | unchar hdr[INT_H_SIZE]; | 164 | unchar hdr[INT_H_SIZE]; |
@@ -166,7 +169,6 @@ struct tipc_link { | |||
166 | char net_plane; | 169 | char net_plane; |
167 | 170 | ||
168 | /* Failover/synch */ | 171 | /* Failover/synch */ |
169 | u8 exec_mode; | ||
170 | u16 drop_point; | 172 | u16 drop_point; |
171 | struct sk_buff *failover_reasm_skb; | 173 | struct sk_buff *failover_reasm_skb; |
172 | 174 | ||
@@ -214,8 +216,13 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | |||
214 | int mtyp, struct sk_buff_head *xmitq); | 216 | int mtyp, struct sk_buff_head *xmitq); |
215 | void tipc_link_build_bcast_sync_msg(struct tipc_link *l, | 217 | void tipc_link_build_bcast_sync_msg(struct tipc_link *l, |
216 | struct sk_buff_head *xmitq); | 218 | struct sk_buff_head *xmitq); |
219 | int tipc_link_fsm_evt(struct tipc_link *l, int evt); | ||
217 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); | 220 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); |
218 | int tipc_link_is_up(struct tipc_link *l_ptr); | 221 | bool tipc_link_is_up(struct tipc_link *l); |
222 | bool tipc_link_is_reset(struct tipc_link *l); | ||
223 | bool tipc_link_is_synching(struct tipc_link *l); | ||
224 | bool tipc_link_is_failingover(struct tipc_link *l); | ||
225 | bool tipc_link_is_blocked(struct tipc_link *l); | ||
219 | int tipc_link_is_active(struct tipc_link *l_ptr); | 226 | int tipc_link_is_active(struct tipc_link *l_ptr); |
220 | void tipc_link_purge_queues(struct tipc_link *l_ptr); | 227 | void tipc_link_purge_queues(struct tipc_link *l_ptr); |
221 | void tipc_link_purge_backlog(struct tipc_link *l); | 228 | void tipc_link_purge_backlog(struct tipc_link *l); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e20acffb3d4..a3ceeda2a80a 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -334,7 +334,6 @@ static void tipc_node_link_up(struct tipc_node *n, int bearer_id, | |||
334 | if (!ol) { | 334 | if (!ol) { |
335 | *slot0 = bearer_id; | 335 | *slot0 = bearer_id; |
336 | *slot1 = bearer_id; | 336 | *slot1 = bearer_id; |
337 | nl->exec_mode = TIPC_LINK_OPEN; | ||
338 | tipc_link_build_bcast_sync_msg(nl, xmitq); | 337 | tipc_link_build_bcast_sync_msg(nl, xmitq); |
339 | node_established_contact(n); | 338 | node_established_contact(n); |
340 | return; | 339 | return; |
@@ -368,7 +367,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id) | |||
368 | struct sk_buff_head xmitq; | 367 | struct sk_buff_head xmitq; |
369 | 368 | ||
370 | l = n->links[bearer_id].link; | 369 | l = n->links[bearer_id].link; |
371 | if (!l || !tipc_link_is_up(l)) | 370 | if (!l || tipc_link_is_reset(l)) |
372 | return; | 371 | return; |
373 | 372 | ||
374 | __skb_queue_head_init(&xmitq); | 373 | __skb_queue_head_init(&xmitq); |
@@ -414,6 +413,7 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id) | |||
414 | n->sync_point = tnl->rcv_nxt + (U16_MAX / 2 - 1); | 413 | n->sync_point = tnl->rcv_nxt + (U16_MAX / 2 - 1); |
415 | tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, &xmitq); | 414 | tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, &xmitq); |
416 | tipc_link_reset(l); | 415 | tipc_link_reset(l); |
416 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); | ||
417 | tipc_bearer_xmit(n->net, tnl->bearer_id, &xmitq, maddr); | 417 | tipc_bearer_xmit(n->net, tnl->bearer_id, &xmitq, maddr); |
418 | } | 418 | } |
419 | 419 | ||
@@ -749,7 +749,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
749 | struct tipc_link *l_ptr = n_ptr->links[i].link; | 749 | struct tipc_link *l_ptr = n_ptr->links[i].link; |
750 | if (!l_ptr) | 750 | if (!l_ptr) |
751 | continue; | 751 | continue; |
752 | l_ptr->exec_mode = TIPC_LINK_OPEN; | 752 | tipc_link_fsm_evt(l_ptr, LINK_FAILOVER_END_EVT); |
753 | kfree_skb(l_ptr->failover_reasm_skb); | 753 | kfree_skb(l_ptr->failover_reasm_skb); |
754 | l_ptr->failover_reasm_skb = NULL; | 754 | l_ptr->failover_reasm_skb = NULL; |
755 | tipc_link_reset_fragments(l_ptr); | 755 | tipc_link_reset_fragments(l_ptr); |
@@ -989,7 +989,7 @@ int tipc_node_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode, | |||
989 | * Returns true if state is ok, otherwise consumes buffer and returns false | 989 | * Returns true if state is ok, otherwise consumes buffer and returns false |
990 | */ | 990 | */ |
991 | static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | 991 | static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, |
992 | int bearer_id) | 992 | int bearer_id, struct sk_buff_head *xmitq) |
993 | { | 993 | { |
994 | struct tipc_msg *hdr = buf_msg(skb); | 994 | struct tipc_msg *hdr = buf_msg(skb); |
995 | int usr = msg_user(hdr); | 995 | int usr = msg_user(hdr); |
@@ -1042,42 +1042,47 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, | |||
1042 | /* Initiate or update failover mode if applicable */ | 1042 | /* Initiate or update failover mode if applicable */ |
1043 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == FAILOVER_MSG)) { | 1043 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == FAILOVER_MSG)) { |
1044 | syncpt = oseqno + exp_pkts - 1; | 1044 | syncpt = oseqno + exp_pkts - 1; |
1045 | if (pl && tipc_link_is_up(pl)) { | 1045 | if (pl && tipc_link_is_up(pl)) |
1046 | tipc_node_link_down(n, pl->bearer_id); | 1046 | tipc_node_link_down(n, pl->bearer_id); |
1047 | pl->exec_mode = TIPC_LINK_BLOCKED; | 1047 | |
1048 | } | ||
1049 | /* If pkts arrive out of order, use lowest calculated syncpt */ | 1048 | /* If pkts arrive out of order, use lowest calculated syncpt */ |
1050 | if (less(syncpt, n->sync_point)) | 1049 | if (less(syncpt, n->sync_point)) |
1051 | n->sync_point = syncpt; | 1050 | n->sync_point = syncpt; |
1052 | } | 1051 | } |
1053 | 1052 | ||
1054 | /* Open parallel link when tunnel link reaches synch point */ | 1053 | /* Open parallel link when tunnel link reaches synch point */ |
1055 | if ((n->state == NODE_FAILINGOVER) && (more(rcv_nxt, n->sync_point))) { | 1054 | if ((n->state == NODE_FAILINGOVER) && !tipc_link_is_failingover(l)) { |
1055 | if (!more(rcv_nxt, n->sync_point)) | ||
1056 | return true; | ||
1056 | tipc_node_fsm_evt(n, NODE_FAILOVER_END_EVT); | 1057 | tipc_node_fsm_evt(n, NODE_FAILOVER_END_EVT); |
1057 | if (pl) | 1058 | if (pl) |
1058 | pl->exec_mode = TIPC_LINK_OPEN; | 1059 | tipc_link_fsm_evt(pl, LINK_FAILOVER_END_EVT); |
1059 | return true; | 1060 | return true; |
1060 | } | 1061 | } |
1061 | 1062 | ||
1062 | /* Initiate or update synch mode if applicable */ | 1063 | /* Initiate or update synch mode if applicable */ |
1063 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) { | 1064 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) { |
1064 | syncpt = iseqno + exp_pkts - 1; | 1065 | syncpt = iseqno + exp_pkts - 1; |
1066 | if (!tipc_link_is_up(l)) { | ||
1067 | tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT); | ||
1068 | tipc_node_link_up(n, bearer_id, xmitq); | ||
1069 | } | ||
1065 | if (n->state == SELF_UP_PEER_UP) { | 1070 | if (n->state == SELF_UP_PEER_UP) { |
1066 | n->sync_point = syncpt; | 1071 | n->sync_point = syncpt; |
1072 | tipc_link_fsm_evt(l, LINK_SYNCH_BEGIN_EVT); | ||
1067 | tipc_node_fsm_evt(n, NODE_SYNCH_BEGIN_EVT); | 1073 | tipc_node_fsm_evt(n, NODE_SYNCH_BEGIN_EVT); |
1068 | } | 1074 | } |
1069 | l->exec_mode = TIPC_LINK_TUNNEL; | ||
1070 | if (less(syncpt, n->sync_point)) | 1075 | if (less(syncpt, n->sync_point)) |
1071 | n->sync_point = syncpt; | 1076 | n->sync_point = syncpt; |
1072 | } | 1077 | } |
1073 | 1078 | ||
1074 | /* Open tunnel link when parallel link reaches synch point */ | 1079 | /* Open tunnel link when parallel link reaches synch point */ |
1075 | if ((n->state == NODE_SYNCHING) && (l->exec_mode == TIPC_LINK_TUNNEL)) { | 1080 | if ((n->state == NODE_SYNCHING) && tipc_link_is_synching(l)) { |
1076 | if (pl) | 1081 | if (pl) |
1077 | dlv_nxt = mod(pl->rcv_nxt - skb_queue_len(pl->inputq)); | 1082 | dlv_nxt = mod(pl->rcv_nxt - skb_queue_len(pl->inputq)); |
1078 | if (!pl || more(dlv_nxt, n->sync_point)) { | 1083 | if (!pl || more(dlv_nxt, n->sync_point)) { |
1084 | tipc_link_fsm_evt(l, LINK_SYNCH_END_EVT); | ||
1079 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); | 1085 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); |
1080 | l->exec_mode = TIPC_LINK_OPEN; | ||
1081 | return true; | 1086 | return true; |
1082 | } | 1087 | } |
1083 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) | 1088 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) |
@@ -1143,7 +1148,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
1143 | tipc_bclink_acknowledge(n, msg_bcast_ack(hdr)); | 1148 | tipc_bclink_acknowledge(n, msg_bcast_ack(hdr)); |
1144 | 1149 | ||
1145 | /* Check and if necessary update node state */ | 1150 | /* Check and if necessary update node state */ |
1146 | if (likely(tipc_node_check_state(n, skb, bearer_id))) { | 1151 | if (likely(tipc_node_check_state(n, skb, bearer_id, &xmitq))) { |
1147 | rc = tipc_link_rcv(le->link, skb, &xmitq); | 1152 | rc = tipc_link_rcv(le->link, skb, &xmitq); |
1148 | skb = NULL; | 1153 | skb = NULL; |
1149 | } | 1154 | } |