kernel - VM PAGER part 1/2 - Remove vm_page_alloc()
[dragonfly.git] / usr.sbin / atm / scspd / scsp_msg.c
blob75ca384d802d717dc8e196537aa4b5ea8f41d0b7
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/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.4 2004/12/18 22:48:02 swildner 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>
42 #include <net/if.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>
52 #include <errno.h>
53 #include <libatm.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <syslog.h>
59 #include "scsp_msg.h"
60 #include "scsp_if.h"
61 #include "scsp_var.h"
64 * Copy CSAS records into a CA record
66 * Arguments:
67 * dcsp pointer to DCS block for DCS
68 * cap pointer to CA record for CSASs
71 * Returns:
72 * none
75 static void
76 scsp_ca_csas_setup(Scsp_dcs *dcsp, Scsp_ca *cap)
78 int csas_len, len, mtu;
79 Scsp_server *ssp = dcsp->sd_server;
80 Scsp_cse *csep, *next_csep;
81 Scsp_csa *csap;
84 * Loop through pending CSAS records
86 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
87 ssp->ss_lsid.id_len +
88 dcsp->sd_dcsid.id_len;
89 csas_len = sizeof(struct scsp_ncsa) +
90 dcsp->sd_server->ss_id_len +
91 dcsp->sd_server->ss_ckey_len;
92 mtu = dcsp->sd_server->ss_mtu;
93 for (csep = dcsp->sd_ca_csas;
94 csep && (len < mtu - csas_len);
95 csep = next_csep) {
96 next_csep = csep->sc_next;
97 csap = scsp_cse2csas(csep);
98 LINK2TAIL(csap, Scsp_csa, cap->ca_csa_rec, next);
99 len += csas_len;
100 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
101 UM_FREE(csep);
102 cap->ca_mcp.rec_cnt++;
108 * Process CSA records from a CSU Request that may be in response to
109 * CSAS records sent in a CSUS
111 * Arguments:
112 * dcsp pointer to DCS control block
113 * msg pointer to received message
115 * Returns:
116 * none
119 void
120 scsp_csus_ack(Scsp_dcs *dcsp, Scsp_msg *msg)
122 Scsp_csu_msg *csusp;
123 Scsp_csa *csap, *csasp, *next_csasp;
126 * If this isn't a CSU Request, or there's no outstanding CSUS,
127 * or the outstanding CSUS has already been satisfied, just
128 * return
130 if (!msg || msg->sc_msg_type != SCSP_CSU_REQ_MSG ||
131 !dcsp->sd_csus_rexmt_msg ||
132 !dcsp->sd_csus_rexmt_msg->sc_csu_msg ||
133 !dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_csa_rec)
134 return;
138 * Loop through the CSASs in the CSUS message, checking for
139 * each in the CSA records of the received CSU Request
141 csusp = dcsp->sd_csus_rexmt_msg->sc_csu_msg;
142 for (csasp = csusp->csu_csa_rec; csasp; csasp = next_csasp) {
143 next_csasp = csasp->next;
144 for (csap = msg->sc_csu_msg->csu_csa_rec;
145 csap; csap = csap->next) {
147 * If the records match, unlink and free the
148 * CSAS from the CSUS
150 if (scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
151 scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
152 scsp_cmp_id(&csap->oid, &csasp->oid) == 0 &&
153 csap->seq >= csasp->seq) {
154 UNLINK(csasp, Scsp_csa,
155 csusp->csu_csa_rec,
156 next);
157 SCSP_FREE_CSA(csasp);
158 dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_mcp.rec_cnt--;
159 break;
164 if (csusp->csu_csa_rec == NULL) {
166 * All CSASs in the CSUS message have been
167 * answered. Stop the timer and free the
168 * saved message.
170 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
171 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
172 dcsp->sd_csus_rexmt_msg = NULL;
175 * If the CRL isn't empty, send another CSUS
177 if (dcsp->sd_crl) {
178 scsp_send_csus(dcsp);
185 * Send a CA message
187 * Arguments:
188 * dcsp pointer to DCS block for DCS
190 * Returns:
191 * 0 message sent OK
192 * else errno indicating reason for failure
196 scsp_send_ca(Scsp_dcs *dcsp)
198 int rc;
199 Scsp_msg *ca_msg;
200 Scsp_ca *cap;
201 Scsp_server *ssp = dcsp->sd_server;
204 * Get memory for a CA message
206 ca_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
207 if (!ca_msg) {
208 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
210 cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
211 if (!cap) {
212 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
214 UM_ZERO(ca_msg, sizeof(Scsp_msg));
215 UM_ZERO(cap, sizeof(Scsp_ca));
218 * Fill out constant fields
220 ca_msg->sc_msg_type = SCSP_CA_MSG;
221 ca_msg->sc_ca = cap;
222 cap->ca_seq = dcsp->sd_ca_seq;
223 cap->ca_mcp.pid = ssp->ss_pid;
224 cap->ca_mcp.sgid = ssp->ss_sgid;
225 cap->ca_mcp.sid = ssp->ss_lsid;
226 cap->ca_mcp.rid = dcsp->sd_dcsid;
229 * Fill out state-dependent fields
231 switch(dcsp->sd_ca_state) {
232 case SCSP_CAFSM_NEG:
233 cap->ca_m = 1;
234 cap->ca_i = 1;
235 cap->ca_o = 1;
236 break;
237 case SCSP_CAFSM_MASTER:
238 cap->ca_m = 1;
239 cap->ca_i = 0;
240 scsp_ca_csas_setup(dcsp, cap);
241 cap->ca_o = dcsp->sd_ca_csas != NULL;
242 break;
243 case SCSP_CAFSM_SLAVE:
244 cap->ca_m = 0;
245 cap->ca_i = 0;
246 scsp_ca_csas_setup(dcsp, cap);
247 cap->ca_o = dcsp->sd_ca_csas != NULL;
248 break;
249 default:
250 scsp_log(LOG_ERR, "Invalid state in scsp_send_ca");
251 abort();
255 * Send the CA message and save a pointer to it in case
256 * it needs to be retransmitted
258 rc = scsp_send_msg(dcsp, ca_msg);
259 if (rc == 0) {
260 dcsp->sd_ca_rexmt_msg = ca_msg;
261 } else {
262 scsp_free_msg(ca_msg);
265 return(rc);
270 * Send a CSU Solicit message
272 * Arguments:
273 * dcsp pointer to DCS block for DCS
275 * Returns:
276 * 0 message sent OK
277 * else errno indicating reason for failure
281 scsp_send_csus(Scsp_dcs *dcsp)
283 int csas_len, len, mtu, rc;
284 Scsp_msg *csus_msg;
285 Scsp_csu_msg *csusp;
286 Scsp_csa *csasp, *next_csasp;
287 Scsp_server *ssp = dcsp->sd_server;
290 * If we have a mesage saved for retransmission, use it.
291 * If not, get memory for a new one.
293 if (dcsp->sd_csus_rexmt_msg) {
294 csus_msg = dcsp->sd_csus_rexmt_msg;
295 csusp = csus_msg->sc_csu_msg;
296 } else {
298 * Get memory for a CSUS message
300 csus_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
301 if (!csus_msg) {
302 scsp_mem_err("scsp_send_csus: sizeof(Scsp_msg)");
304 csusp = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
305 if (!csusp) {
306 scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
308 UM_ZERO(csus_msg, sizeof(Scsp_msg));
309 UM_ZERO(csusp, sizeof(Scsp_csu_msg));
312 * Fill out constant fields
314 csus_msg->sc_msg_type = SCSP_CSUS_MSG;
315 csus_msg->sc_csu_msg = csusp;
316 csusp->csu_mcp.pid = ssp->ss_pid;
317 csusp->csu_mcp.sgid = ssp->ss_sgid;
318 csusp->csu_mcp.sid = ssp->ss_lsid;
319 csusp->csu_mcp.rid = dcsp->sd_dcsid;
323 * Move CSAS records from CRL into message
325 mtu = dcsp->sd_server->ss_mtu;
326 csas_len = sizeof(struct scsp_ncsa) + ssp->ss_id_len +
327 ssp->ss_ckey_len;
328 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
329 2 * ssp->ss_id_len +
330 csas_len * (csusp->csu_mcp.rec_cnt + 1);
331 for (csasp = dcsp->sd_crl;
332 csasp && ((len + csas_len) < mtu);
333 csasp = next_csasp, len += csas_len) {
334 next_csasp = csasp->next;
335 csusp->csu_mcp.rec_cnt++;
336 UNLINK(csasp, Scsp_csa, dcsp->sd_crl, next);
337 LINK2TAIL(csasp, Scsp_csa, csusp->csu_csa_rec, next);
338 csasp->hops = 1;
342 * Send the CSUS message and save a pointer to it in case
343 * it needs to be retransmitted
345 rc = scsp_send_msg(dcsp, csus_msg);
346 if (rc == 0) {
348 * Success--Save a pointer to the message and
349 * start the CSUS retransmit timer
351 dcsp->sd_csus_rexmt_msg = csus_msg;
352 HARP_TIMER(&dcsp->sd_csus_rexmt_t,
353 dcsp->sd_csus_rexmt_int,
354 scsp_csus_retran_timeout);
355 } else {
357 * Error--free the CSUS message
359 scsp_free_msg(csus_msg);
362 return(rc);
367 * Send a CSU Request message
369 * Arguments:
370 * dcsp pointer to DCS block for DCS
371 * csap pointer to CSAs to include
373 * Returns:
374 * 0 message sent OK
375 * else errno indicating reason for failure
379 scsp_send_csu_req(Scsp_dcs *dcsp, Scsp_csa *csap)
381 int rc;
382 Scsp_server *ssp = dcsp->sd_server;
383 Scsp_csa *cnt_csap;
384 Scsp_msg *csu_msg;
385 Scsp_csu_msg *csup;
386 Scsp_csu_rexmt *rxp;
389 * Return if CSA list is empty
391 if (!csap)
392 return(0);
395 * Get memory for a CSU Req message
397 csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
398 if (!csu_msg) {
399 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
401 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
402 if (!csup) {
403 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
405 UM_ZERO(csu_msg, sizeof(Scsp_msg));
406 UM_ZERO(csup, sizeof(Scsp_csu_msg));
409 * Get memory for a CSU Req retransmission queue entry
411 rxp = (Scsp_csu_rexmt *)UM_ALLOC(sizeof(Scsp_csu_rexmt));
412 if (!rxp) {
413 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
415 UM_ZERO(rxp, sizeof(Scsp_csu_rexmt));
418 * Fill out constant fields
420 csu_msg->sc_msg_type = SCSP_CSU_REQ_MSG;
421 csu_msg->sc_csu_msg = csup;
422 csup->csu_mcp.pid = ssp->ss_pid;
423 csup->csu_mcp.sgid = ssp->ss_sgid;
424 csup->csu_mcp.sid = ssp->ss_lsid;
425 csup->csu_mcp.rid = dcsp->sd_dcsid;
428 * Put the CSA list into the message
430 csup->csu_csa_rec = csap;
431 for (cnt_csap = csap; cnt_csap; cnt_csap = cnt_csap->next) {
432 csup->csu_mcp.rec_cnt++;
436 * Send the CSU Request
438 rc = scsp_send_msg(dcsp, csu_msg);
439 if (rc) {
440 scsp_free_msg(csu_msg);
441 return(rc);
443 UM_FREE(csu_msg);
444 UM_FREE(csup);
447 * Save the CSA entries on the CSU Request retransmission
448 * queue and start the retransmission timer
450 rxp->sr_dcs = dcsp;
451 rxp->sr_csa = csap;
452 HARP_TIMER(&rxp->sr_t, dcsp->sd_csu_rexmt_int,
453 scsp_csu_req_retran_timeout);
454 LINK2TAIL(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
456 return(0);
461 * Send a CSU Reply message
463 * Arguments:
464 * dcsp pointer to DCS block for DCS
465 * csap pointer to CSAs to include
467 * Returns:
468 * 0 message sent OK
469 * errno reason for failure
473 scsp_send_csu_reply(Scsp_dcs *dcsp, Scsp_csa *csap)
475 int rc;
476 Scsp_server *ssp = dcsp->sd_server;
477 Scsp_csa *csap1;
478 Scsp_msg *csu_msg;
479 Scsp_csu_msg *csup;
482 * Return if CSA list is empty
484 if (!csap)
485 return(0);
488 * Get memory for a CSU Reply message
490 csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
491 if (!csu_msg) {
492 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
494 csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
495 if (!csup) {
496 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
498 UM_ZERO(csu_msg, sizeof(Scsp_msg));
499 UM_ZERO(csup, sizeof(Scsp_csu_msg));
502 * Fill out constant fields
504 csu_msg->sc_msg_type = SCSP_CSU_REPLY_MSG;
505 csu_msg->sc_csu_msg = csup;
506 csup->csu_mcp.pid = ssp->ss_pid;
507 csup->csu_mcp.sgid = ssp->ss_sgid;
508 csup->csu_mcp.sid = ssp->ss_lsid;
509 csup->csu_mcp.rid = dcsp->sd_dcsid;
512 * Put the CSA list into the message. Convert the CSAs into
513 * CSASs by freeing the protocol-specific portion.
515 csup->csu_csa_rec = csap;
516 for (csap1 = csap; csap1; csap1 = csap1->next) {
517 switch(dcsp->sd_server->ss_pid) {
519 * We currently only support ATMARP
521 case SCSP_PROTO_ATMARP:
522 if (csap1->atmarp_data) {
523 UM_FREE(csap1->atmarp_data);
524 csap1->atmarp_data = NULL;
526 break;
528 csup->csu_mcp.rec_cnt++;
532 * Send the CSU Reply
534 rc = scsp_send_msg(dcsp, csu_msg);
535 scsp_free_msg(csu_msg);
537 return(rc);
542 * Send a Hello message
544 * Arguments:
545 * dcsp pointer to DCS control block
547 * Returns:
548 * 0 success
549 * errno error encountered
553 scsp_send_hello(Scsp_dcs *dcsp)
555 int rc;
556 Scsp_msg *hello;
557 Scsp_hello *hp;
560 * Get memory for a Hello message
562 hello = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
563 if (!hello) {
564 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
566 UM_ZERO(hello, sizeof(Scsp_msg));
567 hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
568 if (!hp) {
569 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
571 UM_ZERO(hp, sizeof(Scsp_hello));
574 * Set up the Hello message
576 hello->sc_msg_type = SCSP_HELLO_MSG;
577 hello->sc_hello = hp;
578 hp->hello_int = SCSP_HELLO_Interval;
579 hp->dead_factor = SCSP_HELLO_DF;
580 hp->family_id = dcsp->sd_server->ss_fid;
581 hp->hello_mcp.pid = dcsp->sd_server->ss_pid;
582 hp->hello_mcp.sgid = dcsp->sd_server->ss_sgid;
583 hp->hello_mcp.flags = 0;
584 hp->hello_mcp.rec_cnt = 0;
585 hp->hello_mcp.sid = dcsp->sd_server->ss_lsid;
586 hp->hello_mcp.rid = dcsp->sd_dcsid;
589 * Send and free the message
591 rc = scsp_send_msg(dcsp, hello);
592 scsp_free_msg(hello);
594 return(rc);