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 $
30 * ATM Forum UNI 3.0/3.1 Signalling Manager
31 * ----------------------------------------
33 * Signalling manager finite state machine
37 #include <netproto/atm/kern_include.h>
41 #include "unisig_var.h"
46 static int unisig_sigmgr_invalid (struct unisig *, KBuffer *);
47 static int unisig_sigmgr_act01 (struct unisig *, KBuffer *);
48 static int unisig_sigmgr_act02 (struct unisig *, KBuffer *);
49 static int unisig_sigmgr_act03 (struct unisig *, KBuffer *);
50 static int unisig_sigmgr_act04 (struct unisig *, KBuffer *);
51 static int unisig_sigmgr_act05 (struct unisig *, KBuffer *);
52 static int unisig_sigmgr_act06 (struct unisig *, KBuffer *);
53 static int unisig_sigmgr_act07 (struct unisig *, KBuffer *);
54 static int unisig_sigmgr_act08 (struct unisig *, KBuffer *);
55 static int unisig_sigmgr_act09 (struct unisig *, KBuffer *);
56 static int unisig_sigmgr_act10 (struct unisig *, KBuffer *);
57 static int unisig_sigmgr_act11 (struct unisig *, KBuffer *);
58 static int unisig_sigmgr_act12 (struct unisig *, KBuffer *);
59 static int unisig_sigmgr_act13 (struct unisig *, KBuffer *);
60 static int unisig_sigmgr_act14 (struct unisig *, KBuffer *);
66 static int sigmgr_state_table[10][7] = {
68 { 1, 0, 0, 0, 0 }, /* 0 - Time out */
69 { 0, 0, 3, 5, 0 }, /* 1 - SSCF estab ind */
70 { 0, 0, 3, 5, 0 }, /* 2 - SSCF estab cnf */
71 { 0, 0, 4, 6, 0 }, /* 3 - SSCF release ind */
72 { 0, 0, 0, 6, 0 }, /* 4 - SSCF release cnf */
73 { 0, 0, 0, 7, 0 }, /* 5 - SSCF data ind */
74 { 0, 0, 2, 2, 0 }, /* 6 - SSCF unit data ind */
75 { 0, 0, 8, 8, 8 }, /* 7 - Call cleared */
76 { 14, 14, 14, 14, 0 }, /* 8 - Detach */
77 { 13, 13, 0, 0, 0 } /* 9 - Address set */
84 static int (*unisig_sigmgr_act_vec[MAX_ACTION])
85 (struct unisig *, KBuffer *) = {
86 unisig_sigmgr_invalid,
105 * ATM endpoint for UNI signalling channel
107 static Atm_endpoint unisig_endpt = {
109 ENDPT_UNI_SIG, /* ep_id */
111 unisig_getname, /* ep_getname */
112 unisig_connected, /* ep_connected */
113 unisig_cleared, /* ep_cleared */
114 NULL, /* ep_incoming */
115 NULL, /* ep_addparty */
116 NULL, /* ep_dropparty */
117 NULL, /* ep_cpcs_ctl */
118 NULL, /* ep_cpcs_data */
119 unisig_saal_ctl, /* ep_saal_ctl */
120 unisig_saal_data, /* ep_saal_data */
121 NULL, /* ep_sscop_ctl */
122 NULL /* ep_sscop_data */
127 * ATM connection attributes for UNI signalling channel
129 static Atm_attributes unisig_attr = {
131 CMAPI_SAAL, /* api */
132 UNI_VERS_3_0, /* api_init */
136 T_ATM_PRESENT, /* aal.tag */
137 ATM_AAL5 /* aal.aal_type */
140 T_ATM_PRESENT, /* traffic.tag */
142 { /* traffic.v.forward */
143 T_ATM_ABSENT, /* PCR_high */
145 T_ATM_ABSENT, /* SCR_high */
146 T_ATM_ABSENT, /* SCR_all */
147 T_ATM_ABSENT, /* MBS_high */
148 T_ATM_ABSENT, /* MBS_all */
151 { /* traffic.v.backward */
152 T_ATM_ABSENT, /* PCR_high */
154 T_ATM_ABSENT, /* SCR_high */
155 T_ATM_ABSENT, /* SCR_all */
156 T_ATM_ABSENT, /* MBS_high */
157 T_ATM_ABSENT, /* MBS_all */
160 T_YES, /* best_effort */
164 T_ATM_PRESENT, /* bearer.tag */
166 T_ATM_CLASS_X, /* class */
167 T_ATM_NULL, /* traffic_type */
168 T_ATM_NO_END_TO_END, /* timing_req */
170 T_ATM_1_TO_1, /* conn_conf */
174 T_ATM_ABSENT, /* bhli.tag */
177 T_ATM_ABSENT, /* blli.tag_l2 */
178 T_ATM_ABSENT, /* blli.tag_l3 */
181 T_ATM_ABSENT, /* llc.tag */
184 T_ATM_PRESENT, /* called.tag */
187 T_ATM_ABSENT, /* calling.tag */
190 T_ATM_PRESENT, /* qos.tag */
192 T_ATM_NETWORK_CODING, /* coding_standard */
193 { /* qos.v.forward */
194 T_ATM_QOS_CLASS_0, /* class */
196 { /* qos.v.backward */
197 T_ATM_QOS_CLASS_0, /* class */
202 T_ATM_ABSENT, /* transit.tag */
205 T_ATM_ABSENT, /* cause.tag */
211 * Finite state machine for the UNISIG signalling manager
214 * usp pointer to the UNISIG protocol control block
215 * event indication of the event to be processed
216 * m pointer to a buffer with a message (optional)
220 * errno error encountered
224 unisig_sigmgr_state(struct unisig *usp, int event, KBuffer *m)
229 * Cancel any signalling manager timer
234 * Select an action based on the incoming event and
235 * the signalling manager's state
237 action = sigmgr_state_table[event][usp->us_state];
238 ATM_DEBUG4("unisig_sigmgr_state: usp=%p, state=%d, event=%d, action=%d\n",
239 usp, usp->us_state, event, action);
240 if (action >= MAX_ACTION || action < 0) {
241 panic("unisig_sigmgr_state: invalid action");
245 * Perform the requested action
247 err = unisig_sigmgr_act_vec[action](usp, m);
254 * Signalling manager state machine action 0
259 * usp pointer to the UNISIG protocol control block
260 * m buffer pointer (may be NULL)
264 * errno error encountered
268 unisig_sigmgr_invalid(struct unisig *usp, KBuffer *m)
270 log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
278 * Signalling manager state machine action 1
280 * The kickoff timer has expired at attach time; go to
281 * UNISIG_ADDR_WAIT state.
284 * usp pointer to the UNISIG protocol control block
285 * m buffer pointer (may be NULL)
289 * errno error encountered
293 unisig_sigmgr_act01(struct unisig *usp, KBuffer *m)
298 usp->us_state = UNISIG_ADDR_WAIT;
305 * Signalling manager state machine action 2
310 * usp pointer to the UNISIG protocol control block
311 * m buffer pointer (may be NULL)
315 * errno error encountered
319 unisig_sigmgr_act02(struct unisig *usp, KBuffer *m)
322 * Ignore event, discard message if present
332 * Signalling manager state machine action 3
334 * SSCF session on signalling channel has come up
337 * usp pointer to the UNISIG protocol control block
338 * m buffer pointer (may be NULL)
342 * errno error encountered
346 unisig_sigmgr_act03(struct unisig *usp, KBuffer *m)
348 struct unisig_vccb *uvp, *vnext;
353 log(LOG_INFO, "unisig: signalling channel active\n");
358 usp->us_state = UNISIG_ACTIVE;
361 * Notify the VC state machine that the channel is up
363 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
365 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
366 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
375 * Signalling manager state machine action 4
377 * A SSCF release indication was received. Try to establish an
378 * SSCF session on the signalling PVC.
381 * usp pointer to the UNISIG protocol control block
382 * m buffer pointer (may be NULL)
386 * errno error encountered
390 unisig_sigmgr_act04(struct unisig *usp, KBuffer *m)
395 * Try to establish an SSCF session.
397 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
399 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
406 * Signalling manager state machine action 5
408 * SSCF session on signalling channel has been reset
411 * usp pointer to the UNISIG protocol control block
412 * m buffer pointer (may be NULL)
416 * errno error encountered
420 unisig_sigmgr_act05(struct unisig *usp, KBuffer *m)
422 struct unisig_vccb *uvp, *vnext;
427 log(LOG_INFO, "unisig: signalling channel reset\n");
430 * Notify the VC state machine of the reset
432 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
434 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
435 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
444 * Signalling manager state machine action 6
446 * SSCF session on signalling channel has been lost
449 * usp pointer to the UNISIG protocol control block
450 * m buffer pointer (may be NULL)
454 * errno error encountered
458 unisig_sigmgr_act06(struct unisig *usp, KBuffer *m)
460 struct unisig_vccb *uvp, *vnext;
463 * Log the fact that the session has been lost
465 log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
468 * Notify the VC state machine of the loss
470 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
472 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
473 unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
478 * Try to restart the SSCF session
480 unisig_sigmgr_act04(usp, NULL);
485 usp->us_state = UNISIG_INIT;
492 * Signalling manager state machine action 7
494 * A Q.2931 signalling message has been received
497 * usp pointer to the UNISIG protocol control block
498 * m buffer pointer (may be NULL)
502 * errno error encountered
506 unisig_sigmgr_act07(struct unisig *usp, KBuffer *m)
511 * Pass the Q.2931 signalling message on
512 * to the VC state machine
514 err = unisig_rcv_msg(usp, m);
521 * Signalling manager state machine action 8
523 * Process a CALL_CLOSED event for the signalling PVC
526 * usp pointer to the UNISIG protocol control block
527 * m buffer pointer (may be NULL)
531 * errno error encountered
535 unisig_sigmgr_act08(struct unisig *usp, KBuffer *m)
539 * Signalling manager is now incommunicado
541 if (usp->us_state != UNISIG_DETACH) {
543 * Log an error and set the state to NULL if
544 * we're not detaching
546 log(LOG_ERR, "unisig: signalling channel closed\n");
547 usp->us_state = UNISIG_NULL;
556 * Signalling manager state machine action 9
561 * usp pointer to the UNISIG protocol control block
562 * m buffer pointer (may be NULL)
566 * errno error encountered
570 unisig_sigmgr_act09(struct unisig *usp, KBuffer *m)
572 log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
580 * Signalling manager state machine action 10
585 * usp pointer to the UNISIG protocol control block
586 * m buffer pointer (may be NULL)
590 * errno error encountered
594 unisig_sigmgr_act10(struct unisig *usp, KBuffer *m)
601 * Signalling manager state machine action 11
606 * usp pointer to the UNISIG protocol control block
607 * m buffer pointer (may be NULL)
611 * errno error encountered
615 unisig_sigmgr_act11(struct unisig *usp, KBuffer *m)
617 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
625 * Signalling manager state machine action 12
630 * usp pointer to the UNISIG protocol control block
631 * m buffer pointer (may be NULL)
635 * errno error encountered
639 unisig_sigmgr_act12(struct unisig *usp, KBuffer *m)
641 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
649 * Signalling manager state machine action 13
651 * NSAP prefix has been set
654 * usp pointer to the UNISIG protocol control block
655 * m buffer pointer (may be NULL)
659 * errno error encountered
663 unisig_sigmgr_act13(struct unisig *usp, KBuffer *m)
669 * Set UNI signalling channel connection attributes
671 if (usp->us_proto == ATM_SIG_UNI30)
672 unisig_attr.api_init = UNI_VERS_3_0;
674 unisig_attr.api_init = UNI_VERS_3_1;
676 unisig_attr.nif = usp->us_pif->pif_nif;
678 unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
679 unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
680 unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
682 unisig_attr.called.tag = T_ATM_PRESENT;
683 unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
684 unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
685 pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
686 ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
687 ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
688 unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
689 unisig_attr.called.subaddr.address_length = 0;
691 unisig_attr.traffic.v.forward.PCR_all_traffic =
692 usp->us_pif->pif_pcr;
693 unisig_attr.traffic.v.backward.PCR_all_traffic =
694 usp->us_pif->pif_pcr;
697 * Create UNISIG signalling channel
699 err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
706 * Establish the SSCF session
708 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
710 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
715 usp->us_state = UNISIG_INIT;
722 * Signalling manager state machine action 14
724 * Process a detach event
727 * usp pointer to the UNISIG protocol control block
728 * m buffer pointer (may be NULL)
732 * errno error encountered
736 unisig_sigmgr_act14(struct unisig *usp, KBuffer *m)
739 struct unisig_vccb *sig_vccb, *uvp, *vnext;
741 struct t_atm_cause cause;
744 * Locate the signalling channel's VCCB
747 if (usp->us_conn && usp->us_conn->co_connvc)
748 sig_vccb = (struct unisig_vccb *)
749 usp->us_conn->co_connvc->cvc_vcc;
752 * Terminate all of our VCCs
754 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
756 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
759 * Don't close the signalling VCC yet
765 * Close VCC and notify owner
767 err = unisig_clear_vcc(usp, uvp,
768 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
772 * Close the signalling channel
775 cause.coding_standard = T_ATM_ITU_CODING;
776 cause.coding_standard = T_ATM_LOC_USER;
777 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
778 err = atm_cm_release(usp->us_conn, &cause);
780 panic("unisig_sigmgr_act14: close failed");
784 * Get rid of protocol instance if there are no VCCs queued
787 if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
789 struct sigmgr *smp = pip->pif_sigmgr;
792 pip->pif_sigmgr = NULL;
793 pip->pif_siginst = NULL;
796 UNLINK((struct siginst *)usp, struct siginst,
797 smp->sm_prinst, si_next);
798 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
801 * Otherwise, set new signalling manager state and
802 * wait for protocol instance to be freed during
803 * unisig_free processing for the last queued VCC
805 usp->us_state = UNISIG_DETACH;