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>
42 #include "unisig_var.h"
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 *);
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 (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(struct unisig *usp, int event, KBuffer *m)
230 * Cancel any signalling manager timer
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);
255 * Signalling manager state machine action 0
260 * usp pointer to the UNISIG protocol control block
261 * m buffer pointer (may be NULL)
265 * errno error encountered
269 unisig_sigmgr_invalid(struct unisig *usp, KBuffer *m)
271 log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
279 * Signalling manager state machine action 1
281 * The kickoff timer has expired at attach time; go to
282 * UNISIG_ADDR_WAIT state.
285 * usp pointer to the UNISIG protocol control block
286 * m buffer pointer (may be NULL)
290 * errno error encountered
294 unisig_sigmgr_act01(struct unisig *usp, KBuffer *m)
299 usp->us_state = UNISIG_ADDR_WAIT;
306 * Signalling manager state machine action 2
311 * usp pointer to the UNISIG protocol control block
312 * m buffer pointer (may be NULL)
316 * errno error encountered
320 unisig_sigmgr_act02(struct unisig *usp, KBuffer *m)
323 * Ignore event, discard message if present
333 * Signalling manager state machine action 3
335 * SSCF session on signalling channel has come up
338 * usp pointer to the UNISIG protocol control block
339 * m buffer pointer (may be NULL)
343 * errno error encountered
347 unisig_sigmgr_act03(struct unisig *usp, KBuffer *m)
349 struct unisig_vccb *uvp, *vnext;
354 log(LOG_INFO, "unisig: signalling channel active\n");
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);
366 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
367 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
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.
382 * usp pointer to the UNISIG protocol control block
383 * m buffer pointer (may be NULL)
387 * errno error encountered
391 unisig_sigmgr_act04(struct unisig *usp, KBuffer *m)
396 * Try to establish an SSCF session.
398 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
400 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
407 * Signalling manager state machine action 5
409 * SSCF session on signalling channel has been reset
412 * usp pointer to the UNISIG protocol control block
413 * m buffer pointer (may be NULL)
417 * errno error encountered
421 unisig_sigmgr_act05(struct unisig *usp, KBuffer *m)
423 struct unisig_vccb *uvp, *vnext;
428 log(LOG_INFO, "unisig: signalling channel reset\n");
431 * Notify the VC state machine of the reset
433 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
435 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
436 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
445 * Signalling manager state machine action 6
447 * SSCF session on signalling channel has been lost
450 * usp pointer to the UNISIG protocol control block
451 * m buffer pointer (may be NULL)
455 * errno error encountered
459 unisig_sigmgr_act06(struct unisig *usp, KBuffer *m)
461 struct unisig_vccb *uvp, *vnext;
464 * Log the fact that the session has been lost
466 log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
469 * Notify the VC state machine of the loss
471 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
473 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
474 unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
479 * Try to restart the SSCF session
481 unisig_sigmgr_act04(usp, NULL);
486 usp->us_state = UNISIG_INIT;
493 * Signalling manager state machine action 7
495 * A Q.2931 signalling message has been received
498 * usp pointer to the UNISIG protocol control block
499 * m buffer pointer (may be NULL)
503 * errno error encountered
507 unisig_sigmgr_act07(struct unisig *usp, KBuffer *m)
512 * Pass the Q.2931 signalling message on
513 * to the VC state machine
515 err = unisig_rcv_msg(usp, m);
522 * Signalling manager state machine action 8
524 * Process a CALL_CLOSED event for the signalling PVC
527 * usp pointer to the UNISIG protocol control block
528 * m buffer pointer (may be NULL)
532 * errno error encountered
536 unisig_sigmgr_act08(struct unisig *usp, KBuffer *m)
540 * Signalling manager is now incommunicado
542 if (usp->us_state != UNISIG_DETACH) {
544 * Log an error and set the state to NULL if
545 * we're not detaching
547 log(LOG_ERR, "unisig: signalling channel closed\n");
548 usp->us_state = UNISIG_NULL;
557 * Signalling manager state machine action 9
562 * usp pointer to the UNISIG protocol control block
563 * m buffer pointer (may be NULL)
567 * errno error encountered
571 unisig_sigmgr_act09(struct unisig *usp, KBuffer *m)
573 log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
581 * Signalling manager state machine action 10
586 * usp pointer to the UNISIG protocol control block
587 * m buffer pointer (may be NULL)
591 * errno error encountered
595 unisig_sigmgr_act10(struct unisig *usp, KBuffer *m)
602 * Signalling manager state machine action 11
607 * usp pointer to the UNISIG protocol control block
608 * m buffer pointer (may be NULL)
612 * errno error encountered
616 unisig_sigmgr_act11(struct unisig *usp, KBuffer *m)
618 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
626 * Signalling manager state machine action 12
631 * usp pointer to the UNISIG protocol control block
632 * m buffer pointer (may be NULL)
636 * errno error encountered
640 unisig_sigmgr_act12(struct unisig *usp, KBuffer *m)
642 log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
650 * Signalling manager state machine action 13
652 * NSAP prefix has been set
655 * usp pointer to the UNISIG protocol control block
656 * m buffer pointer (may be NULL)
660 * errno error encountered
664 unisig_sigmgr_act13(struct unisig *usp, KBuffer *m)
670 * Set UNI signalling channel connection attributes
672 if (usp->us_proto == ATM_SIG_UNI30)
673 unisig_attr.api_init = UNI_VERS_3_0;
675 unisig_attr.api_init = UNI_VERS_3_1;
677 unisig_attr.nif = usp->us_pif->pif_nif;
679 unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
680 unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
681 unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
683 unisig_attr.called.tag = T_ATM_PRESENT;
684 unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
685 unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
686 pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
687 ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
688 ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
689 unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
690 unisig_attr.called.subaddr.address_length = 0;
692 unisig_attr.traffic.v.forward.PCR_all_traffic =
693 usp->us_pif->pif_pcr;
694 unisig_attr.traffic.v.backward.PCR_all_traffic =
695 usp->us_pif->pif_pcr;
698 * Create UNISIG signalling channel
700 err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
707 * Establish the SSCF session
709 err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
711 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
716 usp->us_state = UNISIG_INIT;
723 * Signalling manager state machine action 14
725 * Process a detach event
728 * usp pointer to the UNISIG protocol control block
729 * m buffer pointer (may be NULL)
733 * errno error encountered
737 unisig_sigmgr_act14(struct unisig *usp, KBuffer *m)
740 struct unisig_vccb *sig_vccb, *uvp, *vnext;
742 struct t_atm_cause cause;
745 * Locate the signalling channel's VCCB
748 if (usp->us_conn && usp->us_conn->co_connvc)
749 sig_vccb = (struct unisig_vccb *)
750 usp->us_conn->co_connvc->cvc_vcc;
753 * Terminate all of our VCCs
755 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
757 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
760 * Don't close the signalling VCC yet
766 * Close VCC and notify owner
768 err = unisig_clear_vcc(usp, uvp,
769 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
773 * Close the signalling channel
776 cause.coding_standard = T_ATM_ITU_CODING;
777 cause.coding_standard = T_ATM_LOC_USER;
778 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
779 err = atm_cm_release(usp->us_conn, &cause);
781 panic("unisig_sigmgr_act14: close failed\n");
785 * Get rid of protocol instance if there are no VCCs queued
788 if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
790 struct sigmgr *smp = pip->pif_sigmgr;
793 pip->pif_sigmgr = NULL;
794 pip->pif_siginst = NULL;
797 UNLINK((struct siginst *)usp, struct siginst,
798 smp->sm_prinst, si_next);
799 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
802 * Otherwise, set new signalling manager state and
803 * wait for protocol instance to be freed during
804 * unisig_free processing for the last queued VCC
806 usp->us_state = UNISIG_DETACH;