3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_hfsm.c,v 1.3 1999/08/28 01:15:33 peter Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * HELLO finite state machine
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
61 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_hfsm.c,v 1.3 1999/08/28 01:15:33 peter Exp $");
68 #define HELLO_ACTION_CNT 7
69 int scsp_hello_act_00 __P((Scsp_dcs *, Scsp_msg *));
70 int scsp_hello_act_01 __P((Scsp_dcs *, Scsp_msg *));
71 int scsp_hello_act_02 __P((Scsp_dcs *, Scsp_msg *));
72 int scsp_hello_act_03 __P((Scsp_dcs *, Scsp_msg *));
73 int scsp_hello_act_04 __P((Scsp_dcs *, Scsp_msg *));
74 int scsp_hello_act_05 __P((Scsp_dcs *, Scsp_msg *));
75 int scsp_hello_act_06 __P((Scsp_dcs *, Scsp_msg *));
77 static int (*scsp_action_vector[HELLO_ACTION_CNT])() = {
88 * HELLO FSM state table
90 static int hello_state_table[SCSP_HFSM_EVENT_CNT][SCSP_HFSM_STATE_CNT] = {
92 { 1, 1, 1, 1 }, /* 0 */
93 { 0, 2, 2, 2 }, /* 1 */
94 { 0, 3, 3, 3 }, /* 2 */
95 { 0, 0, 4, 4 }, /* 3 */
96 { 0, 5, 5, 6 }, /* 4 */
100 * HELLO finite state machine
103 * dcsp pointer to a DCS control block for the neighbor
104 * event the event which has occurred
105 * msg pointer to received message, if there is one
109 * errno error encountered
113 scsp_hfsm(dcsp, event, msg)
118 int action, rc, state;
121 * Select an action from the state table
123 state = dcsp->sd_hello_state;
124 action = hello_state_table[event][state];
125 if (scsp_trace_mode & SCSP_TRACE_HFSM) {
126 scsp_trace("HFSM: state=%d, event=%d, action=%d\n",
127 state, event, action);
129 if (action >= HELLO_ACTION_CNT || action <= 0) {
130 scsp_log(LOG_ERR, "Hello FSM--invalid action %d; state=%d, event=%d",
131 action, dcsp->sd_hello_state, event);
136 * Perform the selected action
138 rc = scsp_action_vector[action](dcsp, msg);
145 * HELLO finite state machine action 0
146 * Unexpected action -- log an error message
149 * dcsp pointer to DCS control block
150 * msg pointer to received message (ignored)
153 * EOPNOTSUPP always returns EOPNOTSUPP
157 scsp_hello_act_00(dcsp, msg)
161 scsp_log(LOG_ERR, "Hello FSM error--unexpected action, state=%d",
162 dcsp->sd_hello_state);
168 * HELLO finite state machine action 1
169 * VCC open -- send HELLO message, start hello timer, go to Waiting
173 * dcsp pointer to DCS control block
174 * msg pointer to received message (ignored)
178 * errno error encountered
182 scsp_hello_act_01(dcsp, msg)
189 * Cancel the VCC open timer if it's running
191 HARP_CANCEL(&dcsp->sd_open_t);
194 * Go to Waiting state
196 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
199 * Send a Hello message
201 rc = scsp_send_hello(dcsp);
204 * Success--start the Hello timer
206 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
215 * HELLO finite state machine action 2
216 * VCC closed -- notify CA FSM, go to Down state, try to re-open VCC
219 * dcsp pointer to DCS control block
220 * msg pointer to received message (ignored)
224 * errno error encountered
228 scsp_hello_act_02(dcsp, msg)
235 * Cancel any current timers
237 HARP_CANCEL(&dcsp->sd_hello_h_t);
238 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
241 * Log the loss of the VCC
243 if (dcsp->sd_hello_state > SCSP_HFSM_WAITING) {
244 scsp_log(LOG_ERR, "VC to %s closed",
245 format_atm_addr(&dcsp->sd_addr));
249 * Tell the CA FSM that the conection to the DCS is lost
251 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
256 dcsp->sd_hello_state = SCSP_HFSM_DOWN;
259 * If our ID is lower than the DCS's, wait a second before
260 * trying to connect. This should keep both of us from
261 * trying to connect at the same time, resulting in two
264 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid,
265 &dcsp->sd_dcsid) < 0) {
267 * Our ID is lower--start the VCC open timer for one
268 * second so we'll try to open the VCC if the DCS
269 * doesn't do it by then
271 HARP_TIMER(&dcsp->sd_open_t, 1, scsp_open_timeout);
274 * Our ID is higher--try to reopen the VCC immediately
276 if (scsp_dcs_connect(dcsp)) {
278 * Conncect failed -- set a timer and try
281 HARP_TIMER(&dcsp->sd_open_t, SCSP_Open_Interval,
291 * HELLO finite state machine action 3
292 * Hello timer expired -- send HELLO message, restart hello timer
295 * dcsp pointer to DCS control block
296 * msg pointer to received message (ignored)
300 * errno error encountered
304 scsp_hello_act_03(dcsp, msg)
311 * Send a Hello message
313 rc = scsp_send_hello(dcsp);
316 * Success--restart the Hello timer
318 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
327 * HELLO finite state machine action 4
328 * Receive timer expired -- if we haven't received any Hellos, notify
329 * CA FSM and go to Waiting state; if we've received Hellos, but we
330 * weren't in the receiver ID list, go to Unidirectional state
333 * dcsp pointer to DCS control block
334 * msg pointer to received message (ignored)
338 * errno error encountered
342 scsp_hello_act_04(dcsp, msg)
349 * Check whether we'ver received any Hellos lately
351 if (dcsp->sd_hello_rcvd) {
353 * We've had Hellos since the receive timer was
354 * started--go to Unidirectional state
356 dcsp->sd_hello_rcvd = 0;
357 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
360 * We haven't seen any Hellos at all from the DCS in
361 * hello_interval * dead_factor seconds--go to Waiting
364 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
370 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
377 * HELLO finite state machine action 5
378 * Message received -- Ignore all but HELLO messages; if local server
379 * is in receiver list, notify CA FSM and go to Bidirectional state;
380 * otherwise, go to Unidirectional state
383 * dcsp pointer to DCS control block
384 * msg pointer to received message
388 * errno error encountered
392 scsp_hello_act_05(dcsp, msg)
400 * Null message pointer means message decode failed, so
401 * message must have been invalid. Go to Waiting state.
403 if (msg == (Scsp_msg *)0) {
404 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
405 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
410 * Ignore the message if it isn't a Hello
412 if (msg->sc_msg_type != SCSP_HELLO_MSG) {
417 * Save relevant information about DCS, but don't let him give
418 * us zero for timeout values
420 if (msg->sc_hello->hello_int) {
421 dcsp->sd_hello_int = msg->sc_hello->hello_int;
423 dcsp->sd_hello_int = 1;
425 if (msg->sc_hello->dead_factor) {
426 dcsp->sd_hello_df = msg->sc_hello->dead_factor;
428 dcsp->sd_hello_df = 1;
430 dcsp->sd_dcsid = msg->sc_hello->hello_mcp.sid;
433 * Check the message for the local server's ID
435 for (ridp = &msg->sc_hello->hello_mcp.rid;
438 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid, ridp) == 0) {
440 * Cancel and restart the receive timer
442 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
443 HARP_TIMER(&dcsp->sd_hello_rcv_t,
444 dcsp->sd_hello_int * dcsp->sd_hello_df,
445 scsp_hello_rcv_timeout);
448 * Go to Bidirectional state and notify the
449 * CA FSM that the connection is up
451 dcsp->sd_hello_state = SCSP_HFSM_BI_DIR;
452 rc = scsp_cafsm(dcsp,
460 * We weren't in the receiver ID list, so go to
461 * Unidirectional state
463 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
470 * HELLO finite state machine action 6
471 * Message received -- if message is not a HELLO, pass it to the CA
472 * FSM; otherwise, if local server is not in receiver list, notify
473 * CA FSM and go to Unidirectional state
476 * dcsp pointer to DCS control block
477 * msg pointer to received message
481 * errno error encountered
485 scsp_hello_act_06(dcsp, msg)
489 int rc = 0, rcv_found;
493 * Null message pointer means message decode failed, so
494 * message must have been invalid. Go to Waiting state.
496 if (msg == (Scsp_msg *)0) {
497 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
498 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
499 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
504 * Process the message depending on its type
506 switch(msg->sc_msg_type) {
508 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CA_MSG, (void *)msg);
510 case SCSP_CSU_REQ_MSG:
511 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REQ, (void *)msg);
513 case SCSP_CSU_REPLY_MSG:
514 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REPLY,
518 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSUS_MSG, (void *)msg);
522 * Make sure DCS info is consistent. The sender ID,
523 * family ID, protocol ID, and server group ID are
526 if (scsp_cmp_id(&msg->sc_hello->hello_mcp.sid,
528 (msg->sc_hello->family_id !=
529 dcsp->sd_server->ss_fid) ||
530 (msg->sc_hello->hello_mcp.pid !=
531 dcsp->sd_server->ss_pid) ||
532 (msg->sc_hello->hello_mcp.sgid !=
533 dcsp->sd_server->ss_sgid)) {
535 * Bad info--revert to waiting state
537 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
538 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
539 rc = scsp_cafsm(dcsp,
540 SCSP_CAFSM_HELLO_DOWN,
546 * Mark the arrival of the Hello message
548 dcsp->sd_hello_rcvd = 1;
551 * Check the message for the local server's ID
553 for (ridp = &msg->sc_hello->hello_mcp.rid,
557 rcv_found = (scsp_cmp_id(ridp,
558 &dcsp->sd_server->ss_lsid) == 0);
563 * The LS ID was in the list of receiver IDs--
564 * Reset the Hello receive timer
566 dcsp->sd_hello_rcvd = 0;
567 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
568 HARP_TIMER(&dcsp->sd_hello_rcv_t,
571 scsp_hello_rcv_timeout);