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 $
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>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/unisig_sigmgr_state.c,v 1.6 2000/01/17 20:49:58 mks Exp $");
52 static int unisig_sigmgr_invalid __P((struct unisig *, KBuffer *));
53 static int unisig_sigmgr_act01 __P((struct unisig *, KBuffer *));
54 static int unisig_sigmgr_act02 __P((struct unisig *, KBuffer *));
55 static int unisig_sigmgr_act03 __P((struct unisig *, KBuffer *));
56 static int unisig_sigmgr_act04 __P((struct unisig *, KBuffer *));
57 static int unisig_sigmgr_act05 __P((struct unisig *, KBuffer *));
58 static int unisig_sigmgr_act06 __P((struct unisig *, KBuffer *));
59 static int unisig_sigmgr_act07 __P((struct unisig *, KBuffer *));
60 static int unisig_sigmgr_act08 __P((struct unisig *, KBuffer *));
61 static int unisig_sigmgr_act09 __P((struct unisig *, KBuffer *));
62 static int unisig_sigmgr_act10 __P((struct unisig *, KBuffer *));
63 static int unisig_sigmgr_act11 __P((struct unisig *, KBuffer *));
64 static int unisig_sigmgr_act12 __P((struct unisig *, KBuffer *));
65 static int unisig_sigmgr_act13 __P((struct unisig *, KBuffer *));
66 static int unisig_sigmgr_act14 __P((struct unisig *, KBuffer *));
72 static int sigmgr_state_table[10][7] = {
74 { 1, 0, 0, 0, 0 }, /* 0 - Time out */
75 { 0, 0, 3, 5, 0 }, /* 1 - SSCF estab ind */
76 { 0, 0, 3, 5, 0 }, /* 2 - SSCF estab cnf */
77 { 0, 0, 4, 6, 0 }, /* 3 - SSCF release ind */
78 { 0, 0, 0, 6, 0 }, /* 4 - SSCF release cnf */
79 { 0, 0, 0, 7, 0 }, /* 5 - SSCF data ind */
80 { 0, 0, 2, 2, 0 }, /* 6 - SSCF unit data ind */
81 { 0, 0, 8, 8, 8 }, /* 7 - Call cleared */
82 { 14, 14, 14, 14, 0 }, /* 8 - Detach */
83 { 13, 13, 0, 0, 0 } /* 9 - Address set */
90 static int (*unisig_sigmgr_act_vec[MAX_ACTION])
91 __P((struct unisig *, KBuffer *)) = {
92 unisig_sigmgr_invalid,
111 * ATM endpoint for UNI signalling channel
113 static Atm_endpoint unisig_endpt = {
115 ENDPT_UNI_SIG, /* ep_id */
117 unisig_getname, /* ep_getname */
118 unisig_connected, /* ep_connected */
119 unisig_cleared, /* ep_cleared */
120 NULL, /* ep_incoming */
121 NULL, /* ep_addparty */
122 NULL, /* ep_dropparty */
123 NULL, /* ep_cpcs_ctl */
124 NULL, /* ep_cpcs_data */
125 unisig_saal_ctl, /* ep_saal_ctl */
126 unisig_saal_data, /* ep_saal_data */
127 NULL, /* ep_sscop_ctl */
128 NULL /* ep_sscop_data */
133 * ATM connection attributes for UNI signalling channel
135 static Atm_attributes unisig_attr = {
137 CMAPI_SAAL, /* api */
138 UNI_VERS_3_0, /* api_init */
142 T_ATM_PRESENT, /* aal.tag */
143 ATM_AAL5 /* aal.aal_type */
146 T_ATM_PRESENT, /* traffic.tag */
148 { /* traffic.v.forward */
149 T_ATM_ABSENT, /* PCR_high */
151 T_ATM_ABSENT, /* SCR_high */
152 T_ATM_ABSENT, /* SCR_all */
153 T_ATM_ABSENT, /* MBS_high */
154 T_ATM_ABSENT, /* MBS_all */
157 { /* traffic.v.backward */
158 T_ATM_ABSENT, /* PCR_high */
160 T_ATM_ABSENT, /* SCR_high */
161 T_ATM_ABSENT, /* SCR_all */
162 T_ATM_ABSENT, /* MBS_high */
163 T_ATM_ABSENT, /* MBS_all */
166 T_YES, /* best_effort */
170 T_ATM_PRESENT, /* bearer.tag */
172 T_ATM_CLASS_X, /* class */
173 T_ATM_NULL, /* traffic_type */
174 T_ATM_NO_END_TO_END, /* timing_req */
176 T_ATM_1_TO_1, /* conn_conf */
180 T_ATM_ABSENT, /* bhli.tag */
183 T_ATM_ABSENT, /* blli.tag_l2 */
184 T_ATM_ABSENT, /* blli.tag_l3 */
187 T_ATM_ABSENT, /* llc.tag */
190 T_ATM_PRESENT, /* called.tag */
193 T_ATM_ABSENT, /* calling.tag */
196 T_ATM_PRESENT, /* qos.tag */
198 T_ATM_NETWORK_CODING, /* coding_standard */
199 { /* qos.v.forward */
200 T_ATM_QOS_CLASS_0, /* class */
202 { /* qos.v.backward */
203 T_ATM_QOS_CLASS_0, /* class */
208 T_ATM_ABSENT, /* transit.tag */
211 T_ATM_ABSENT, /* cause.tag */
217 * Finite state machine for the UNISIG signalling manager
220 * usp pointer to the UNISIG protocol control block
221 * event indication of the event to be processed
222 * m pointer to a buffer with a message (optional)
226 * errno error encountered
230 unisig_sigmgr_state(usp, event, m)
238 * Cancel any signalling manager timer
243 * Select an action based on the incoming event and
244 * the signalling manager's state
246 action = sigmgr_state_table[event][usp->us_state];
247 ATM_DEBUG4("unisig_sigmgr_state: usp=%p, state=%d, event=%d, action=%d\n",
248 usp, usp->us_state, event, action);
249 if (action >= MAX_ACTION || action < 0) {
250 panic("unisig_sigmgr_state: invalid action\n");
254 * Perform the requested action
256 err = unisig_sigmgr_act_vec[action](usp, m);
263 * Signalling manager state machine action 0
268 * usp pointer to the UNISIG protocol control block
269 * m buffer pointer (may be NULL)
273 * errno error encountered
277 unisig_sigmgr_invalid(usp, m)
281 log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
289 * Signalling manager state machine action 1
291 * The kickoff timer has expired at attach time; go to
292 * UNISIG_ADDR_WAIT state.
295 * usp pointer to the UNISIG protocol control block
296 * m buffer pointer (may be NULL)
300 * errno error encountered
304 unisig_sigmgr_act01(usp, m)
311 usp->us_state = UNISIG_ADDR_WAIT;
318 * Signalling manager state machine action 2
323 * usp pointer to the UNISIG protocol control block
324 * m buffer pointer (may be NULL)
328 * errno error encountered
332 unisig_sigmgr_act02(usp, m)
337 * Ignore event, discard message if present
347 * Signalling manager state machine action 3
349 * SSCF session on signalling channel has come up
352 * usp pointer to the UNISIG protocol control block
353 * m buffer pointer (may be NULL)
357 * errno error encountered
361 unisig_sigmgr_act03(usp, m)
365 struct unisig_vccb *uvp, *vnext;
370 log(LOG_INFO, "unisig: signalling channel active\n");
375 usp->us_state = UNISIG_ACTIVE;
378 * Notify the VC state machine that the channel is up
380 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
382 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
383 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
384 (struct unisig_msg *) 0);
392 * Signalling manager state machine action 4
394 * A SSCF release indication was received. Try to establish an
395 * SSCF session on the signalling PVC.
398 * usp pointer to the UNISIG protocol control block
399 * m buffer pointer (may be NULL)
403 * errno error encountered
407 unisig_sigmgr_act04(usp, m)
414 * Try to establish an SSCF session.
416 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
420 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
427 * Signalling manager state machine action 5
429 * SSCF session on signalling channel has been reset
432 * usp pointer to the UNISIG protocol control block
433 * m buffer pointer (may be NULL)
437 * errno error encountered
441 unisig_sigmgr_act05(usp, m)
445 struct unisig_vccb *uvp, *vnext;
450 log(LOG_INFO, "unisig: signalling channel reset\n");
453 * Notify the VC state machine of the reset
455 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
457 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
458 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
459 (struct unisig_msg *) 0);
467 * Signalling manager state machine action 6
469 * SSCF session on signalling channel has been lost
472 * usp pointer to the UNISIG protocol control block
473 * m buffer pointer (may be NULL)
477 * errno error encountered
481 unisig_sigmgr_act06(usp, m)
485 struct unisig_vccb *uvp, *vnext;
488 * Log the fact that the session has been lost
490 log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
493 * Notify the VC state machine of the loss
495 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
497 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
498 (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
499 (struct unisig_msg *) 0);
503 * Try to restart the SSCF session
505 (void) unisig_sigmgr_act04(usp, (KBuffer *) 0);
510 usp->us_state = UNISIG_INIT;
517 * Signalling manager state machine action 7
519 * A Q.2931 signalling message has been received
522 * usp pointer to the UNISIG protocol control block
523 * m buffer pointer (may be NULL)
527 * errno error encountered
531 unisig_sigmgr_act07(usp, m)
538 * Pass the Q.2931 signalling message on
539 * to the VC state machine
541 err = unisig_rcv_msg(usp, m);
548 * Signalling manager state machine action 8
550 * Process a CALL_CLOSED event for the signalling PVC
553 * usp pointer to the UNISIG protocol control block
554 * m buffer pointer (may be NULL)
558 * errno error encountered
562 unisig_sigmgr_act08(usp, m)
568 * Signalling manager is now incommunicado
570 if (usp->us_state != UNISIG_DETACH) {
572 * Log an error and set the state to NULL if
573 * we're not detaching
575 log(LOG_ERR, "unisig: signalling channel closed\n");
576 usp->us_state = UNISIG_NULL;
585 * Signalling manager state machine action 9
590 * usp pointer to the UNISIG protocol control block
591 * m buffer pointer (may be NULL)
595 * errno error encountered
599 unisig_sigmgr_act09(usp, m)
603 log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
611 * Signalling manager state machine action 10
616 * usp pointer to the UNISIG protocol control block
617 * m buffer pointer (may be NULL)
621 * errno error encountered
625 unisig_sigmgr_act10(usp, m)
634 * Signalling manager state machine action 11
639 * usp pointer to the UNISIG protocol control block
640 * m buffer pointer (may be NULL)
644 * errno error encountered
648 unisig_sigmgr_act11(usp, m)
652 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
660 * Signalling manager state machine action 12
665 * usp pointer to the UNISIG protocol control block
666 * m buffer pointer (may be NULL)
670 * errno error encountered
674 unisig_sigmgr_act12(usp, m)
678 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
686 * Signalling manager state machine action 13
688 * NSAP prefix has been set
691 * usp pointer to the UNISIG protocol control block
692 * m buffer pointer (may be NULL)
696 * errno error encountered
700 unisig_sigmgr_act13(usp, m)
708 * Set UNI signalling channel connection attributes
710 if (usp->us_proto == ATM_SIG_UNI30)
711 unisig_attr.api_init = UNI_VERS_3_0;
713 unisig_attr.api_init = UNI_VERS_3_1;
715 unisig_attr.nif = usp->us_pif->pif_nif;
717 unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
718 unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
719 unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
721 unisig_attr.called.tag = T_ATM_PRESENT;
722 unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
723 unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
724 pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
725 ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
726 ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
727 unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
728 unisig_attr.called.subaddr.address_length = 0;
730 unisig_attr.traffic.v.forward.PCR_all_traffic =
731 usp->us_pif->pif_pcr;
732 unisig_attr.traffic.v.backward.PCR_all_traffic =
733 usp->us_pif->pif_pcr;
736 * Create UNISIG signalling channel
738 err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
745 * Establish the SSCF session
747 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
751 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
756 usp->us_state = UNISIG_INIT;
763 * Signalling manager state machine action 14
765 * Process a detach event
768 * usp pointer to the UNISIG protocol control block
769 * m buffer pointer (may be NULL)
773 * errno error encountered
777 unisig_sigmgr_act14(usp, m)
782 struct unisig_vccb *sig_vccb, *uvp, *vnext;
784 struct t_atm_cause cause;
787 * Locate the signalling channel's VCCB
789 sig_vccb = (struct unisig_vccb *)0;
790 if (usp->us_conn && usp->us_conn->co_connvc)
791 sig_vccb = (struct unisig_vccb *)
792 usp->us_conn->co_connvc->cvc_vcc;
795 * Terminate all of our VCCs
797 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
799 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
802 * Don't close the signalling VCC yet
808 * Close VCC and notify owner
810 err = unisig_clear_vcc(usp, uvp,
811 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
815 * Close the signalling channel
818 cause.coding_standard = T_ATM_ITU_CODING;
819 cause.coding_standard = T_ATM_LOC_USER;
820 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
821 err = atm_cm_release(usp->us_conn, &cause);
823 panic("unisig_sigmgr_act14: close failed\n");
827 * Get rid of protocol instance if there are no VCCs queued
830 if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
832 struct sigmgr *smp = pip->pif_sigmgr;
835 pip->pif_sigmgr = NULL;
836 pip->pif_siginst = NULL;
839 UNLINK((struct siginst *)usp, struct siginst,
840 smp->sm_prinst, si_next);
841 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
844 * Otherwise, set new signalling manager state and
845 * wait for protocol instance to be freed during
846 * unisig_free processing for the last queued VCC
848 usp->us_state = UNISIG_DETACH;