2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
27 * SPANS Signalling Manager
28 * ---------------------------
30 * SPANS protocol processing module.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/syslog.h>
42 #include <sys/kernel.h>
43 #include <sys/sysctl.h>
45 #include <netinet/in.h>
46 #include <netatm/port.h>
47 #include <netatm/queue.h>
48 #include <netatm/atm.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_sap.h>
51 #include <netatm/atm_cm.h>
52 #include <netatm/atm_if.h>
53 #include <netatm/atm_vc.h>
54 #include <netatm/atm_sigmgr.h>
55 #include <netatm/atm_stack.h>
56 #include <netatm/atm_pcb.h>
57 #include <netatm/atm_var.h>
59 #include "spans_xdr.h"
60 #include <netatm/spans/spans_var.h>
65 caddr_t spans_getname(void *);
66 void spans_connected(void *);
67 void spans_cleared(void *, struct t_atm_cause *);
68 void spans_cpcs_data(void *, KBuffer *);
72 * ATM endpoint for SPANS signalling channel
74 static Atm_endpoint spans_endpt = {
76 ENDPT_SPANS_SIG, /* ep_id */
78 spans_getname, /* ep_getname */
79 spans_connected, /* ep_connected */
80 spans_cleared, /* ep_cleared */
81 NULL, /* ep_incoming */
82 NULL, /* ep_addparty */
83 NULL, /* ep_dropparty */
84 NULL, /* ep_cpcs_ctl */
85 spans_cpcs_data, /* ep_cpcs_data */
86 NULL, /* ep_saal_ctl */
87 NULL, /* ep_saal_data */
88 NULL, /* ep_sscop_ctl */
89 NULL /* ep_sscop_data */
94 * ATM connection attributes for UNI signalling channel
96 static Atm_attributes spans_attr = {
103 T_ATM_PRESENT, /* aal.tag */
104 ATM_AAL3_4 /* aal.aal_type */
107 T_ATM_PRESENT, /* traffic.tag */
109 { /* traffic.v.forward */
110 T_ATM_ABSENT, /* PCR_high */
112 T_ATM_ABSENT, /* SCR_high */
113 T_ATM_ABSENT, /* SCR_all */
114 T_ATM_ABSENT, /* MBS_high */
115 T_ATM_ABSENT, /* MBS_all */
118 { /* traffic.v.backward */
119 T_ATM_ABSENT, /* PCR_high */
121 T_ATM_ABSENT, /* SCR_high */
122 T_ATM_ABSENT, /* SCR_all */
123 T_ATM_ABSENT, /* MBS_high */
124 T_ATM_ABSENT, /* MBS_all */
127 T_YES, /* best_effort */
131 T_ATM_PRESENT, /* bearer.tag */
133 T_ATM_CLASS_X, /* class */
134 T_ATM_NULL, /* traffic_type */
135 T_ATM_NO_END_TO_END, /* timing_req */
137 T_ATM_1_TO_1, /* conn_conf */
141 T_ATM_ABSENT, /* bhli.tag */
144 T_ATM_ABSENT, /* blli.tag_l2 */
145 T_ATM_ABSENT, /* blli.tag_l3 */
148 T_ATM_ABSENT, /* llc.tag */
151 T_ATM_PRESENT, /* called.tag */
154 T_ATM_ABSENT, /* calling.tag */
157 T_ATM_PRESENT, /* qos.tag */
159 T_ATM_NETWORK_CODING, /* coding_standard */
160 { /* qos.v.forward */
161 T_ATM_QOS_CLASS_0, /* class */
163 { /* qos.v.backward */
164 T_ATM_QOS_CLASS_0, /* class */
169 T_ATM_ABSENT, /* transit.tag */
172 T_ATM_ABSENT, /* cause.tag */
178 * SPANS cause structre
180 struct t_atm_cause spans_cause = {
181 T_ATM_ITU_CODING, /* coding_standard */
182 T_ATM_LOC_USER, /* location */
183 T_ATM_CAUSE_UNSPECIFIED_NORMAL, /* cause_value */
184 { 0, 0, 0, 0 } /* diagnostics */
187 SYSCTL_NODE(_net_harp, OID_AUTO, spans, CTLFLAG_RW, 0, "spans");
190 * Process a SPANS timeout
192 * Called when a previously scheduled spans control block timer expires.
193 * Processing will based on the current SPANS state.
198 * tip pointer to spans timer control block
206 struct atm_time *tip;
214 * Back-off to SPANS control block
216 spp = (struct spans *)
217 ((caddr_t)tip - (int)(&((struct spans *)0)->sp_time));
219 ATM_DEBUG2("spans_timer: spp=%p,state=%d\n",
223 * Process timeout based on protocol state
225 switch (spp->sp_state) {
230 * Open signalling channel
232 spans_attr.nif = spp->sp_pif->pif_nif;
234 spans_attr.aal.v.aal4.forward_max_SDU_size =
236 spans_attr.aal.v.aal4.backward_max_SDU_size =
238 spans_attr.aal.v.aal4.SSCS_type =
239 T_ATM_SSCS_SSCOP_UNREL;
240 spans_attr.aal.v.aal4.mid_low = 0;
241 spans_attr.aal.v.aal4.mid_high = 0;
243 spans_attr.called.tag = T_ATM_PRESENT;
244 spans_attr.called.addr.address_format = T_ATM_PVC_ADDR;
245 spans_attr.called.addr.address_length =
246 sizeof(Atm_addr_pvc);
247 pvcp = (Atm_addr_pvc *)spans_attr.called.addr.address;
248 ATM_PVC_SET_VPI(pvcp, SPANS_SIG_VPI);
249 ATM_PVC_SET_VCI(pvcp, SPANS_SIG_VCI);
250 spans_attr.called.subaddr.address_format = T_ATM_ABSENT;
251 spans_attr.called.subaddr.address_length = 0;
253 spans_attr.traffic.v.forward.PCR_all_traffic =
254 spp->sp_pif->pif_pcr;
255 spans_attr.traffic.v.backward.PCR_all_traffic =
256 spp->sp_pif->pif_pcr;
258 err = atm_cm_connect(&spans_endpt, spp, &spans_attr,
261 log(LOG_CRIT, "spans: signalling channel setup failed\n");
266 * Signalling channel open, start probing
268 spp->sp_state = SPANS_PROBE;
276 * Send out SPANS_STAT_REQ message
278 msg = uma_zalloc(spans_msg_zone, M_WAITOK);
280 /* XXX arr: This is bogus and will go away RSN */
281 /* Retry later if no memory */
282 SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
285 msg->sm_vers = SPANS_VERS_1_0;
286 msg->sm_type = SPANS_STAT_REQ;
287 msg->sm_stat_req.streq_es_epoch = spp->sp_h_epoch;
288 if (spans_send_msg(spp, msg)) {
289 /* Retry later if send fails */
290 SPANS_TIMER(spp, SPANS_PROBE_ERR_WAIT);
291 uma_zfree(spans_msg_zone, msg);
294 uma_zfree(spans_msg_zone, msg);
298 * Check whether we're getting an answer to our probes
300 if (spp->sp_state == SPANS_ACTIVE &&
301 spp->sp_probe_ct > SPANS_PROBE_THRESH) {
303 * Interface is down, notify VCC owners
305 spans_switch_reset(spp, SPANS_UNI_DOWN);
308 * Set new state and increment host epoch so
309 * switch knows we reset everyting.
311 spp->sp_state = SPANS_PROBE;
317 * Keep sending status requests
319 SPANS_TIMER(spp, SPANS_PROBE_INTERVAL);
325 * Try to terminate the SPANS signalling PVC
327 err = atm_cm_release(spp->sp_conn, &spans_cause);
329 log(LOG_ERR, "spans: can't close signalling channel\n");
334 log(LOG_ERR, "spans: timer state: spp=%p, state=%d\n",
341 * Process a SPANS VCC timeout
343 * Called when a previously scheduled SPANS VCCB timer expires.
344 * Processing will based on the current VCC state.
349 * tip pointer to vccb timer control block
357 struct atm_time *tip;
361 struct spans_vccb *svp;
364 * Get VCCB and SPANS control block addresses
366 svp = (struct spans_vccb *) ((caddr_t)tip -
367 (int)(&((struct vccb *)0)->vc_time));
368 spp = (struct spans *)svp->sv_pif->pif_siginst;
370 ATM_DEBUG3("spans_vctimer: svp=%p, sstate=%d, ustate=%d\n",
371 svp, svp->sv_sstate, svp->sv_ustate);
374 * Process timeout based on protocol state
376 switch (svp->sv_sstate) {
380 * Kill the VCCB and notify the owner
382 err = spans_clear_vcc(spp, svp);
389 svp->sv_ustate = VCCU_CLOSED;
390 svp->sv_sstate = SPANS_VC_FREE;
391 spans_free((struct vccb *)svp);
396 * Issued open request, but didn't get response.
398 if (svp->sv_retry < SV_MAX_RETRY) {
400 * Retransmit the open request
402 err = spans_send_open_req(spp, svp);
404 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
407 * Retry limit exceeded--report the open failed
409 svp->sv_ustate = VCCU_CLOSED;
410 svp->sv_sstate = SPANS_VC_FREE;
411 svp->sv_connvc->cvc_attr.cause.tag =
413 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
415 svp->sv_connvc->cvc_attr.cause.v.location =
417 svp->sv_connvc->cvc_attr.cause.v.cause_value =
418 T_ATM_CAUSE_NO_USER_RESPONDING;
419 bzero(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
420 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
421 atm_cm_cleared(svp->sv_connvc);
427 * Issued close request, but didn't get response.
429 if (svp->sv_retry < SV_MAX_RETRY) {
431 * Retransmit the close request
433 err = spans_send_close_req(spp, svp);
435 SPANS_VC_TIMER((struct vccb *) svp, SV_TIMEOUT);
438 * Retry limit exceeded--just finish the close
440 svp->sv_sstate = SPANS_VC_FREE;
441 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
442 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
444 svp->sv_connvc->cvc_attr.cause.v.location =
446 svp->sv_connvc->cvc_attr.cause.v.cause_value =
447 T_ATM_CAUSE_NO_USER_RESPONDING;
448 bzero(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
449 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
450 atm_cm_cleared(svp->sv_connvc);
454 case SPANS_VC_ACTIVE:
455 case SPANS_VC_ACT_DOWN:
459 log(LOG_ERR, "spans_vctimer: unexpected state %d\n",
464 log(LOG_ERR, "spans: vctimer state: svp=%p, sstate=%d\n",
465 svp, svp->sv_sstate);
474 * tok SPANS signalling channel token (ignored)
477 * pointer to a string identifying the SPANS signalling manager
489 * Process a VCC connection notification
491 * Should never be called
494 * tok user's connection token (SPANS protocol block)
504 struct spans *spp = (struct spans *)tok;
506 ATM_DEBUG2("spans_connected: spp=%p,state=%d\n",
510 * Connected routine shouldn't ever get called for a PVC
512 log(LOG_ERR, "spans: connected function called, tok=%p\n", spp);
517 * Process a VCC close notification
519 * Called when the SPANS signalling channel is closed
522 * tok user's connection token (spans protocol block)
523 * cp pointer to cause structure
530 spans_cleared(tok, cp)
532 struct t_atm_cause *cp;
534 struct spans *spp = (struct spans *)tok;
537 * VCC has been closed.
539 log(LOG_ERR, "spans: signalling channel closed\n");
546 * SPANS CPCS data handler
548 * This is the module which receives data on the SPANS signalling
549 * channel. Processing is based on the indication received from the
550 * AAL and the protocol state.
553 * tok session token (pointer to spans protocol control block)
554 * m pointer to buffer with data
561 spans_cpcs_data(tok, m)
565 struct spans *spp = tok;
567 ATM_DEBUG3("spans_cpcs_data: spp=%p,state=%d,m=%p,\n",
568 spp, spp->sp_state, m);
573 spans_rcv_msg(spp, m);