HAMMER Utilities: MFC work to date.
[dragonfly.git] / sys / netproto / atm / uni / unisig_sigmgr_state.c
blobece9eabfbc16025d63d0203ed63ffc1afa3f867b
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/sys/netatm/uni/unisig_sigmgr_state.c,v 1.6 2000/01/17 20:49:58 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_sigmgr_state.c,v 1.7 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * Signalling manager finite state machine
38 #include <netproto/atm/kern_include.h>
40 #include "uni.h"
41 #include "unisig.h"
42 #include "unisig_var.h"
45 * Local functions
47 static int unisig_sigmgr_invalid (struct unisig *, KBuffer *);
48 static int unisig_sigmgr_act01 (struct unisig *, KBuffer *);
49 static int unisig_sigmgr_act02 (struct unisig *, KBuffer *);
50 static int unisig_sigmgr_act03 (struct unisig *, KBuffer *);
51 static int unisig_sigmgr_act04 (struct unisig *, KBuffer *);
52 static int unisig_sigmgr_act05 (struct unisig *, KBuffer *);
53 static int unisig_sigmgr_act06 (struct unisig *, KBuffer *);
54 static int unisig_sigmgr_act07 (struct unisig *, KBuffer *);
55 static int unisig_sigmgr_act08 (struct unisig *, KBuffer *);
56 static int unisig_sigmgr_act09 (struct unisig *, KBuffer *);
57 static int unisig_sigmgr_act10 (struct unisig *, KBuffer *);
58 static int unisig_sigmgr_act11 (struct unisig *, KBuffer *);
59 static int unisig_sigmgr_act12 (struct unisig *, KBuffer *);
60 static int unisig_sigmgr_act13 (struct unisig *, KBuffer *);
61 static int unisig_sigmgr_act14 (struct unisig *, KBuffer *);
65 * State table.
67 static int sigmgr_state_table[10][7] = {
68 /* 0 1 2 3 4 5 */
69 { 1, 0, 0, 0, 0 }, /* 0 - Time out */
70 { 0, 0, 3, 5, 0 }, /* 1 - SSCF estab ind */
71 { 0, 0, 3, 5, 0 }, /* 2 - SSCF estab cnf */
72 { 0, 0, 4, 6, 0 }, /* 3 - SSCF release ind */
73 { 0, 0, 0, 6, 0 }, /* 4 - SSCF release cnf */
74 { 0, 0, 0, 7, 0 }, /* 5 - SSCF data ind */
75 { 0, 0, 2, 2, 0 }, /* 6 - SSCF unit data ind */
76 { 0, 0, 8, 8, 8 }, /* 7 - Call cleared */
77 { 14, 14, 14, 14, 0 }, /* 8 - Detach */
78 { 13, 13, 0, 0, 0 } /* 9 - Address set */
82 * Action vector
84 #define MAX_ACTION 15
85 static int (*unisig_sigmgr_act_vec[MAX_ACTION])
86 (struct unisig *, KBuffer *) = {
87 unisig_sigmgr_invalid,
88 unisig_sigmgr_act01,
89 unisig_sigmgr_act02,
90 unisig_sigmgr_act03,
91 unisig_sigmgr_act04,
92 unisig_sigmgr_act05,
93 unisig_sigmgr_act06,
94 unisig_sigmgr_act07,
95 unisig_sigmgr_act08,
96 unisig_sigmgr_act09,
97 unisig_sigmgr_act10,
98 unisig_sigmgr_act11,
99 unisig_sigmgr_act12,
100 unisig_sigmgr_act13,
101 unisig_sigmgr_act14
106 * ATM endpoint for UNI signalling channel
108 static Atm_endpoint unisig_endpt = {
109 NULL, /* ep_next */
110 ENDPT_UNI_SIG, /* ep_id */
111 NULL, /* ep_ioctl */
112 unisig_getname, /* ep_getname */
113 unisig_connected, /* ep_connected */
114 unisig_cleared, /* ep_cleared */
115 NULL, /* ep_incoming */
116 NULL, /* ep_addparty */
117 NULL, /* ep_dropparty */
118 NULL, /* ep_cpcs_ctl */
119 NULL, /* ep_cpcs_data */
120 unisig_saal_ctl, /* ep_saal_ctl */
121 unisig_saal_data, /* ep_saal_data */
122 NULL, /* ep_sscop_ctl */
123 NULL /* ep_sscop_data */
128 * ATM connection attributes for UNI signalling channel
130 static Atm_attributes unisig_attr = {
131 NULL, /* nif */
132 CMAPI_SAAL, /* api */
133 UNI_VERS_3_0, /* api_init */
134 0, /* headin */
135 0, /* headout */
136 { /* aal */
137 T_ATM_PRESENT, /* aal.tag */
138 ATM_AAL5 /* aal.aal_type */
140 { /* traffic */
141 T_ATM_PRESENT, /* traffic.tag */
142 { /* traffic.v */
143 { /* traffic.v.forward */
144 T_ATM_ABSENT, /* PCR_high */
145 0, /* PCR_all */
146 T_ATM_ABSENT, /* SCR_high */
147 T_ATM_ABSENT, /* SCR_all */
148 T_ATM_ABSENT, /* MBS_high */
149 T_ATM_ABSENT, /* MBS_all */
150 T_NO, /* tagging */
152 { /* traffic.v.backward */
153 T_ATM_ABSENT, /* PCR_high */
154 0, /* PCR_all */
155 T_ATM_ABSENT, /* SCR_high */
156 T_ATM_ABSENT, /* SCR_all */
157 T_ATM_ABSENT, /* MBS_high */
158 T_ATM_ABSENT, /* MBS_all */
159 T_NO, /* tagging */
161 T_YES, /* best_effort */
164 { /* bearer */
165 T_ATM_PRESENT, /* bearer.tag */
166 { /* bearer.v */
167 T_ATM_CLASS_X, /* class */
168 T_ATM_NULL, /* traffic_type */
169 T_ATM_NO_END_TO_END, /* timing_req */
170 T_NO, /* clipping */
171 T_ATM_1_TO_1, /* conn_conf */
174 { /* bhli */
175 T_ATM_ABSENT, /* bhli.tag */
177 { /* blli */
178 T_ATM_ABSENT, /* blli.tag_l2 */
179 T_ATM_ABSENT, /* blli.tag_l3 */
181 { /* llc */
182 T_ATM_ABSENT, /* llc.tag */
184 { /* called */
185 T_ATM_PRESENT, /* called.tag */
187 { /* calling */
188 T_ATM_ABSENT, /* calling.tag */
190 { /* qos */
191 T_ATM_PRESENT, /* qos.tag */
192 { /* qos.v */
193 T_ATM_NETWORK_CODING, /* coding_standard */
194 { /* qos.v.forward */
195 T_ATM_QOS_CLASS_0, /* class */
197 { /* qos.v.backward */
198 T_ATM_QOS_CLASS_0, /* class */
202 { /* transit */
203 T_ATM_ABSENT, /* transit.tag */
205 { /* cause */
206 T_ATM_ABSENT, /* cause.tag */
212 * Finite state machine for the UNISIG signalling manager
214 * Arguments:
215 * usp pointer to the UNISIG protocol control block
216 * event indication of the event to be processed
217 * m pointer to a buffer with a message (optional)
219 * Returns:
220 * 0 success
221 * errno error encountered
225 unisig_sigmgr_state(struct unisig *usp, int event, KBuffer *m)
227 int action, err = 0;
230 * Cancel any signalling manager timer
232 UNISIG_CANCEL(usp);
235 * Select an action based on the incoming event and
236 * the signalling manager's state
238 action = sigmgr_state_table[event][usp->us_state];
239 ATM_DEBUG4("unisig_sigmgr_state: usp=%p, state=%d, event=%d, action=%d\n",
240 usp, usp->us_state, event, action);
241 if (action >= MAX_ACTION || action < 0) {
242 panic("unisig_sigmgr_state: invalid action\n");
246 * Perform the requested action
248 err = unisig_sigmgr_act_vec[action](usp, m);
250 return(err);
255 * Signalling manager state machine action 0
257 * Invalid action
259 * Arguments:
260 * usp pointer to the UNISIG protocol control block
261 * m buffer pointer (may be NULL)
263 * Returns:
264 * 0 success
265 * errno error encountered
268 static int
269 unisig_sigmgr_invalid(struct unisig *usp, KBuffer *m)
271 log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
272 if (m)
273 KB_FREEALL(m);
274 return(0);
279 * Signalling manager state machine action 1
281 * The kickoff timer has expired at attach time; go to
282 * UNISIG_ADDR_WAIT state.
284 * Arguments:
285 * usp pointer to the UNISIG protocol control block
286 * m buffer pointer (may be NULL)
288 * Returns:
289 * 0 success
290 * errno error encountered
293 static int
294 unisig_sigmgr_act01(struct unisig *usp, KBuffer *m)
297 * Set the new state
299 usp->us_state = UNISIG_ADDR_WAIT;
301 return(0);
306 * Signalling manager state machine action 2
308 * Ignore the event
310 * Arguments:
311 * usp pointer to the UNISIG protocol control block
312 * m buffer pointer (may be NULL)
314 * Returns:
315 * 0 success
316 * errno error encountered
319 static int
320 unisig_sigmgr_act02(struct unisig *usp, KBuffer *m)
323 * Ignore event, discard message if present
325 if (m)
326 KB_FREEALL(m);
328 return(0);
333 * Signalling manager state machine action 3
335 * SSCF session on signalling channel has come up
337 * Arguments:
338 * usp pointer to the UNISIG protocol control block
339 * m buffer pointer (may be NULL)
341 * Returns:
342 * 0 success
343 * errno error encountered
346 static int
347 unisig_sigmgr_act03(struct unisig *usp, KBuffer *m)
349 struct unisig_vccb *uvp, *vnext;
352 * Log the activation
354 log(LOG_INFO, "unisig: signalling channel active\n");
357 * Go to ACTIVE state
359 usp->us_state = UNISIG_ACTIVE;
362 * Notify the VC state machine that the channel is up
364 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
365 uvp; uvp = vnext) {
366 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
367 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
368 (struct unisig_msg *) 0);
371 return(0);
376 * Signalling manager state machine action 4
378 * A SSCF release indication was received. Try to establish an
379 * SSCF session on the signalling PVC.
381 * Arguments:
382 * usp pointer to the UNISIG protocol control block
383 * m buffer pointer (may be NULL)
385 * Returns:
386 * 0 success
387 * errno error encountered
390 static int
391 unisig_sigmgr_act04(struct unisig *usp, KBuffer *m)
393 int err;
396 * Try to establish an SSCF session.
398 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
399 usp->us_conn,
400 (void *)0);
401 if (err)
402 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
404 return(0);
409 * Signalling manager state machine action 5
411 * SSCF session on signalling channel has been reset
413 * Arguments:
414 * usp pointer to the UNISIG protocol control block
415 * m buffer pointer (may be NULL)
417 * Returns:
418 * 0 success
419 * errno error encountered
422 static int
423 unisig_sigmgr_act05(struct unisig *usp, KBuffer *m)
425 struct unisig_vccb *uvp, *vnext;
428 * Log the reset
430 log(LOG_INFO, "unisig: signalling channel reset\n");
433 * Notify the VC state machine of the reset
435 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
436 uvp; uvp = vnext) {
437 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
438 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
439 (struct unisig_msg *) 0);
442 return(0);
447 * Signalling manager state machine action 6
449 * SSCF session on signalling channel has been lost
451 * Arguments:
452 * usp pointer to the UNISIG protocol control block
453 * m buffer pointer (may be NULL)
455 * Returns:
456 * 0 success
457 * errno error encountered
460 static int
461 unisig_sigmgr_act06(struct unisig *usp, KBuffer *m)
463 struct unisig_vccb *uvp, *vnext;
466 * Log the fact that the session has been lost
468 log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
471 * Notify the VC state machine of the loss
473 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
474 uvp; uvp = vnext) {
475 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
476 unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
477 (struct unisig_msg *) 0);
481 * Try to restart the SSCF session
483 unisig_sigmgr_act04(usp, (KBuffer *) 0);
486 * Go to INIT state
488 usp->us_state = UNISIG_INIT;
490 return(0);
495 * Signalling manager state machine action 7
497 * A Q.2931 signalling message has been received
499 * Arguments:
500 * usp pointer to the UNISIG protocol control block
501 * m buffer pointer (may be NULL)
503 * Returns:
504 * 0 success
505 * errno error encountered
508 static int
509 unisig_sigmgr_act07(struct unisig *usp, KBuffer *m)
511 int err;
514 * Pass the Q.2931 signalling message on
515 * to the VC state machine
517 err = unisig_rcv_msg(usp, m);
519 return(err);
524 * Signalling manager state machine action 8
526 * Process a CALL_CLOSED event for the signalling PVC
528 * Arguments:
529 * usp pointer to the UNISIG protocol control block
530 * m buffer pointer (may be NULL)
532 * Returns:
533 * 0 success
534 * errno error encountered
537 static int
538 unisig_sigmgr_act08(struct unisig *usp, KBuffer *m)
542 * Signalling manager is now incommunicado
544 if (usp->us_state != UNISIG_DETACH) {
546 * Log an error and set the state to NULL if
547 * we're not detaching
549 log(LOG_ERR, "unisig: signalling channel closed\n");
550 usp->us_state = UNISIG_NULL;
552 usp->us_conn = 0;
554 return(0);
559 * Signalling manager state machine action 9
561 * Not used
563 * Arguments:
564 * usp pointer to the UNISIG protocol control block
565 * m buffer pointer (may be NULL)
567 * Returns:
568 * 0 success
569 * errno error encountered
572 static int
573 unisig_sigmgr_act09(struct unisig *usp, KBuffer *m)
575 log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
576 if (m)
577 KB_FREEALL(m);
578 return (0);
583 * Signalling manager state machine action 10
585 * Not used
587 * Arguments:
588 * usp pointer to the UNISIG protocol control block
589 * m buffer pointer (may be NULL)
591 * Returns:
592 * 0 success
593 * errno error encountered
596 static int
597 unisig_sigmgr_act10(struct unisig *usp, KBuffer *m)
599 return(0);
604 * Signalling manager state machine action 11
606 * Not used
608 * Arguments:
609 * usp pointer to the UNISIG protocol control block
610 * m buffer pointer (may be NULL)
612 * Returns:
613 * 0 success
614 * errno error encountered
617 static int
618 unisig_sigmgr_act11(struct unisig *usp, KBuffer *m)
620 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
621 if (m)
622 KB_FREEALL(m);
623 return(0);
628 * Signalling manager state machine action 12
630 * Not used
632 * Arguments:
633 * usp pointer to the UNISIG protocol control block
634 * m buffer pointer (may be NULL)
636 * Returns:
637 * 0 success
638 * errno error encountered
641 static int
642 unisig_sigmgr_act12(struct unisig *usp, KBuffer *m)
644 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
645 if (m)
646 KB_FREEALL(m);
647 return(0);
652 * Signalling manager state machine action 13
654 * NSAP prefix has been set
656 * Arguments:
657 * usp pointer to the UNISIG protocol control block
658 * m buffer pointer (may be NULL)
660 * Returns:
661 * 0 success
662 * errno error encountered
665 static int
666 unisig_sigmgr_act13(struct unisig *usp, KBuffer *m)
668 int err;
669 Atm_addr_pvc *pvcp;
672 * Set UNI signalling channel connection attributes
674 if (usp->us_proto == ATM_SIG_UNI30)
675 unisig_attr.api_init = UNI_VERS_3_0;
676 else
677 unisig_attr.api_init = UNI_VERS_3_1;
679 unisig_attr.nif = usp->us_pif->pif_nif;
681 unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
682 unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
683 unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
685 unisig_attr.called.tag = T_ATM_PRESENT;
686 unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
687 unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
688 pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
689 ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
690 ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
691 unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
692 unisig_attr.called.subaddr.address_length = 0;
694 unisig_attr.traffic.v.forward.PCR_all_traffic =
695 usp->us_pif->pif_pcr;
696 unisig_attr.traffic.v.backward.PCR_all_traffic =
697 usp->us_pif->pif_pcr;
700 * Create UNISIG signalling channel
702 err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
703 &usp->us_conn);
704 if (err) {
705 return(err);
709 * Establish the SSCF session
711 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
712 usp->us_conn,
713 (void *)0);
714 if (err)
715 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
718 * Set the new state
720 usp->us_state = UNISIG_INIT;
722 return(0);
727 * Signalling manager state machine action 14
729 * Process a detach event
731 * Arguments:
732 * usp pointer to the UNISIG protocol control block
733 * m buffer pointer (may be NULL)
735 * Returns:
736 * 0 success
737 * errno error encountered
740 static int
741 unisig_sigmgr_act14(struct unisig *usp, KBuffer *m)
743 int err;
744 struct unisig_vccb *sig_vccb, *uvp, *vnext;
745 struct atm_pif *pip;
746 struct t_atm_cause cause;
749 * Locate the signalling channel's VCCB
751 sig_vccb = (struct unisig_vccb *)0;
752 if (usp->us_conn && usp->us_conn->co_connvc)
753 sig_vccb = (struct unisig_vccb *)
754 usp->us_conn->co_connvc->cvc_vcc;
757 * Terminate all of our VCCs
759 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
760 uvp; uvp = vnext) {
761 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
764 * Don't close the signalling VCC yet
766 if (uvp == sig_vccb)
767 continue;
770 * Close VCC and notify owner
772 err = unisig_clear_vcc(usp, uvp,
773 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
777 * Close the signalling channel
779 if (usp->us_conn) {
780 cause.coding_standard = T_ATM_ITU_CODING;
781 cause.coding_standard = T_ATM_LOC_USER;
782 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
783 err = atm_cm_release(usp->us_conn, &cause);
784 if (err)
785 panic("unisig_sigmgr_act14: close failed\n");
789 * Get rid of protocol instance if there are no VCCs queued
791 pip = usp->us_pif;
792 if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
793 pip->pif_sigmgr) {
794 struct sigmgr *smp = pip->pif_sigmgr;
796 crit_enter();
797 pip->pif_sigmgr = NULL;
798 pip->pif_siginst = NULL;
799 crit_exit();
801 UNLINK((struct siginst *)usp, struct siginst,
802 smp->sm_prinst, si_next);
803 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
804 } else {
806 * Otherwise, set new signalling manager state and
807 * wait for protocol instance to be freed during
808 * unisig_free processing for the last queued VCC
810 usp->us_state = UNISIG_DETACH;
813 return (0);