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.2 2003/06/17 04:28:49 dillon Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * Signalling manager finite state machine
38 #include <netatm/kern_include.h>
40 #include <netatm/uni/uni.h>
41 #include <netatm/uni/unisig.h>
42 #include <netatm/uni/unisig_var.h>
47 static int unisig_sigmgr_invalid __P((struct unisig *, KBuffer *));
48 static int unisig_sigmgr_act01 __P((struct unisig *, KBuffer *));
49 static int unisig_sigmgr_act02 __P((struct unisig *, KBuffer *));
50 static int unisig_sigmgr_act03 __P((struct unisig *, KBuffer *));
51 static int unisig_sigmgr_act04 __P((struct unisig *, KBuffer *));
52 static int unisig_sigmgr_act05 __P((struct unisig *, KBuffer *));
53 static int unisig_sigmgr_act06 __P((struct unisig *, KBuffer *));
54 static int unisig_sigmgr_act07 __P((struct unisig *, KBuffer *));
55 static int unisig_sigmgr_act08 __P((struct unisig *, KBuffer *));
56 static int unisig_sigmgr_act09 __P((struct unisig *, KBuffer *));
57 static int unisig_sigmgr_act10 __P((struct unisig *, KBuffer *));
58 static int unisig_sigmgr_act11 __P((struct unisig *, KBuffer *));
59 static int unisig_sigmgr_act12 __P((struct unisig *, KBuffer *));
60 static int unisig_sigmgr_act13 __P((struct unisig *, KBuffer *));
61 static int unisig_sigmgr_act14 __P((struct unisig *, KBuffer *));
67 static int sigmgr_state_table[10][7] = {
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 */
85 static int (*unisig_sigmgr_act_vec[MAX_ACTION])
86 __P((struct unisig *, KBuffer *)) = {
87 unisig_sigmgr_invalid,
106 * ATM endpoint for UNI signalling channel
108 static Atm_endpoint unisig_endpt = {
110 ENDPT_UNI_SIG, /* ep_id */
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 = {
132 CMAPI_SAAL, /* api */
133 UNI_VERS_3_0, /* api_init */
137 T_ATM_PRESENT, /* aal.tag */
138 ATM_AAL5 /* aal.aal_type */
141 T_ATM_PRESENT, /* traffic.tag */
143 { /* traffic.v.forward */
144 T_ATM_ABSENT, /* PCR_high */
146 T_ATM_ABSENT, /* SCR_high */
147 T_ATM_ABSENT, /* SCR_all */
148 T_ATM_ABSENT, /* MBS_high */
149 T_ATM_ABSENT, /* MBS_all */
152 { /* traffic.v.backward */
153 T_ATM_ABSENT, /* PCR_high */
155 T_ATM_ABSENT, /* SCR_high */
156 T_ATM_ABSENT, /* SCR_all */
157 T_ATM_ABSENT, /* MBS_high */
158 T_ATM_ABSENT, /* MBS_all */
161 T_YES, /* best_effort */
165 T_ATM_PRESENT, /* bearer.tag */
167 T_ATM_CLASS_X, /* class */
168 T_ATM_NULL, /* traffic_type */
169 T_ATM_NO_END_TO_END, /* timing_req */
171 T_ATM_1_TO_1, /* conn_conf */
175 T_ATM_ABSENT, /* bhli.tag */
178 T_ATM_ABSENT, /* blli.tag_l2 */
179 T_ATM_ABSENT, /* blli.tag_l3 */
182 T_ATM_ABSENT, /* llc.tag */
185 T_ATM_PRESENT, /* called.tag */
188 T_ATM_ABSENT, /* calling.tag */
191 T_ATM_PRESENT, /* qos.tag */
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 */
203 T_ATM_ABSENT, /* transit.tag */
206 T_ATM_ABSENT, /* cause.tag */
212 * Finite state machine for the UNISIG signalling manager
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)
221 * errno error encountered
225 unisig_sigmgr_state(usp, event, m)
233 * Cancel any signalling manager timer
238 * Select an action based on the incoming event and
239 * the signalling manager's state
241 action = sigmgr_state_table[event][usp->us_state];
242 ATM_DEBUG4("unisig_sigmgr_state: usp=%p, state=%d, event=%d, action=%d\n",
243 usp, usp->us_state, event, action);
244 if (action >= MAX_ACTION || action < 0) {
245 panic("unisig_sigmgr_state: invalid action\n");
249 * Perform the requested action
251 err = unisig_sigmgr_act_vec[action](usp, m);
258 * Signalling manager state machine action 0
263 * usp pointer to the UNISIG protocol control block
264 * m buffer pointer (may be NULL)
268 * errno error encountered
272 unisig_sigmgr_invalid(usp, m)
276 log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
284 * Signalling manager state machine action 1
286 * The kickoff timer has expired at attach time; go to
287 * UNISIG_ADDR_WAIT state.
290 * usp pointer to the UNISIG protocol control block
291 * m buffer pointer (may be NULL)
295 * errno error encountered
299 unisig_sigmgr_act01(usp, m)
306 usp->us_state = UNISIG_ADDR_WAIT;
313 * Signalling manager state machine action 2
318 * usp pointer to the UNISIG protocol control block
319 * m buffer pointer (may be NULL)
323 * errno error encountered
327 unisig_sigmgr_act02(usp, m)
332 * Ignore event, discard message if present
342 * Signalling manager state machine action 3
344 * SSCF session on signalling channel has come up
347 * usp pointer to the UNISIG protocol control block
348 * m buffer pointer (may be NULL)
352 * errno error encountered
356 unisig_sigmgr_act03(usp, m)
360 struct unisig_vccb *uvp, *vnext;
365 log(LOG_INFO, "unisig: signalling channel active\n");
370 usp->us_state = UNISIG_ACTIVE;
373 * Notify the VC state machine that the channel is up
375 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
377 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
378 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
379 (struct unisig_msg *) 0);
387 * Signalling manager state machine action 4
389 * A SSCF release indication was received. Try to establish an
390 * SSCF session on the signalling PVC.
393 * usp pointer to the UNISIG protocol control block
394 * m buffer pointer (may be NULL)
398 * errno error encountered
402 unisig_sigmgr_act04(usp, m)
409 * Try to establish an SSCF session.
411 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
415 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
422 * Signalling manager state machine action 5
424 * SSCF session on signalling channel has been reset
427 * usp pointer to the UNISIG protocol control block
428 * m buffer pointer (may be NULL)
432 * errno error encountered
436 unisig_sigmgr_act05(usp, m)
440 struct unisig_vccb *uvp, *vnext;
445 log(LOG_INFO, "unisig: signalling channel reset\n");
448 * Notify the VC state machine of the reset
450 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
452 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
453 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
454 (struct unisig_msg *) 0);
462 * Signalling manager state machine action 6
464 * SSCF session on signalling channel has been lost
467 * usp pointer to the UNISIG protocol control block
468 * m buffer pointer (may be NULL)
472 * errno error encountered
476 unisig_sigmgr_act06(usp, m)
480 struct unisig_vccb *uvp, *vnext;
483 * Log the fact that the session has been lost
485 log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
488 * Notify the VC state machine of the loss
490 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
492 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
493 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
494 (struct unisig_msg *) 0);
498 * Try to restart the SSCF session
500 (void) unisig_sigmgr_act04(usp, (KBuffer *) 0);
505 usp->us_state = UNISIG_INIT;
512 * Signalling manager state machine action 7
514 * A Q.2931 signalling message has been received
517 * usp pointer to the UNISIG protocol control block
518 * m buffer pointer (may be NULL)
522 * errno error encountered
526 unisig_sigmgr_act07(usp, m)
533 * Pass the Q.2931 signalling message on
534 * to the VC state machine
536 err = unisig_rcv_msg(usp, m);
543 * Signalling manager state machine action 8
545 * Process a CALL_CLOSED event for the signalling PVC
548 * usp pointer to the UNISIG protocol control block
549 * m buffer pointer (may be NULL)
553 * errno error encountered
557 unisig_sigmgr_act08(usp, m)
563 * Signalling manager is now incommunicado
565 if (usp->us_state != UNISIG_DETACH) {
567 * Log an error and set the state to NULL if
568 * we're not detaching
570 log(LOG_ERR, "unisig: signalling channel closed\n");
571 usp->us_state = UNISIG_NULL;
580 * Signalling manager state machine action 9
585 * usp pointer to the UNISIG protocol control block
586 * m buffer pointer (may be NULL)
590 * errno error encountered
594 unisig_sigmgr_act09(usp, m)
598 log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
606 * Signalling manager state machine action 10
611 * usp pointer to the UNISIG protocol control block
612 * m buffer pointer (may be NULL)
616 * errno error encountered
620 unisig_sigmgr_act10(usp, m)
629 * Signalling manager state machine action 11
634 * usp pointer to the UNISIG protocol control block
635 * m buffer pointer (may be NULL)
639 * errno error encountered
643 unisig_sigmgr_act11(usp, m)
647 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
655 * Signalling manager state machine action 12
660 * usp pointer to the UNISIG protocol control block
661 * m buffer pointer (may be NULL)
665 * errno error encountered
669 unisig_sigmgr_act12(usp, m)
673 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
681 * Signalling manager state machine action 13
683 * NSAP prefix has been set
686 * usp pointer to the UNISIG protocol control block
687 * m buffer pointer (may be NULL)
691 * errno error encountered
695 unisig_sigmgr_act13(usp, m)
703 * Set UNI signalling channel connection attributes
705 if (usp->us_proto == ATM_SIG_UNI30)
706 unisig_attr.api_init = UNI_VERS_3_0;
708 unisig_attr.api_init = UNI_VERS_3_1;
710 unisig_attr.nif = usp->us_pif->pif_nif;
712 unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
713 unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
714 unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
716 unisig_attr.called.tag = T_ATM_PRESENT;
717 unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
718 unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
719 pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
720 ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
721 ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
722 unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
723 unisig_attr.called.subaddr.address_length = 0;
725 unisig_attr.traffic.v.forward.PCR_all_traffic =
726 usp->us_pif->pif_pcr;
727 unisig_attr.traffic.v.backward.PCR_all_traffic =
728 usp->us_pif->pif_pcr;
731 * Create UNISIG signalling channel
733 err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
740 * Establish the SSCF session
742 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
746 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
751 usp->us_state = UNISIG_INIT;
758 * Signalling manager state machine action 14
760 * Process a detach event
763 * usp pointer to the UNISIG protocol control block
764 * m buffer pointer (may be NULL)
768 * errno error encountered
772 unisig_sigmgr_act14(usp, m)
777 struct unisig_vccb *sig_vccb, *uvp, *vnext;
779 struct t_atm_cause cause;
782 * Locate the signalling channel's VCCB
784 sig_vccb = (struct unisig_vccb *)0;
785 if (usp->us_conn && usp->us_conn->co_connvc)
786 sig_vccb = (struct unisig_vccb *)
787 usp->us_conn->co_connvc->cvc_vcc;
790 * Terminate all of our VCCs
792 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
794 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
797 * Don't close the signalling VCC yet
803 * Close VCC and notify owner
805 err = unisig_clear_vcc(usp, uvp,
806 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
810 * Close the signalling channel
813 cause.coding_standard = T_ATM_ITU_CODING;
814 cause.coding_standard = T_ATM_LOC_USER;
815 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
816 err = atm_cm_release(usp->us_conn, &cause);
818 panic("unisig_sigmgr_act14: close failed\n");
822 * Get rid of protocol instance if there are no VCCs queued
825 if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
827 struct sigmgr *smp = pip->pif_sigmgr;
830 pip->pif_sigmgr = NULL;
831 pip->pif_siginst = NULL;
834 UNLINK((struct siginst *)usp, struct siginst,
835 smp->sm_prinst, si_next);
836 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
839 * Otherwise, set new signalling manager state and
840 * wait for protocol instance to be freed during
841 * unisig_free processing for the last queued VCC
843 usp->us_state = UNISIG_DETACH;