Bring in a transport-independent RPC (TI-RPC).
[dragonfly.git] / sys / netproto / atm / spans / spans_msg.c
blob1f8993537574eb30d5d1878758b9a740070de83e
1 /*
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/spans/spans_msg.c,v 1.5 1999/08/28 00:48:50 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_msg.c,v 1.7 2006/12/22 23:57:54 swildner Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS signalling message processing.
38 #include <netproto/atm/kern_include.h>
40 #include "spans_xdr.h"
41 #include "spans_var.h"
44 * External functions
46 void xdrmbuf_init (XDR *, KBuffer *, enum xdr_op);
49 * Local functions
51 static void spans_host_link (struct spans *, long);
52 static void spans_status_ind (struct spans *, spans_msg *);
53 static void spans_status_rsp (struct spans *, spans_msg *);
54 static void spans_open_req (struct spans *, spans_msg *);
55 static void spans_open_rsp (struct spans *, spans_msg *);
56 static void spans_close_req (struct spans *, spans_msg *);
57 static void spans_close_rsp (struct spans *, spans_msg *);
58 static void spans_multi_req (struct spans *, spans_msg *);
59 static void spans_add_req (struct spans *, spans_msg *);
60 static void spans_join_req (struct spans *, spans_msg *);
61 static void spans_leave_req (struct spans *, spans_msg *);
62 static void spans_vcir_ind (struct spans *, spans_msg *);
63 static void spans_query_req (struct spans *, spans_msg *);
67 * Called to set status when a status message comes in from a host
68 * connected back-to-back with us. Check the epoch and, if it has
69 * changed, set the appropriate state and save updated state
70 * information.
72 * Arguments:
73 * spp pointer to SPANS protocol instance block
74 * host_epoch epoch of host at far end of link
76 * Returns:
77 * 0 message sent OK
78 * errno error encountered
81 static void
82 spans_host_link(struct spans *spp, long host_epoch)
84 struct atm_pif *pip = spp->sp_pif;
87 * There's a host at the other end of the link. If its
88 * epoch has changed, clean up our state and save the
89 * new information.
91 if (spp->sp_s_epoch != host_epoch) {
92 spp->sp_s_epoch = host_epoch;
93 spans_switch_reset(spp, SPANS_UNI_UP);
94 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
95 spp->sp_addr.address_length = sizeof(spans_addr);
96 KM_COPY(&pip->pif_macaddr.ma_data[2],
97 &spp->sp_addr.address[4],
98 4);
99 log(LOG_INFO,
100 "spans: using SPANS address of %s on interface %s%d\n",
101 spans_addr_print((spans_addr *)spp->sp_addr.address),
102 pip->pif_name,
103 pip->pif_unit);
108 * Send a SPANS signalling message
110 * Called to send a SPANS message. This routine gets a buffer, performs
111 * XDR processing, and hands the message to the AAL for transmission.
113 * Arguments:
114 * spp pointer to SPANS protocol instance block
115 * msg pointer to status message
117 * Returns:
118 * 0 message sent OK
119 * errno error encountered
123 spans_send_msg(struct spans *spp, spans_msg *msg)
125 int err = 0;
126 KBuffer *m;
127 XDR xdrs;
129 #ifdef NOTDEF
130 ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
131 msg->sm_type);
132 if (msg->sm_type != SPANS_STAT_REQ &&
133 msg->sm_type != SPANS_STAT_IND &&
134 msg->sm_type != SPANS_STAT_RSP) {
135 kprintf("spans_send_msg: sending ");
136 spans_print_msg(msg);
138 #endif
141 * If the signalling channel has been closed, don't do anything
143 if (!spp->sp_conn)
144 return(ECONNABORTED);
147 * Get a buffer
149 KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
150 if (m == NULL) {
151 /* No buffer available */
152 return(ENOBUFS);
156 * Convert message to network order
158 KB_LEN(m) = KB_BFRLEN(m);
159 xdrmbuf_init(&xdrs, m, XDR_ENCODE);
160 if (!xdr_spans_msg(&xdrs, msg)) {
161 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
162 KB_LEN(m) = XDR_GETPOS(&xdrs);
163 spans_dump_buffer(m);
164 KB_FREEALL(m);
165 return(EIO);
167 KB_LEN(m) = XDR_GETPOS(&xdrs);
170 * Send the message
172 err = atm_cm_cpcs_data(spp->sp_conn, m);
173 if (err)
174 KB_FREEALL(m);
176 return(err);
181 * Send an open request
183 * Build and send an open request.
185 * Arguments:
186 * spp pointer to SPANS protocol instance block
187 * svp pointer to VCCB for which the request is being sent
189 * Returns:
190 * none
194 spans_send_open_req(struct spans *spp, struct spans_vccb *svp)
196 spans_msg *req;
197 int err = 0;
199 ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
202 * Get memory for a request message
204 req = (spans_msg *)atm_allocate(&spans_msgpool);
205 if (req == NULL) {
206 err = ENOBUFS;
207 goto done;
211 * Fill in the request
213 req->sm_vers = SPANS_VERS_1_0;
214 req->sm_type = SPANS_OPEN_REQ;
215 req->sm_open_req.opreq_conn = svp->sv_conn;
216 req->sm_open_req.opreq_aal = svp->sv_spans_aal;
217 req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
218 req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
219 req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
220 req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
221 req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
224 * Send the request
226 err = spans_send_msg(spp, req);
227 atm_free(req);
229 done:
230 return(err);
235 * Send an open response
237 * Build and send a response to an open request or open indication.
239 * Arguments:
240 * spp pointer to SPANS protocol instance block
241 * svp pointer to VCCB for which the response is being sent
242 * result result code to include in the response
244 * Returns:
245 * none
249 spans_send_open_rsp(struct spans *spp, struct spans_vccb *svp,
250 spans_result result)
252 spans_msg *rsp;
253 int rc;
255 ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
256 result);
259 * Get memory for a response message
261 rsp = (spans_msg *)atm_allocate(&spans_msgpool);
262 if (rsp == NULL)
263 return(ENOBUFS);
266 * Fill in the response
268 rsp->sm_vers = SPANS_VERS_1_0;
269 rsp->sm_type = SPANS_OPEN_RSP;
270 rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
271 rsp->sm_open_rsp.oprsp_result = result;
272 rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
273 rsp->sm_open_rsp.oprsp_vpvc =
274 SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
277 * Send the response
279 rc = spans_send_msg(spp, rsp);
280 atm_free(rsp);
282 return(rc);
287 * Send a close request
289 * Called to send a close request.
291 * Arguments:
292 * spp pointer to SPANS protocol instance block
293 * svp pointer to VCCB for which the close is being sent
295 * Returns:
296 * none
300 spans_send_close_req(struct spans *spp, struct spans_vccb *svp)
302 spans_msg *req;
303 int err = 0;
305 ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
308 * Get memory for a close request
310 req = (spans_msg *)atm_allocate(&spans_msgpool);
311 if (req == NULL) {
312 err = ENOBUFS;
313 goto done;
317 * Fill in the request
319 req->sm_vers = SPANS_VERS_1_0;
320 if (svp->sv_type & VCC_OUT) {
321 req->sm_type = SPANS_CLOSE_REQ;
322 } else if (svp->sv_type & VCC_IN) {
323 req->sm_type = SPANS_RCLOSE_REQ;
324 } else {
325 err = EINVAL;
326 ATM_DEBUG1(
327 "spans_send_close_req: invalid VCCB type 0x%x\n",
328 svp->sv_type);
329 goto done;
331 req->sm_close_req.clreq_conn = svp->sv_conn;
334 * Send the close request
336 err = spans_send_msg(spp, req);
338 done:
339 if (req)
340 atm_free(req);
342 return(err);
348 * Process a status indication or status request
350 * Called when a status indication or status request is received.
351 * Processing will be based on the current SPANS state.
353 * Arguments:
354 * spp pointer to SPANS protocol instance block
355 * msg pointer to the status message
357 * Returns:
358 * none
361 static void
362 spans_status_ind(struct spans *spp, spans_msg *msg)
364 spans_msg *rsp_msg;
365 struct atm_pif *pip = spp->sp_pif;
368 * Reset the probe count.
370 spp->sp_probe_ct = 0;
372 switch (spp->sp_state) {
373 case SPANS_PROBE:
375 * Interface just came up, update signalling state
377 spp->sp_state = SPANS_ACTIVE;
378 break;
380 case SPANS_ACTIVE:
381 break;
383 default:
384 log(LOG_ERR, "spans: received status msg in state %d\n",
385 spp->sp_state);
389 * Process the message
391 switch (msg->sm_type) {
393 case SPANS_STAT_REQ:
395 * Handle a request from a host at the other end of
396 * the link.
398 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
399 break;
401 case SPANS_STAT_IND:
404 * There's a switch at the other end of the link. If
405 * its epoch has changed, reset the SPANS state and save
406 * the new information.
408 if (spp->sp_s_epoch !=
409 msg->sm_stat_ind.stind_sw_epoch) {
410 spans_switch_reset(spp, SPANS_UNI_UP);
411 spp->sp_s_epoch =
412 msg->sm_stat_ind.stind_sw_epoch;
413 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
414 spp->sp_addr.address_length =
415 sizeof(spans_addr);
416 spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
417 spp->sp_addr.address);
418 log(LOG_INFO,
419 "spans: received SPANS address %s from switch for interface %s%d\n",
420 spans_addr_print((spans_addr *)spp->sp_addr.address),
421 pip->pif_name,
422 pip->pif_unit);
424 break;
426 default:
427 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
428 msg->sm_type);
429 return;
433 * Respond to the status request or indication with a
434 * status response
436 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
437 if (rsp_msg == NULL)
438 return;
439 rsp_msg->sm_vers = SPANS_VERS_1_0;
440 rsp_msg->sm_type = SPANS_STAT_RSP;
441 rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
442 spans_addr_copy(spp->sp_addr.address,
443 &rsp_msg->sm_stat_rsp.strsp_es_addr);
444 spans_send_msg(spp, rsp_msg);
445 atm_free(rsp_msg);
451 * Process a status response
453 * Called when a status response is received.
454 * Processing will be based on the current SPANS state.
456 * Arguments:
457 * spp pointer to SPANS protocol instance block
458 * msg pointer to the status response message
460 * Returns:
461 * none
464 static void
465 spans_status_rsp(struct spans *spp, spans_msg *msg)
469 * Reset the probe count.
471 spp->sp_probe_ct = 0;
473 switch (spp->sp_state) {
474 case SPANS_PROBE:
476 * Interface just came up, update signalling state
478 spp->sp_state = SPANS_ACTIVE;
479 break;
481 case SPANS_ACTIVE:
482 break;
484 default:
485 log(LOG_ERR, "spans: received status msg in state %d\n",
486 spp->sp_state);
490 * Process the message
492 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
497 * Process an open indication or open request
499 * Called when an open indication or open request is received.
500 * Processing will be based on the state of the requested connection.
502 * Arguments:
503 * spp pointer to SPANS protocol instance block
504 * msg pointer to the open message
506 * Returns:
507 * none
510 static void
511 spans_open_req(struct spans *spp, spans_msg *msg)
513 spans_result result = SPANS_OK;
514 spans_msg *rsp_msg;
515 struct spans_vccb *svp = NULL;
516 struct atm_pif *pip;
517 spans_vpvc vpvc;
518 int err = 0, vpi, vci;
519 Aal_t aal;
520 Atm_attributes call_attrs;
522 ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
525 * See if the connection is new
527 if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
529 * We already have a VCCB that matches the connection in
530 * the request
532 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
533 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
534 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
535 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
536 (vpi == svp->sv_vpi &&
537 vci == svp->sv_vci))) {
539 * VCCB already exists, process depending on
540 * state
542 switch (svp->sv_sstate) {
543 case SPANS_VC_R_POPEN:
544 /* I'm still thinking about it */
545 return;
546 case SPANS_VC_OPEN:
547 /* Retransmit the open_rsp */
548 break;
549 case SPANS_VC_POPEN:
550 case SPANS_VC_CLOSE:
551 case SPANS_VC_ABORT:
552 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
553 result = SPANS_FAIL;
554 break;
556 } else {
558 * VCCB is for same connection, but other
559 * parameters don't match
561 ATM_DEBUG0("spans_open_req: VCCB confusion\n");
562 result = SPANS_FAIL;
564 svp = NULL;
565 goto response;
569 * Verify that the request is for our ATM addres
571 if (spans_addr_cmp(spp->sp_addr.address,
572 &msg->sm_open_req.opreq_conn.con_dst)) {
573 ATM_DEBUG0("spans_open_req: bad destination\n");
574 result = SPANS_BADDEST;
575 goto response;
579 * See if we recognize the specified AAL
581 if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
582 ATM_DEBUG0("spans_open_req: bad AAL\n");
583 result = SPANS_FAIL;
584 goto response;
588 * Should verify that we can handle requested connection QOS
592 * Select a VPI/VCI for the new connection
594 if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
596 * Requestor asked for a certain VPI/VCI. Make sure we
597 * aren't already using the pair that was asked for.
599 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
600 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
601 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
602 ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
603 result = SPANS_NOVPVC;
604 goto response;
606 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
607 } else {
609 * Allocate a VPI/VCI for this end of the VCC
611 vpvc = spans_alloc_vpvc(spp);
612 if (vpvc == 0) {
613 ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
614 result = SPANS_NOVPVC;
615 goto response;
620 * Get a new VCCB for the connection
622 svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
623 if (svp == NULL) {
624 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
625 result = SPANS_NORSC;
626 goto response;
630 * Find the physical interface structure
632 pip = spp->sp_pif;
635 * Fill in the VCCB fields that we can at this point
637 svp->sv_type = VCC_SVC | VCC_IN;
638 svp->sv_proto = ATM_SIG_SPANS;
639 svp->sv_sstate = SPANS_VC_R_POPEN;
640 svp->sv_ustate = VCCU_POPEN;
641 svp->sv_pif = pip;
642 svp->sv_nif = pip->pif_nif;
643 svp->sv_conn = msg->sm_open_req.opreq_conn;
644 svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
645 svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
646 svp->sv_tstamp = time_second;
648 svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
649 svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
652 * Put the VCCB on the SPANS queue
654 ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
657 * Set up the ATM attributes block
659 KM_ZERO(&call_attrs, sizeof(call_attrs));
660 call_attrs.nif = svp->sv_nif;
661 call_attrs.api = CMAPI_CPCS;
663 call_attrs.aal.tag = T_ATM_PRESENT;
664 call_attrs.aal.type = aal;
665 switch(aal) {
666 case ATM_AAL3_4:
667 call_attrs.aal.v.aal4.forward_max_SDU_size =
668 ATM_NIF_MTU;
669 call_attrs.aal.v.aal4.backward_max_SDU_size =
670 ATM_NIF_MTU;
671 call_attrs.aal.v.aal4.SSCS_type =
672 T_ATM_NULL;
673 call_attrs.aal.v.aal4.mid_low = 0;
674 call_attrs.aal.v.aal4.mid_high = 1023;
675 break;
676 case ATM_AAL5:
677 call_attrs.aal.v.aal5.forward_max_SDU_size =
678 ATM_NIF_MTU;
679 call_attrs.aal.v.aal5.backward_max_SDU_size =
680 ATM_NIF_MTU;
681 call_attrs.aal.v.aal5.SSCS_type =
682 T_ATM_NULL;
683 break;
686 call_attrs.traffic.tag = T_ATM_PRESENT;
687 call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
688 call_attrs.traffic.v.forward.PCR_all_traffic =
689 msg->sm_open_req.opreq_desrsrc.rsc_peak *
690 1000 / 53;
691 call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
692 call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
693 call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
694 call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
695 call_attrs.traffic.v.forward.tagging = T_NO;
696 call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
697 call_attrs.traffic.v.backward.PCR_all_traffic =
698 call_attrs.traffic.v.forward.PCR_all_traffic;
699 call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
700 call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
701 call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
702 call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
703 call_attrs.traffic.v.backward.tagging = T_NO;
704 call_attrs.traffic.v.best_effort = T_YES;
706 call_attrs.bearer.tag = T_ATM_PRESENT;
707 call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
708 call_attrs.bearer.v.traffic_type = T_ATM_NULL;
709 call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
710 call_attrs.bearer.v.clipping_susceptibility = T_NO;
711 call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
714 call_attrs.bhli.tag = T_ATM_ABSENT;
715 call_attrs.blli.tag_l2 = T_ATM_ABSENT;
716 call_attrs.blli.tag_l3 = T_ATM_ABSENT;
717 call_attrs.llc.tag = T_ATM_ABSENT;
719 call_attrs.called.tag = T_ATM_PRESENT;
720 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
721 call_attrs.called.addr.address);
722 call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
723 call_attrs.called.addr.address_length = sizeof(spans_addr);
724 call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
725 call_attrs.called.subaddr.address_length = 0;
727 call_attrs.calling.tag = T_ATM_PRESENT;
728 spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
729 call_attrs.calling.addr.address);
730 call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
731 call_attrs.calling.addr.address_length = sizeof(spans_addr);
732 call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
733 call_attrs.calling.subaddr.address_length = 0;
735 call_attrs.qos.tag = T_ATM_PRESENT;
736 call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
737 call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
738 call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
740 call_attrs.transit.tag = T_ATM_ABSENT;
741 call_attrs.cause.tag = T_ATM_ABSENT;
744 * Notify the connection manager that it has a new channel
746 err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
747 if (err) {
748 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
749 result = SPANS_FAIL;
750 goto response;
754 * Wait for the connection recipient to issue an accept
756 return;
758 response:
760 * Clean up the VCCB and the atm_conn block if we got them
762 if (svp) {
763 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
764 spp->sp_vccq);
765 atm_free(svp);
769 * Some problem was detected with the request. Send a SPANS
770 * message rejecting the connection.
772 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
773 if (rsp_msg == NULL)
774 return;
777 * Fill out the response
779 rsp_msg->sm_vers = SPANS_VERS_1_0;
780 rsp_msg->sm_type = SPANS_OPEN_RSP;
781 rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
782 rsp_msg->sm_open_rsp.oprsp_result = result;
783 rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
786 * Send the Open Response
788 spans_send_msg(spp, rsp_msg);
789 atm_free(rsp_msg);
794 * Process an open response or open confirmation
796 * Called when an open response or open confirmation is received.
797 * Processing will be based on the state of the requested connection and
798 * the status returned.
800 * Arguments:
801 * spp pointer to SPANS protocol instance block
802 * msg pointer to the open response or confirmation message
804 * Returns:
805 * none
808 static void
809 spans_open_rsp(struct spans *spp, spans_msg *msg)
811 struct spans_vccb *svp;
813 ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
816 * Locate the VCCB for the connection
818 svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
819 if (svp == NULL)
820 return;
823 * Check the connection state
825 if ((svp->sv_sstate != SPANS_VC_POPEN &&
826 svp->sv_sstate != SPANS_VC_R_POPEN) ||
827 svp->sv_ustate != VCCU_POPEN) {
828 ATM_DEBUG2(
829 "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
830 svp->sv_sstate, svp->sv_ustate);
831 return;
835 * Cancel the retransmission timer
837 SPANS_VC_CANCEL((struct vccb *) svp);
840 * Check the result
842 switch (msg->sm_open_rsp.oprsp_result) {
844 case SPANS_OK:
846 * Save the assigned VPI and VCI
848 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
849 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
852 * Update the VCC state and notify the VCC owner
854 svp->sv_sstate = SPANS_VC_OPEN;
855 svp->sv_ustate = VCCU_OPEN;
856 svp->sv_tstamp = time_second;
857 atm_cm_connected(svp->sv_connvc);
858 break;
860 case SPANS_FAIL:
861 case SPANS_NOVPVC:
862 case SPANS_NORSC:
863 case SPANS_BADDEST:
865 * Close out the VCCB and notify the user
867 svp->sv_sstate = SPANS_VC_FREE;
868 svp->sv_ustate = VCCU_CLOSED;
869 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
870 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
871 T_ATM_ITU_CODING;
872 svp->sv_connvc->cvc_attr.cause.v.location =
873 T_ATM_LOC_USER;
874 svp->sv_connvc->cvc_attr.cause.v.cause_value =
875 T_ATM_CAUSE_CALL_REJECTED;
876 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
877 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
878 atm_cm_cleared(svp->sv_connvc);
879 break;
881 default:
882 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
883 msg->sm_open_rsp.oprsp_result);
884 break;
890 * Process a close request from the network
892 * Called when a close request, close indication, rclose request, or
893 * rclose indication is received. Processing will be based on the
894 * state of the connection.
896 * Arguments:
897 * spp pointer to SPANS protocol instance block
898 * msg pointer to the close request message
900 * Returns:
901 * none
904 static void
905 spans_close_req(struct spans *spp, spans_msg *msg)
907 struct spans_vccb *svp;
908 spans_result result;
909 spans_msg *rsp_msg;
910 u_char outstate;
911 Atm_connvc *cvp;
913 ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
916 * Locate the VCCB for the connection
918 svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
919 if (svp == NULL) {
920 result = SPANS_BADDEST;
921 goto response;
925 * Check the connection type
927 if (!(svp->sv_type & VCC_SVC)) {
928 result = SPANS_FAIL;
929 goto response;
933 * Check the connection state
935 switch (svp->sv_sstate) {
936 case SPANS_VC_OPEN:
937 case SPANS_VC_R_POPEN:
938 case SPANS_VC_POPEN:
940 * VCC is open or opening--continue
942 break;
943 case SPANS_VC_CLOSE:
944 case SPANS_VC_FREE:
945 case SPANS_VC_ABORT:
947 * We're already closing--give a response, since this
948 * is probably a retransmission
950 result = SPANS_OK;
951 goto response;
952 case SPANS_VC_NULL:
953 result = SPANS_FAIL;
954 goto response;
958 * Cancel the retransmission timer
960 SPANS_VC_CANCEL((struct vccb *) svp);
963 * Close out the VCCB and notify the user
965 outstate = svp->sv_sstate;
966 svp->sv_ustate = VCCU_CLOSED;
967 svp->sv_sstate = SPANS_VC_FREE;
968 cvp = svp->sv_connvc;
969 switch (outstate) {
970 case SPANS_VC_R_POPEN:
971 spans_free((struct vccb *)svp);
972 /* FALLTHRU */
974 case SPANS_VC_POPEN:
975 case SPANS_VC_OPEN:
976 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
977 cvp->cvc_attr.cause.v.coding_standard =
978 T_ATM_ITU_CODING;
979 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
980 cvp->cvc_attr.cause.v.cause_value =
981 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
982 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
983 sizeof(cvp->cvc_attr.cause.v.diagnostics));
984 atm_cm_cleared(svp->sv_connvc);
985 break;
988 result = SPANS_OK;
990 response:
992 * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
994 rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
995 if (rsp_msg == NULL)
996 return;
997 rsp_msg->sm_vers = SPANS_VERS_1_0;
998 if (msg->sm_type == SPANS_RCLOSE_REQ ||
999 msg->sm_type == SPANS_RCLOSE_IND) {
1000 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1001 } else {
1002 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1004 rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1005 rsp_msg->sm_close_rsp.clrsp_result = result;
1006 spans_send_msg(spp, rsp_msg);
1007 atm_free(rsp_msg);
1012 * Process a close response or close confirmation
1014 * Called when an close response or close confirmation is received.
1015 * Processing will be based on the state of the requested connection and
1016 * the returned status.
1018 * Arguments:
1019 * spp pointer to SPANS protocol instance block
1020 * msg pointer to the close response or confirmation message
1022 * Returns:
1023 * none
1026 static void
1027 spans_close_rsp(struct spans *spp, spans_msg *msg)
1029 struct spans_vccb *svp;
1031 ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1034 * Locate the VCCB for the connection
1036 svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1037 if (svp == NULL) {
1038 return;
1042 * Check the VCCB state
1044 if (svp->sv_sstate != SPANS_VC_CLOSE) {
1045 return;
1049 * Cancel the retransmission timer
1051 SPANS_VC_CANCEL((struct vccb *) svp);
1054 * Check the response from the remote end
1056 switch (msg->sm_close_rsp.clrsp_result) {
1058 case SPANS_OK:
1060 * Mark the VCCB as closed and notify the owner
1062 svp->sv_sstate = SPANS_VC_FREE;
1063 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1064 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1065 T_ATM_ITU_CODING;
1066 svp->sv_connvc->cvc_attr.cause.v.location =
1067 T_ATM_LOC_USER;
1068 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1069 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1070 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1071 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1072 atm_cm_cleared(svp->sv_connvc);
1073 break;
1075 case SPANS_NOVPVC:
1076 case SPANS_BADDEST:
1077 case SPANS_FAIL:
1078 case SPANS_NORSC:
1080 * Mark the VCCB as closed and notify the owner
1082 svp->sv_sstate = SPANS_VC_FREE;
1083 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1084 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1085 T_ATM_ITU_CODING;
1086 svp->sv_connvc->cvc_attr.cause.v.location =
1087 T_ATM_LOC_USER;
1088 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1089 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1090 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1091 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1092 atm_cm_cleared(svp->sv_connvc);
1093 break;
1095 default:
1096 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1097 msg->sm_close_rsp.clrsp_result);
1098 break;
1104 * Process a multi request or multi indication
1106 * Called when a multi response or multi confirmation is received. We
1107 * don't support multicast channels, so we just reject the request.
1109 * Arguments:
1110 * spp pointer to SPANS protocol instance block
1111 * msg pointer to the multi request or indication message
1113 * Returns:
1114 * none
1117 static void
1118 spans_multi_req(struct spans *spp, spans_msg *msg)
1120 spans_msg *rsp_msg;
1123 * Get memory for a SPANS_MULTI_RSP message.
1125 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1126 if (rsp_msg == NULL)
1127 return;
1130 * Fill out the response.
1132 rsp_msg->sm_vers = SPANS_VERS_1_0;
1133 rsp_msg->sm_type = SPANS_MULTI_RSP;
1134 rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1135 rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1136 rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1137 rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1140 * Send the response and free the message.
1142 spans_send_msg(spp, rsp_msg);
1143 atm_free(rsp_msg);
1148 * Process an add request or add indication
1150 * Called when an add response or add confirmation is received. We
1151 * don't support multicast channels, so we just reject the request.
1153 * Arguments:
1154 * spp pointer to SPANS protocol instance block
1155 * msg pointer to the add request or indication message
1157 * Returns:
1158 * none
1161 static void
1162 spans_add_req(struct spans *spp, spans_msg *msg)
1164 spans_msg *rsp_msg;
1167 * Get memory for a SPANS_ADD_RSP message.
1169 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1170 if (rsp_msg == NULL)
1171 return;
1174 * Fill out the response.
1176 rsp_msg->sm_vers = SPANS_VERS_1_0;
1177 rsp_msg->sm_type = SPANS_ADD_RSP;
1178 rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1179 rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1180 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1181 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1182 rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1185 * Send the response and free the message.
1187 spans_send_msg(spp, rsp_msg);
1188 atm_free(rsp_msg);
1193 * Process a join request
1195 * Called when an join request is received. We don't support group
1196 * addresses, so we just reject the request.
1198 * Arguments:
1199 * spp pointer to SPANS protocol instance block
1200 * msg pointer to the join request message
1202 * Returns:
1203 * none
1206 static void
1207 spans_join_req(struct spans *spp, spans_msg *msg)
1209 spans_msg *rsp_msg;
1212 * Get memory for a SPANS_JOIN_CNF message.
1214 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1215 if (rsp_msg == NULL)
1216 return;
1219 * Fill out the response.
1221 rsp_msg->sm_vers = SPANS_VERS_1_0;
1222 rsp_msg->sm_type = SPANS_JOIN_CNF;
1223 spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1224 &rsp_msg->sm_join_cnf.jncnf_addr);
1225 rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1228 * Send the response and free the message.
1230 spans_send_msg(spp, rsp_msg);
1231 atm_free(rsp_msg);
1236 * Process a leave request
1238 * Called when an leave request is received. We don't support group
1239 * addresses, so we just reject the request.
1241 * Arguments:
1242 * spp pointer to SPANS protocol instance block
1243 * msg pointer to the leave request message
1245 * Returns:
1246 * none
1249 static void
1250 spans_leave_req(struct spans *spp, spans_msg *msg)
1252 spans_msg *rsp_msg;
1255 * Get memory for a SPANS_LEAVE_CNF message.
1257 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1258 if (rsp_msg == NULL)
1259 return;
1262 * Fill out the response.
1264 rsp_msg->sm_vers = SPANS_VERS_1_0;
1265 rsp_msg->sm_type = SPANS_LEAVE_CNF;
1266 spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1267 &rsp_msg->sm_leave_cnf.lvcnf_addr);
1268 rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1271 * Send the response and free the message.
1273 spans_send_msg(spp, rsp_msg);
1274 atm_free(rsp_msg);
1279 * Process a VCI range indication
1281 * Called when a VCI range indication is received. Adjust the VCI
1282 * bounds if they have changed.
1284 * Arguments:
1285 * spp pointer to SPANS protocol instance block
1286 * msg pointer to the VCI range indication message
1288 * Returns:
1289 * none
1292 static void
1293 spans_vcir_ind(struct spans *spp, spans_msg *msg)
1296 * Adjust the limits if they have changed
1298 if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1299 spp->sp_min_vci =
1300 (msg->sm_vcir_ind.vrind_min <
1301 SPANS_MIN_VCI ?
1302 SPANS_MIN_VCI :
1303 msg->sm_vcir_ind.vrind_min);
1305 if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1306 spp->sp_max_vci =
1307 (msg->sm_vcir_ind.vrind_max >
1308 SPANS_MAX_VCI ?
1309 SPANS_MAX_VCI :
1310 msg->sm_vcir_ind.vrind_max);
1316 * Process a query request
1318 * Called when a query request is received. Respond with the
1319 * appropriate query response.
1321 * Arguments:
1322 * spp pointer to SPANS protocol instance block
1323 * msg pointer to the VCI range indication message
1325 * Returns:
1326 * none
1329 static void
1330 spans_query_req(struct spans *spp, spans_msg *msg)
1332 struct spans_vccb *svp = NULL;
1333 spans_msg *rsp_msg;
1335 ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1338 * Ignore an end-to-end query
1340 if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1341 return;
1345 * Get memory for a SPANS_QUERY_RSP message.
1347 rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1348 if (rsp_msg == NULL)
1349 return;
1352 * Fill out the response.
1354 rsp_msg->sm_vers = SPANS_VERS_1_0;
1355 rsp_msg->sm_type = SPANS_QUERY_RSP;
1356 rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1357 rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1358 rsp_msg->sm_query_rsp.qyrsp_data = 0;
1361 * Get the state of the requested connection
1363 svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1364 if (svp) {
1365 switch(svp->sv_sstate) {
1366 case SPANS_VC_NULL:
1367 case SPANS_VC_FREE:
1368 rsp_msg->sm_query_rsp.qyrsp_state =
1369 SPANS_CONN_CLOSED;
1370 break;
1371 case SPANS_VC_OPEN:
1372 rsp_msg->sm_query_rsp.qyrsp_state =
1373 SPANS_CONN_OPEN;
1374 break;
1375 case SPANS_VC_POPEN:
1376 case SPANS_VC_R_POPEN:
1377 rsp_msg->sm_query_rsp.qyrsp_state =
1378 SPANS_CONN_OPEN_PEND;
1379 break;
1380 case SPANS_VC_CLOSE:
1381 case SPANS_VC_ABORT:
1382 rsp_msg->sm_query_rsp.qyrsp_state =
1383 SPANS_CONN_CLOSE_PEND;
1384 break;
1385 case SPANS_VC_ACTIVE:
1386 case SPANS_VC_ACT_DOWN:
1388 * VCCB is for a PVC (shouldn't happen)
1390 atm_free(rsp_msg);
1391 return;
1393 } else {
1395 * No VCCB found--connection doesn't exist
1397 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1401 * Send the response and free the message.
1403 spans_send_msg(spp, rsp_msg);
1404 atm_free(rsp_msg);
1409 * Process a SPANS signalling message
1411 * Called when a SPANS message is received. The message is converted
1412 * into internal format with XDR and decoded by calling the appropriate
1413 * mesage handling routine. Unrecognized and unexpected messages are
1414 * logged.
1416 * Arguments:
1417 * spp pointer to SPANS protocol instance block
1418 * m pointer to a buffer chain containing the SPANS message
1420 * Returns:
1421 * none
1424 void
1425 spans_rcv_msg(struct spans *spp, KBuffer *m)
1427 XDR xdrs;
1428 spans_msg *msg;
1431 * Get storage for the message
1433 msg = (spans_msg *)atm_allocate(&spans_msgpool);
1434 if (msg == NULL) {
1435 return;
1439 * Convert the message from network order to internal format
1441 xdrmbuf_init(&xdrs, m, XDR_DECODE);
1442 if (!xdr_spans_msg(&xdrs, msg)) {
1443 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1444 spans_dump_buffer(m);
1445 goto done;
1448 #ifdef NOTDEF
1450 * Debug--print some information about the message
1452 if (msg->sm_type != SPANS_STAT_REQ &&
1453 msg->sm_type != SPANS_STAT_IND &&
1454 msg->sm_type != SPANS_STAT_RSP) {
1455 kprintf("spans_rcv_msg: got ");
1456 spans_print_msg(msg);
1458 #endif
1461 * Verify the message sm_vers
1463 if (msg->sm_vers != SPANS_VERS_1_0) {
1464 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1465 msg->sm_vers);
1469 * Ignore the message if SPANS isn't up yet
1471 if (spp->sp_state != SPANS_ACTIVE &&
1472 (spp->sp_state != SPANS_PROBE ||
1473 (msg->sm_type != SPANS_STAT_REQ &&
1474 msg->sm_type != SPANS_STAT_RSP &&
1475 msg->sm_type != SPANS_STAT_IND))) {
1476 goto done;
1480 * Process the message based on its type
1482 switch(msg->sm_type) {
1483 case SPANS_STAT_REQ:
1484 spans_status_ind(spp, msg);
1485 break;
1486 case SPANS_STAT_IND:
1487 spans_status_ind(spp, msg);
1488 break;
1489 case SPANS_STAT_RSP:
1490 spans_status_rsp(spp, msg);
1491 break;
1492 case SPANS_OPEN_REQ:
1493 spans_open_req(spp, msg);
1494 break;
1495 case SPANS_OPEN_IND:
1496 spans_open_req(spp, msg);
1497 break;
1498 case SPANS_OPEN_RSP:
1499 spans_open_rsp(spp, msg);
1500 break;
1501 case SPANS_OPEN_CNF:
1502 spans_open_rsp(spp, msg);
1503 break;
1504 case SPANS_CLOSE_REQ:
1505 spans_close_req(spp, msg);
1506 break;
1507 case SPANS_CLOSE_IND:
1508 spans_close_req(spp, msg);
1509 break;
1510 case SPANS_CLOSE_RSP:
1511 spans_close_rsp(spp, msg);
1512 break;
1513 case SPANS_CLOSE_CNF:
1514 spans_close_rsp(spp, msg);
1515 break;
1516 case SPANS_RCLOSE_REQ:
1517 spans_close_req(spp, msg);
1518 break;
1519 case SPANS_RCLOSE_IND:
1520 spans_close_req(spp, msg);
1521 break;
1522 case SPANS_RCLOSE_RSP:
1523 spans_close_rsp(spp, msg);
1524 break;
1525 case SPANS_RCLOSE_CNF:
1526 spans_close_rsp(spp, msg);
1527 break;
1528 case SPANS_MULTI_REQ:
1529 spans_multi_req(spp, msg);
1530 break;
1531 case SPANS_MULTI_IND:
1532 spans_multi_req(spp, msg);
1533 break;
1534 case SPANS_MULTI_RSP:
1535 log(LOG_ERR,
1536 "spans: unexpected message (multi_rsp)\n");
1537 break;
1538 case SPANS_MULTI_CNF:
1539 log(LOG_ERR,
1540 "spans: unexpected message (multi_conf)\n");
1541 break;
1542 case SPANS_ADD_REQ:
1543 spans_add_req(spp, msg);
1544 break;
1545 case SPANS_ADD_IND:
1546 spans_add_req(spp, msg);
1547 break;
1548 case SPANS_ADD_RSP:
1549 log(LOG_ERR,
1550 "spans: unexpected message (add_rsp)\n");
1551 break;
1552 case SPANS_ADD_CNF:
1553 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1554 break;
1555 case SPANS_JOIN_REQ:
1556 spans_join_req(spp, msg);
1557 break;
1558 case SPANS_JOIN_CNF:
1559 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1560 break;
1561 case SPANS_LEAVE_REQ:
1562 spans_leave_req(spp, msg);
1563 break;
1564 case SPANS_LEAVE_CNF:
1565 log(LOG_ERR,
1566 "spans: unexpected message (leave_conf)\n");
1567 break;
1568 case SPANS_VCIR_IND:
1569 spans_vcir_ind(spp, msg);
1570 break;
1571 case SPANS_QUERY_REQ:
1572 spans_query_req(spp, msg);
1573 break;
1574 case SPANS_QUERY_RSP:
1575 log(LOG_ERR,
1576 "spans: unexpected message (query_rsp)\n");
1577 break;
1578 default:
1579 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1580 msg->sm_type);
1583 done:
1585 * Free the incoming message (both buffer and internal format) if
1586 * necessary.
1588 if (msg)
1589 atm_free(msg);
1590 if (m)
1591 KB_FREEALL(m);