kernel - VM PAGER part 1/2 - Remove vm_page_alloc()
[dragonfly.git] / usr.sbin / atm / scspd / scsp_hfsm.c
blobdc127e75c3ce72647ba893e8d163a1adad7455b0
1 /*
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 $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_hfsm.c,v 1.5 2007/11/25 01:28:23 swildner 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>
42 #include <net/if.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>
51 #include <errno.h>
52 #include <libatm.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <syslog.h>
57 #include "scsp_msg.h"
58 #include "scsp_if.h"
59 #include "scsp_var.h"
62 * HELLO FSM actions
64 #define HELLO_ACTION_CNT 7
65 int scsp_hello_act_00(Scsp_dcs *, Scsp_msg *);
66 int scsp_hello_act_01(Scsp_dcs *, Scsp_msg *);
67 int scsp_hello_act_02(Scsp_dcs *, Scsp_msg *);
68 int scsp_hello_act_03(Scsp_dcs *, Scsp_msg *);
69 int scsp_hello_act_04(Scsp_dcs *, Scsp_msg *);
70 int scsp_hello_act_05(Scsp_dcs *, Scsp_msg *);
71 int scsp_hello_act_06(Scsp_dcs *, Scsp_msg *);
73 static int (*scsp_action_vector[HELLO_ACTION_CNT])() = {
74 scsp_hello_act_00,
75 scsp_hello_act_01,
76 scsp_hello_act_02,
77 scsp_hello_act_03,
78 scsp_hello_act_04,
79 scsp_hello_act_05,
80 scsp_hello_act_06
84 * HELLO FSM state table
86 static int hello_state_table[SCSP_HFSM_EVENT_CNT][SCSP_HFSM_STATE_CNT] = {
87 /* 0 1 2 3 */
88 { 1, 1, 1, 1 }, /* 0 */
89 { 0, 2, 2, 2 }, /* 1 */
90 { 0, 3, 3, 3 }, /* 2 */
91 { 0, 0, 4, 4 }, /* 3 */
92 { 0, 5, 5, 6 }, /* 4 */
96 * HELLO finite state machine
98 * Arguments:
99 * dcsp pointer to a DCS control block for the neighbor
100 * event the event which has occurred
101 * msg pointer to received message, if there is one
103 * Returns:
104 * 0 success
105 * errno error encountered
109 scsp_hfsm(Scsp_dcs *dcsp, int event, Scsp_msg *msg)
111 int action, rc, state;
114 * Select an action from the state table
116 state = dcsp->sd_hello_state;
117 action = hello_state_table[event][state];
118 if (scsp_trace_mode & SCSP_TRACE_HFSM) {
119 scsp_trace("HFSM: state=%d, event=%d, action=%d\n",
120 state, event, action);
122 if (action >= HELLO_ACTION_CNT || action <= 0) {
123 scsp_log(LOG_ERR, "Hello FSM--invalid action %d; state=%d, event=%d",
124 action, dcsp->sd_hello_state, event);
125 abort();
129 * Perform the selected action
131 rc = scsp_action_vector[action](dcsp, msg);
133 return(rc);
138 * HELLO finite state machine action 0
139 * Unexpected action -- log an error message
141 * Arguments:
142 * dcsp pointer to DCS control block
143 * msg pointer to received message (ignored)
145 * Returns:
146 * EOPNOTSUPP always returns EOPNOTSUPP
150 scsp_hello_act_00(Scsp_dcs *dcsp, Scsp_msg *msg)
152 scsp_log(LOG_ERR, "Hello FSM error--unexpected action, state=%d",
153 dcsp->sd_hello_state);
154 return(EOPNOTSUPP);
159 * HELLO finite state machine action 1
160 * VCC open -- send HELLO message, start hello timer, go to Waiting
161 * state
163 * Arguments:
164 * dcsp pointer to DCS control block
165 * msg pointer to received message (ignored)
167 * Returns:
168 * 0 success
169 * errno error encountered
173 scsp_hello_act_01(Scsp_dcs *dcsp, Scsp_msg *msg)
175 int rc;
178 * Cancel the VCC open timer if it's running
180 HARP_CANCEL(&dcsp->sd_open_t);
183 * Go to Waiting state
185 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
188 * Send a Hello message
190 rc = scsp_send_hello(dcsp);
191 if (rc == 0) {
193 * Success--start the Hello timer
195 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
196 scsp_hello_timeout);
199 return(rc);
204 * HELLO finite state machine action 2
205 * VCC closed -- notify CA FSM, go to Down state, try to re-open VCC
207 * Arguments:
208 * dcsp pointer to DCS control block
209 * msg pointer to received message (ignored)
211 * Returns:
212 * 0 success
213 * errno error encountered
217 scsp_hello_act_02(Scsp_dcs *dcsp, Scsp_msg *msg)
219 int rc;
222 * Cancel any current timers
224 HARP_CANCEL(&dcsp->sd_hello_h_t);
225 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
228 * Log the loss of the VCC
230 if (dcsp->sd_hello_state > SCSP_HFSM_WAITING) {
231 scsp_log(LOG_ERR, "VC to %s closed",
232 format_atm_addr(&dcsp->sd_addr));
236 * Tell the CA FSM that the conection to the DCS is lost
238 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, NULL);
241 * Go to Down state
243 dcsp->sd_hello_state = SCSP_HFSM_DOWN;
246 * If our ID is lower than the DCS's, wait a second before
247 * trying to connect. This should keep both of us from
248 * trying to connect at the same time, resulting in two
249 * VCCs being open.
251 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid,
252 &dcsp->sd_dcsid) < 0) {
254 * Our ID is lower--start the VCC open timer for one
255 * second so we'll try to open the VCC if the DCS
256 * doesn't do it by then
258 HARP_TIMER(&dcsp->sd_open_t, 1, scsp_open_timeout);
259 } else {
261 * Our ID is higher--try to reopen the VCC immediately
263 if (scsp_dcs_connect(dcsp)) {
265 * Conncect failed -- set a timer and try
266 * again later
268 HARP_TIMER(&dcsp->sd_open_t, SCSP_Open_Interval,
269 scsp_open_timeout);
273 return(0);
278 * HELLO finite state machine action 3
279 * Hello timer expired -- send HELLO message, restart hello timer
281 * Arguments:
282 * dcsp pointer to DCS control block
283 * msg pointer to received message (ignored)
285 * Returns:
286 * 0 success
287 * errno error encountered
291 scsp_hello_act_03(Scsp_dcs *dcsp, Scsp_msg *msg)
293 int rc;
296 * Send a Hello message
298 rc = scsp_send_hello(dcsp);
299 if (rc == 0) {
301 * Success--restart the Hello timer
303 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
304 scsp_hello_timeout);
307 return(rc);
312 * HELLO finite state machine action 4
313 * Receive timer expired -- if we haven't received any Hellos, notify
314 * CA FSM and go to Waiting state; if we've received Hellos, but we
315 * weren't in the receiver ID list, go to Unidirectional state
317 * Arguments:
318 * dcsp pointer to DCS control block
319 * msg pointer to received message (ignored)
321 * Returns:
322 * 0 success
323 * errno error encountered
327 scsp_hello_act_04(Scsp_dcs *dcsp, Scsp_msg *msg)
329 int rc = 0;
332 * Check whether we'ver received any Hellos lately
334 if (dcsp->sd_hello_rcvd) {
336 * We've had Hellos since the receive timer was
337 * started--go to Unidirectional state
339 dcsp->sd_hello_rcvd = 0;
340 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
341 } else {
343 * We haven't seen any Hellos at all from the DCS in
344 * hello_interval * dead_factor seconds--go to Waiting
345 * state
347 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
351 * Notify the CA FSM
353 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, NULL);
355 return(rc);
360 * HELLO finite state machine action 5
361 * Message received -- Ignore all but HELLO messages; if local server
362 * is in receiver list, notify CA FSM and go to Bidirectional state;
363 * otherwise, go to Unidirectional state
365 * Arguments:
366 * dcsp pointer to DCS control block
367 * msg pointer to received message
369 * Returns:
370 * 0 success
371 * errno error encountered
375 scsp_hello_act_05(Scsp_dcs *dcsp, Scsp_msg *msg)
377 int rc;
378 Scsp_id *ridp;
381 * Null message pointer means message decode failed, so
382 * message must have been invalid. Go to Waiting state.
384 if (msg == NULL) {
385 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
386 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
387 return(0);
391 * Ignore the message if it isn't a Hello
393 if (msg->sc_msg_type != SCSP_HELLO_MSG) {
394 return(0);
398 * Save relevant information about DCS, but don't let him give
399 * us zero for timeout values
401 if (msg->sc_hello->hello_int) {
402 dcsp->sd_hello_int = msg->sc_hello->hello_int;
403 } else {
404 dcsp->sd_hello_int = 1;
406 if (msg->sc_hello->dead_factor) {
407 dcsp->sd_hello_df = msg->sc_hello->dead_factor;
408 } else {
409 dcsp->sd_hello_df = 1;
411 dcsp->sd_dcsid = msg->sc_hello->hello_mcp.sid;
414 * Check the message for the local server's ID
416 for (ridp = &msg->sc_hello->hello_mcp.rid;
417 ridp;
418 ridp = ridp->next) {
419 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid, ridp) == 0) {
421 * Cancel and restart the receive timer
423 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
424 HARP_TIMER(&dcsp->sd_hello_rcv_t,
425 dcsp->sd_hello_int * dcsp->sd_hello_df,
426 scsp_hello_rcv_timeout);
429 * Go to Bidirectional state and notify the
430 * CA FSM that the connection is up
432 dcsp->sd_hello_state = SCSP_HFSM_BI_DIR;
433 rc = scsp_cafsm(dcsp,
434 SCSP_CAFSM_HELLO_UP,
435 NULL);
436 return(rc);
441 * We weren't in the receiver ID list, so go to
442 * Unidirectional state
444 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
446 return(0);
451 * HELLO finite state machine action 6
452 * Message received -- if message is not a HELLO, pass it to the CA
453 * FSM; otherwise, if local server is not in receiver list, notify
454 * CA FSM and go to Unidirectional state
456 * Arguments:
457 * dcsp pointer to DCS control block
458 * msg pointer to received message
460 * Returns:
461 * 0 success
462 * errno error encountered
466 scsp_hello_act_06(Scsp_dcs *dcsp, Scsp_msg *msg)
468 int rc = 0, rcv_found;
469 Scsp_id *ridp;
472 * Null message pointer means message decode failed, so
473 * message must have been invalid. Go to Waiting state.
475 if (msg == NULL) {
476 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
477 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
478 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, NULL);
479 return(rc);
483 * Process the message depending on its type
485 switch(msg->sc_msg_type) {
486 case SCSP_CA_MSG:
487 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CA_MSG, (void *)msg);
488 break;
489 case SCSP_CSU_REQ_MSG:
490 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REQ, (void *)msg);
491 break;
492 case SCSP_CSU_REPLY_MSG:
493 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REPLY,
494 (void *)msg);
495 break;
496 case SCSP_CSUS_MSG:
497 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSUS_MSG, (void *)msg);
498 break;
499 case SCSP_HELLO_MSG:
501 * Make sure DCS info is consistent. The sender ID,
502 * family ID, protocol ID, and server group ID are
503 * checked.
505 if (scsp_cmp_id(&msg->sc_hello->hello_mcp.sid,
506 &dcsp->sd_dcsid) ||
507 (msg->sc_hello->family_id !=
508 dcsp->sd_server->ss_fid) ||
509 (msg->sc_hello->hello_mcp.pid !=
510 dcsp->sd_server->ss_pid) ||
511 (msg->sc_hello->hello_mcp.sgid !=
512 dcsp->sd_server->ss_sgid)) {
514 * Bad info--revert to waiting state
516 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
517 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
518 rc = scsp_cafsm(dcsp,
519 SCSP_CAFSM_HELLO_DOWN,
520 NULL);
521 return(rc);
525 * Mark the arrival of the Hello message
527 dcsp->sd_hello_rcvd = 1;
530 * Check the message for the local server's ID
532 for (ridp = &msg->sc_hello->hello_mcp.rid,
533 rcv_found = 0;
534 ridp;
535 ridp = ridp->next) {
536 rcv_found = (scsp_cmp_id(ridp,
537 &dcsp->sd_server->ss_lsid) == 0);
540 if (rcv_found) {
542 * The LS ID was in the list of receiver IDs--
543 * Reset the Hello receive timer
545 dcsp->sd_hello_rcvd = 0;
546 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
547 HARP_TIMER(&dcsp->sd_hello_rcv_t,
548 dcsp->sd_hello_int *
549 dcsp->sd_hello_df,
550 scsp_hello_rcv_timeout);
552 break;
555 return(rc);