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/usr.sbin/atm/scspd/scsp_msg.c,v 1.3 1999/08/28 01:15:33 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_msg.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP message-handling routines
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netatm/port.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_ioctl.h>
64 * Copy CSAS records into a CA record
67 * dcsp pointer to DCS block for DCS
68 * cap pointer to CA record for CSASs
76 scsp_ca_csas_setup(dcsp, cap)
80 int csas_len, len, mtu;
81 Scsp_server *ssp = dcsp->sd_server;
82 Scsp_cse *csep, *next_csep;
86 * Loop through pending CSAS records
88 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
90 dcsp->sd_dcsid.id_len;
91 csas_len = sizeof(struct scsp_ncsa) +
92 dcsp->sd_server->ss_id_len +
93 dcsp->sd_server->ss_ckey_len;
94 mtu = dcsp->sd_server->ss_mtu;
95 for (csep = dcsp->sd_ca_csas;
96 csep && (len < mtu - csas_len);
98 next_csep = csep->sc_next;
99 csap = scsp_cse2csas(csep);
100 LINK2TAIL(csap, Scsp_csa, cap->ca_csa_rec, next);
102 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
104 cap->ca_mcp.rec_cnt++;
110 * Process CSA records from a CSU Request that may be in response to
111 * CSAS records sent in a CSUS
114 * dcsp pointer to DCS control block
115 * msg pointer to received message
122 scsp_csus_ack(dcsp, msg)
127 Scsp_csa *csap, *csasp, *next_csasp;
130 * If this isn't a CSU Request, or there's no outstanding CSUS,
131 * or the outstanding CSUS has already been satisfied, just
134 if (!msg || msg->sc_msg_type != SCSP_CSU_REQ_MSG ||
135 !dcsp->sd_csus_rexmt_msg ||
136 !dcsp->sd_csus_rexmt_msg->sc_csu_msg ||
137 !dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_csa_rec)
142 * Loop through the CSASs in the CSUS message, checking for
143 * each in the CSA records of the received CSU Request
145 csusp = dcsp->sd_csus_rexmt_msg->sc_csu_msg;
146 for (csasp = csusp->csu_csa_rec; csasp; csasp = next_csasp) {
147 next_csasp = csasp->next;
148 for (csap = msg->sc_csu_msg->csu_csa_rec;
149 csap; csap = csap->next) {
151 * If the records match, unlink and free the
154 if (scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
155 scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
156 scsp_cmp_id(&csap->oid, &csasp->oid) == 0 &&
157 csap->seq >= csasp->seq) {
158 UNLINK(csasp, Scsp_csa,
161 SCSP_FREE_CSA(csasp);
162 dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_mcp.rec_cnt--;
168 if (csusp->csu_csa_rec == (Scsp_csa *)0) {
170 * All CSASs in the CSUS message have been
171 * answered. Stop the timer and free the
174 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
175 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
176 dcsp->sd_csus_rexmt_msg = (Scsp_msg *)0;
179 * If the CRL isn't empty, send another CSUS
182 (void)scsp_send_csus(dcsp);
192 * dcsp pointer to DCS block for DCS
196 * else errno indicating reason for failure
206 Scsp_server *ssp = dcsp->sd_server;
209 * Get memory for a CA message
211 ca_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
213 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
215 cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
217 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
219 UM_ZERO(ca_msg, sizeof(Scsp_msg));
220 UM_ZERO(cap, sizeof(Scsp_ca));
223 * Fill out constant fields
225 ca_msg->sc_msg_type = SCSP_CA_MSG;
227 cap->ca_seq = dcsp->sd_ca_seq;
228 cap->ca_mcp.pid = ssp->ss_pid;
229 cap->ca_mcp.sgid = ssp->ss_sgid;
230 cap->ca_mcp.sid = ssp->ss_lsid;
231 cap->ca_mcp.rid = dcsp->sd_dcsid;
234 * Fill out state-dependent fields
236 switch(dcsp->sd_ca_state) {
242 case SCSP_CAFSM_MASTER:
245 scsp_ca_csas_setup(dcsp, cap);
246 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
248 case SCSP_CAFSM_SLAVE:
251 scsp_ca_csas_setup(dcsp, cap);
252 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
255 scsp_log(LOG_ERR, "Invalid state in scsp_send_ca");
260 * Send the CA message and save a pointer to it in case
261 * it needs to be retransmitted
263 rc = scsp_send_msg(dcsp, ca_msg);
265 dcsp->sd_ca_rexmt_msg = ca_msg;
267 scsp_free_msg(ca_msg);
275 * Send a CSU Solicit message
278 * dcsp pointer to DCS block for DCS
282 * else errno indicating reason for failure
289 int csas_len, len, mtu, rc;
292 Scsp_csa *csasp, *next_csasp;
293 Scsp_server *ssp = dcsp->sd_server;
296 * If we have a mesage saved for retransmission, use it.
297 * If not, get memory for a new one.
299 if (dcsp->sd_csus_rexmt_msg) {
300 csus_msg = dcsp->sd_csus_rexmt_msg;
301 csusp = csus_msg->sc_csu_msg;
304 * Get memory for a CSUS message
306 csus_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
308 scsp_mem_err("scsp_send_csus: sizeof(Scsp_msg)");
310 csusp = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
312 scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
314 UM_ZERO(csus_msg, sizeof(Scsp_msg));
315 UM_ZERO(csusp, sizeof(Scsp_csu_msg));
318 * Fill out constant fields
320 csus_msg->sc_msg_type = SCSP_CSUS_MSG;
321 csus_msg->sc_csu_msg = csusp;
322 csusp->csu_mcp.pid = ssp->ss_pid;
323 csusp->csu_mcp.sgid = ssp->ss_sgid;
324 csusp->csu_mcp.sid = ssp->ss_lsid;
325 csusp->csu_mcp.rid = dcsp->sd_dcsid;
329 * Move CSAS records from CRL into message
331 mtu = dcsp->sd_server->ss_mtu;
332 csas_len = sizeof(struct scsp_ncsa) + ssp->ss_id_len +
334 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
336 csas_len * (csusp->csu_mcp.rec_cnt + 1);
337 for (csasp = dcsp->sd_crl;
338 csasp && ((len + csas_len) < mtu);
339 csasp = next_csasp, len += csas_len) {
340 next_csasp = csasp->next;
341 csusp->csu_mcp.rec_cnt++;
342 UNLINK(csasp, Scsp_csa, dcsp->sd_crl, next);
343 LINK2TAIL(csasp, Scsp_csa, csusp->csu_csa_rec, next);
348 * Send the CSUS message and save a pointer to it in case
349 * it needs to be retransmitted
351 rc = scsp_send_msg(dcsp, csus_msg);
354 * Success--Save a pointer to the message and
355 * start the CSUS retransmit timer
357 dcsp->sd_csus_rexmt_msg = csus_msg;
358 HARP_TIMER(&dcsp->sd_csus_rexmt_t,
359 dcsp->sd_csus_rexmt_int,
360 scsp_csus_retran_timeout);
363 * Error--free the CSUS message
365 scsp_free_msg(csus_msg);
373 * Send a CSU Request message
376 * dcsp pointer to DCS block for DCS
377 * csap pointer to CSAs to include
381 * else errno indicating reason for failure
385 scsp_send_csu_req(dcsp, csap)
390 Scsp_server *ssp = dcsp->sd_server;
397 * Return if CSA list is empty
403 * Get memory for a CSU Req message
405 csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
407 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
409 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
411 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
413 UM_ZERO(csu_msg, sizeof(Scsp_msg));
414 UM_ZERO(csup, sizeof(Scsp_csu_msg));
417 * Get memory for a CSU Req retransmission queue entry
419 rxp = (Scsp_csu_rexmt *)UM_ALLOC(sizeof(Scsp_csu_rexmt));
421 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
423 UM_ZERO(rxp, sizeof(Scsp_csu_rexmt));
426 * Fill out constant fields
428 csu_msg->sc_msg_type = SCSP_CSU_REQ_MSG;
429 csu_msg->sc_csu_msg = csup;
430 csup->csu_mcp.pid = ssp->ss_pid;
431 csup->csu_mcp.sgid = ssp->ss_sgid;
432 csup->csu_mcp.sid = ssp->ss_lsid;
433 csup->csu_mcp.rid = dcsp->sd_dcsid;
436 * Put the CSA list into the message
438 csup->csu_csa_rec = csap;
439 for (cnt_csap = csap; cnt_csap; cnt_csap = cnt_csap->next) {
440 csup->csu_mcp.rec_cnt++;
444 * Send the CSU Request
446 rc = scsp_send_msg(dcsp, csu_msg);
448 scsp_free_msg(csu_msg);
455 * Save the CSA entries on the CSU Request retransmission
456 * queue and start the retransmission timer
460 HARP_TIMER(&rxp->sr_t, dcsp->sd_csu_rexmt_int,
461 scsp_csu_req_retran_timeout);
462 LINK2TAIL(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
469 * Send a CSU Reply message
472 * dcsp pointer to DCS block for DCS
473 * csap pointer to CSAs to include
477 * errno reason for failure
481 scsp_send_csu_reply(dcsp, csap)
486 Scsp_server *ssp = dcsp->sd_server;
492 * Return if CSA list is empty
498 * Get memory for a CSU Reply message
500 csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
502 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
504 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
506 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
508 UM_ZERO(csu_msg, sizeof(Scsp_msg));
509 UM_ZERO(csup, sizeof(Scsp_csu_msg));
512 * Fill out constant fields
514 csu_msg->sc_msg_type = SCSP_CSU_REPLY_MSG;
515 csu_msg->sc_csu_msg = csup;
516 csup->csu_mcp.pid = ssp->ss_pid;
517 csup->csu_mcp.sgid = ssp->ss_sgid;
518 csup->csu_mcp.sid = ssp->ss_lsid;
519 csup->csu_mcp.rid = dcsp->sd_dcsid;
522 * Put the CSA list into the message. Convert the CSAs into
523 * CSASs by freeing the protocol-specific portion.
525 csup->csu_csa_rec = csap;
526 for (csap1 = csap; csap1; csap1 = csap1->next) {
527 switch(dcsp->sd_server->ss_pid) {
529 * We currently only support ATMARP
531 case SCSP_PROTO_ATMARP:
532 if (csap1->atmarp_data) {
533 UM_FREE(csap1->atmarp_data);
535 (Scsp_atmarp_csa *)0;
539 csup->csu_mcp.rec_cnt++;
545 rc = scsp_send_msg(dcsp, csu_msg);
546 scsp_free_msg(csu_msg);
553 * Send a Hello message
556 * dcsp pointer to DCS control block
560 * errno error encountered
564 scsp_send_hello(dcsp)
572 * Get memory for a Hello message
574 hello = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
576 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
578 UM_ZERO(hello, sizeof(Scsp_msg));
579 hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
581 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
583 UM_ZERO(hp, sizeof(Scsp_hello));
586 * Set up the Hello message
588 hello->sc_msg_type = SCSP_HELLO_MSG;
589 hello->sc_hello = hp;
590 hp->hello_int = SCSP_HELLO_Interval;
591 hp->dead_factor = SCSP_HELLO_DF;
592 hp->family_id = dcsp->sd_server->ss_fid;
593 hp->hello_mcp.pid = dcsp->sd_server->ss_pid;
594 hp->hello_mcp.sgid = dcsp->sd_server->ss_sgid;
595 hp->hello_mcp.flags = 0;
596 hp->hello_mcp.rec_cnt = 0;
597 hp->hello_mcp.sid = dcsp->sd_server->ss_lsid;
598 hp->hello_mcp.rid = dcsp->sd_dcsid;
601 * Send and free the message
603 rc = scsp_send_msg(dcsp, hello);
604 scsp_free_msg(hello);