Remove __P macros from src/usr.bin and src/usr.sbin.
[dragonfly.git] / usr.sbin / atm / scspd / scsp_hfsm.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
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.
12 *
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.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_hfsm.c,v 1.3 1999/08/28 01:15:33 peter Exp $
2d8a3be7 27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_hfsm.c,v 1.3 2003/11/03 19:31:35 eirikn Exp $
984263bc
MD
28 */
29
30
31/*
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
34 *
35 * HELLO finite state machine
36 *
37 */
38
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>
50
51#include <errno.h>
52#include <libatm.h>
53#include <stdio.h>
54#include <syslog.h>
55
56#include "scsp_msg.h"
57#include "scsp_if.h"
58#include "scsp_var.h"
59
984263bc
MD
60/*
61 * HELLO FSM actions
62 */
63#define HELLO_ACTION_CNT 7
2d8a3be7
EN
64int scsp_hello_act_00(Scsp_dcs *, Scsp_msg *);
65int scsp_hello_act_01(Scsp_dcs *, Scsp_msg *);
66int scsp_hello_act_02(Scsp_dcs *, Scsp_msg *);
67int scsp_hello_act_03(Scsp_dcs *, Scsp_msg *);
68int scsp_hello_act_04(Scsp_dcs *, Scsp_msg *);
69int scsp_hello_act_05(Scsp_dcs *, Scsp_msg *);
70int scsp_hello_act_06(Scsp_dcs *, Scsp_msg *);
984263bc
MD
71
72static int (*scsp_action_vector[HELLO_ACTION_CNT])() = {
73 scsp_hello_act_00,
74 scsp_hello_act_01,
75 scsp_hello_act_02,
76 scsp_hello_act_03,
77 scsp_hello_act_04,
78 scsp_hello_act_05,
79 scsp_hello_act_06
80};
81
82/*
83 * HELLO FSM state table
84 */
85static int hello_state_table[SCSP_HFSM_EVENT_CNT][SCSP_HFSM_STATE_CNT] = {
86 /* 0 1 2 3 */
87 { 1, 1, 1, 1 }, /* 0 */
88 { 0, 2, 2, 2 }, /* 1 */
89 { 0, 3, 3, 3 }, /* 2 */
90 { 0, 0, 4, 4 }, /* 3 */
91 { 0, 5, 5, 6 }, /* 4 */
92};
93
94/*
95 * HELLO finite state machine
96 *
97 * Arguments:
98 * dcsp pointer to a DCS control block for the neighbor
99 * event the event which has occurred
100 * msg pointer to received message, if there is one
101 *
102 * Returns:
103 * 0 success
104 * errno error encountered
105 *
106 */
107int
108scsp_hfsm(dcsp, event, msg)
109 Scsp_dcs *dcsp;
110 int event;
111 Scsp_msg *msg;
112{
113 int action, rc, state;
114
115 /*
116 * Select an action from the state table
117 */
118 state = dcsp->sd_hello_state;
119 action = hello_state_table[event][state];
120 if (scsp_trace_mode & SCSP_TRACE_HFSM) {
121 scsp_trace("HFSM: state=%d, event=%d, action=%d\n",
122 state, event, action);
123 }
124 if (action >= HELLO_ACTION_CNT || action <= 0) {
125 scsp_log(LOG_ERR, "Hello FSM--invalid action %d; state=%d, event=%d",
126 action, dcsp->sd_hello_state, event);
127 abort();
128 }
129
130 /*
131 * Perform the selected action
132 */
133 rc = scsp_action_vector[action](dcsp, msg);
134
135 return(rc);
136}
137
138
139/*
140 * HELLO finite state machine action 0
141 * Unexpected action -- log an error message
142 *
143 * Arguments:
144 * dcsp pointer to DCS control block
145 * msg pointer to received message (ignored)
146 *
147 * Returns:
148 * EOPNOTSUPP always returns EOPNOTSUPP
149 *
150 */
151int
152scsp_hello_act_00(dcsp, msg)
153 Scsp_dcs *dcsp;
154 Scsp_msg *msg;
155{
156 scsp_log(LOG_ERR, "Hello FSM error--unexpected action, state=%d",
157 dcsp->sd_hello_state);
158 return(EOPNOTSUPP);
159}
160
161
162/*
163 * HELLO finite state machine action 1
164 * VCC open -- send HELLO message, start hello timer, go to Waiting
165 * state
166 *
167 * Arguments:
168 * dcsp pointer to DCS control block
169 * msg pointer to received message (ignored)
170 *
171 * Returns:
172 * 0 success
173 * errno error encountered
174 *
175 */
176int
177scsp_hello_act_01(dcsp, msg)
178 Scsp_dcs *dcsp;
179 Scsp_msg *msg;
180{
181 int rc;
182
183 /*
184 * Cancel the VCC open timer if it's running
185 */
186 HARP_CANCEL(&dcsp->sd_open_t);
187
188 /*
189 * Go to Waiting state
190 */
191 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
192
193 /*
194 * Send a Hello message
195 */
196 rc = scsp_send_hello(dcsp);
197 if (rc == 0) {
198 /*
199 * Success--start the Hello timer
200 */
201 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
202 scsp_hello_timeout);
203 }
204
205 return(rc);
206}
207
208
209/*
210 * HELLO finite state machine action 2
211 * VCC closed -- notify CA FSM, go to Down state, try to re-open VCC
212 *
213 * Arguments:
214 * dcsp pointer to DCS control block
215 * msg pointer to received message (ignored)
216 *
217 * Returns:
218 * 0 success
219 * errno error encountered
220 *
221 */
222int
223scsp_hello_act_02(dcsp, msg)
224 Scsp_dcs *dcsp;
225 Scsp_msg *msg;
226{
227 int rc;
228
229 /*
230 * Cancel any current timers
231 */
232 HARP_CANCEL(&dcsp->sd_hello_h_t);
233 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
234
235 /*
236 * Log the loss of the VCC
237 */
238 if (dcsp->sd_hello_state > SCSP_HFSM_WAITING) {
239 scsp_log(LOG_ERR, "VC to %s closed",
240 format_atm_addr(&dcsp->sd_addr));
241 }
242
243 /*
244 * Tell the CA FSM that the conection to the DCS is lost
245 */
246 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
247
248 /*
249 * Go to Down state
250 */
251 dcsp->sd_hello_state = SCSP_HFSM_DOWN;
252
253 /*
254 * If our ID is lower than the DCS's, wait a second before
255 * trying to connect. This should keep both of us from
256 * trying to connect at the same time, resulting in two
257 * VCCs being open.
258 */
259 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid,
260 &dcsp->sd_dcsid) < 0) {
261 /*
262 * Our ID is lower--start the VCC open timer for one
263 * second so we'll try to open the VCC if the DCS
264 * doesn't do it by then
265 */
266 HARP_TIMER(&dcsp->sd_open_t, 1, scsp_open_timeout);
267 } else {
268 /*
269 * Our ID is higher--try to reopen the VCC immediately
270 */
271 if (scsp_dcs_connect(dcsp)) {
272 /*
273 * Conncect failed -- set a timer and try
274 * again later
275 */
276 HARP_TIMER(&dcsp->sd_open_t, SCSP_Open_Interval,
277 scsp_open_timeout);
278 }
279 }
280
281 return(0);
282}
283
284
285/*
286 * HELLO finite state machine action 3
287 * Hello timer expired -- send HELLO message, restart hello timer
288 *
289 * Arguments:
290 * dcsp pointer to DCS control block
291 * msg pointer to received message (ignored)
292 *
293 * Returns:
294 * 0 success
295 * errno error encountered
296 *
297 */
298int
299scsp_hello_act_03(dcsp, msg)
300 Scsp_dcs *dcsp;
301 Scsp_msg *msg;
302{
303 int rc;
304
305 /*
306 * Send a Hello message
307 */
308 rc = scsp_send_hello(dcsp);
309 if (rc == 0) {
310 /*
311 * Success--restart the Hello timer
312 */
313 HARP_TIMER(&dcsp->sd_hello_h_t, SCSP_HELLO_Interval,
314 scsp_hello_timeout);
315 }
316
317 return(rc);
318}
319
320
321/*
322 * HELLO finite state machine action 4
323 * Receive timer expired -- if we haven't received any Hellos, notify
324 * CA FSM and go to Waiting state; if we've received Hellos, but we
325 * weren't in the receiver ID list, go to Unidirectional state
326 *
327 * Arguments:
328 * dcsp pointer to DCS control block
329 * msg pointer to received message (ignored)
330 *
331 * Returns:
332 * 0 success
333 * errno error encountered
334 *
335 */
336int
337scsp_hello_act_04(dcsp, msg)
338 Scsp_dcs *dcsp;
339 Scsp_msg *msg;
340{
341 int rc = 0;
342
343 /*
344 * Check whether we'ver received any Hellos lately
345 */
346 if (dcsp->sd_hello_rcvd) {
347 /*
348 * We've had Hellos since the receive timer was
349 * started--go to Unidirectional state
350 */
351 dcsp->sd_hello_rcvd = 0;
352 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
353 } else {
354 /*
355 * We haven't seen any Hellos at all from the DCS in
356 * hello_interval * dead_factor seconds--go to Waiting
357 * state
358 */
359 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
360 }
361
362 /*
363 * Notify the CA FSM
364 */
365 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
366
367 return(rc);
368}
369
370
371/*
372 * HELLO finite state machine action 5
373 * Message received -- Ignore all but HELLO messages; if local server
374 * is in receiver list, notify CA FSM and go to Bidirectional state;
375 * otherwise, go to Unidirectional state
376 *
377 * Arguments:
378 * dcsp pointer to DCS control block
379 * msg pointer to received message
380 *
381 * Returns:
382 * 0 success
383 * errno error encountered
384 *
385 */
386int
387scsp_hello_act_05(dcsp, msg)
388 Scsp_dcs *dcsp;
389 Scsp_msg *msg;
390{
391 int rc;
392 Scsp_id *ridp;
393
394 /*
395 * Null message pointer means message decode failed, so
396 * message must have been invalid. Go to Waiting state.
397 */
398 if (msg == (Scsp_msg *)0) {
399 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
400 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
401 return(0);
402 }
403
404 /*
405 * Ignore the message if it isn't a Hello
406 */
407 if (msg->sc_msg_type != SCSP_HELLO_MSG) {
408 return(0);
409 }
410
411 /*
412 * Save relevant information about DCS, but don't let him give
413 * us zero for timeout values
414 */
415 if (msg->sc_hello->hello_int) {
416 dcsp->sd_hello_int = msg->sc_hello->hello_int;
417 } else {
418 dcsp->sd_hello_int = 1;
419 }
420 if (msg->sc_hello->dead_factor) {
421 dcsp->sd_hello_df = msg->sc_hello->dead_factor;
422 } else {
423 dcsp->sd_hello_df = 1;
424 }
425 dcsp->sd_dcsid = msg->sc_hello->hello_mcp.sid;
426
427 /*
428 * Check the message for the local server's ID
429 */
430 for (ridp = &msg->sc_hello->hello_mcp.rid;
431 ridp;
432 ridp = ridp->next) {
433 if (scsp_cmp_id(&dcsp->sd_server->ss_lsid, ridp) == 0) {
434 /*
435 * Cancel and restart the receive timer
436 */
437 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
438 HARP_TIMER(&dcsp->sd_hello_rcv_t,
439 dcsp->sd_hello_int * dcsp->sd_hello_df,
440 scsp_hello_rcv_timeout);
441
442 /*
443 * Go to Bidirectional state and notify the
444 * CA FSM that the connection is up
445 */
446 dcsp->sd_hello_state = SCSP_HFSM_BI_DIR;
447 rc = scsp_cafsm(dcsp,
448 SCSP_CAFSM_HELLO_UP,
449 (void *)0);
450 return(rc);
451 }
452 }
453
454 /*
455 * We weren't in the receiver ID list, so go to
456 * Unidirectional state
457 */
458 dcsp->sd_hello_state = SCSP_HFSM_UNI_DIR;
459
460 return(0);
461}
462
463
464/*
465 * HELLO finite state machine action 6
466 * Message received -- if message is not a HELLO, pass it to the CA
467 * FSM; otherwise, if local server is not in receiver list, notify
468 * CA FSM and go to Unidirectional state
469 *
470 * Arguments:
471 * dcsp pointer to DCS control block
472 * msg pointer to received message
473 *
474 * Returns:
475 * 0 success
476 * errno error encountered
477 *
478 */
479int
480scsp_hello_act_06(dcsp, msg)
481 Scsp_dcs *dcsp;
482 Scsp_msg *msg;
483{
484 int rc = 0, rcv_found;
485 Scsp_id *ridp;
486
487 /*
488 * Null message pointer means message decode failed, so
489 * message must have been invalid. Go to Waiting state.
490 */
491 if (msg == (Scsp_msg *)0) {
492 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
493 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
494 rc = scsp_cafsm(dcsp, SCSP_CAFSM_HELLO_DOWN, (void *)0);
495 return(rc);
496 }
497
498 /*
499 * Process the message depending on its type
500 */
501 switch(msg->sc_msg_type) {
502 case SCSP_CA_MSG:
503 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CA_MSG, (void *)msg);
504 break;
505 case SCSP_CSU_REQ_MSG:
506 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REQ, (void *)msg);
507 break;
508 case SCSP_CSU_REPLY_MSG:
509 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSU_REPLY,
510 (void *)msg);
511 break;
512 case SCSP_CSUS_MSG:
513 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CSUS_MSG, (void *)msg);
514 break;
515 case SCSP_HELLO_MSG:
516 /*
517 * Make sure DCS info is consistent. The sender ID,
518 * family ID, protocol ID, and server group ID are
519 * checked.
520 */
521 if (scsp_cmp_id(&msg->sc_hello->hello_mcp.sid,
522 &dcsp->sd_dcsid) ||
523 (msg->sc_hello->family_id !=
524 dcsp->sd_server->ss_fid) ||
525 (msg->sc_hello->hello_mcp.pid !=
526 dcsp->sd_server->ss_pid) ||
527 (msg->sc_hello->hello_mcp.sgid !=
528 dcsp->sd_server->ss_sgid)) {
529 /*
530 * Bad info--revert to waiting state
531 */
532 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
533 dcsp->sd_hello_state = SCSP_HFSM_WAITING;
534 rc = scsp_cafsm(dcsp,
535 SCSP_CAFSM_HELLO_DOWN,
536 (void *)0);
537 return(rc);
538 }
539
540 /*
541 * Mark the arrival of the Hello message
542 */
543 dcsp->sd_hello_rcvd = 1;
544
545 /*
546 * Check the message for the local server's ID
547 */
548 for (ridp = &msg->sc_hello->hello_mcp.rid,
549 rcv_found = 0;
550 ridp;
551 ridp = ridp->next) {
552 rcv_found = (scsp_cmp_id(ridp,
553 &dcsp->sd_server->ss_lsid) == 0);
554 }
555
556 if (rcv_found) {
557 /*
558 * The LS ID was in the list of receiver IDs--
559 * Reset the Hello receive timer
560 */
561 dcsp->sd_hello_rcvd = 0;
562 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
563 HARP_TIMER(&dcsp->sd_hello_rcv_t,
564 dcsp->sd_hello_int *
565 dcsp->sd_hello_df,
566 scsp_hello_rcv_timeout);
567 }
568 break;
569 }
570
571 return(rc);
572}