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
,
368 (struct unisig_msg
*) 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.
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
,
402 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
409 * Signalling manager state machine action 5
411 * SSCF session on signalling channel has been reset
414 * usp pointer to the UNISIG protocol control block
415 * m buffer pointer (may be NULL)
419 * errno error encountered
423 unisig_sigmgr_act05(struct unisig
*usp
, KBuffer
*m
)
425 struct unisig_vccb
*uvp
, *vnext
;
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
);
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);
447 * Signalling manager state machine action 6
449 * SSCF session on signalling channel has been lost
452 * usp pointer to the UNISIG protocol control block
453 * m buffer pointer (may be NULL)
457 * errno error encountered
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
);
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);
488 usp
->us_state
= UNISIG_INIT
;
495 * Signalling manager state machine action 7
497 * A Q.2931 signalling message has been received
500 * usp pointer to the UNISIG protocol control block
501 * m buffer pointer (may be NULL)
505 * errno error encountered
509 unisig_sigmgr_act07(struct unisig
*usp
, KBuffer
*m
)
514 * Pass the Q.2931 signalling message on
515 * to the VC state machine
517 err
= unisig_rcv_msg(usp
, m
);
524 * Signalling manager state machine action 8
526 * Process a CALL_CLOSED event for the signalling PVC
529 * usp pointer to the UNISIG protocol control block
530 * m buffer pointer (may be NULL)
534 * errno error encountered
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
;
559 * Signalling manager state machine action 9
564 * usp pointer to the UNISIG protocol control block
565 * m buffer pointer (may be NULL)
569 * errno error encountered
573 unisig_sigmgr_act09(struct unisig
*usp
, KBuffer
*m
)
575 log(LOG_ERR
, "unisig_sigmgr_act09: unexpected action\n");
583 * Signalling manager state machine action 10
588 * usp pointer to the UNISIG protocol control block
589 * m buffer pointer (may be NULL)
593 * errno error encountered
597 unisig_sigmgr_act10(struct unisig
*usp
, KBuffer
*m
)
604 * Signalling manager state machine action 11
609 * usp pointer to the UNISIG protocol control block
610 * m buffer pointer (may be NULL)
614 * errno error encountered
618 unisig_sigmgr_act11(struct unisig
*usp
, KBuffer
*m
)
620 log(LOG_ERR
, "unisig_sigmgr_act11: unexpected action\n");
628 * Signalling manager state machine action 12
633 * usp pointer to the UNISIG protocol control block
634 * m buffer pointer (may be NULL)
638 * errno error encountered
642 unisig_sigmgr_act12(struct unisig
*usp
, KBuffer
*m
)
644 log(LOG_ERR
, "unisig_sigmgr_act11: unexpected action\n");
652 * Signalling manager state machine action 13
654 * NSAP prefix has been set
657 * usp pointer to the UNISIG protocol control block
658 * m buffer pointer (may be NULL)
662 * errno error encountered
666 unisig_sigmgr_act13(struct unisig
*usp
, KBuffer
*m
)
672 * Set UNI signalling channel connection attributes
674 if (usp
->us_proto
== ATM_SIG_UNI30
)
675 unisig_attr
.api_init
= UNI_VERS_3_0
;
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
,
709 * Establish the SSCF session
711 err
= atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ
,
715 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
720 usp
->us_state
= UNISIG_INIT
;
727 * Signalling manager state machine action 14
729 * Process a detach event
732 * usp pointer to the UNISIG protocol control block
733 * m buffer pointer (may be NULL)
737 * errno error encountered
741 unisig_sigmgr_act14(struct unisig
*usp
, KBuffer
*m
)
744 struct unisig_vccb
*sig_vccb
, *uvp
, *vnext
;
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
);
761 vnext
= Q_NEXT(uvp
, struct unisig_vccb
, uv_sigelem
);
764 * Don't close the signalling VCC yet
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
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
);
785 panic("unisig_sigmgr_act14: close failed\n");
789 * Get rid of protocol instance if there are no VCCs queued
792 if (Q_HEAD(usp
->us_vccq
, struct vccb
) == NULL
&&
794 struct sigmgr
*smp
= pip
->pif_sigmgr
;
797 pip
->pif_sigmgr
= NULL
;
798 pip
->pif_siginst
= NULL
;
801 UNLINK((struct siginst
*)usp
, struct siginst
,
802 smp
->sm_prinst
, si_next
);
803 KM_FREE(usp
, sizeof(struct unisig
), M_DEVBUF
);
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
;