kernel - VM PAGER part 1/2 - Remove vm_page_alloc()
[dragonfly.git] / usr.sbin / atm / scspd / scsp_cafsm.c
blobefa2e60b46b878b583e42c2db9a53a64f89ffc57
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_cafsm.c,v 1.3 1999/08/28 01:15:32 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_cafsm.c,v 1.5 2004/12/18 22:48:02 swildner Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * Cache Alignment finite state machine
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 * CA FSM actions
66 #define CA_ACTION_CNT 20
67 int scsp_ca_act_00(Scsp_dcs *, void *);
68 int scsp_ca_act_01(Scsp_dcs *, void *);
69 int scsp_ca_act_02(Scsp_dcs *, void *);
70 int scsp_ca_act_03(Scsp_dcs *, void *);
71 int scsp_ca_act_04(Scsp_dcs *, void *);
72 int scsp_ca_act_05(Scsp_dcs *, void *);
73 int scsp_ca_act_06(Scsp_dcs *, void *);
74 int scsp_ca_act_07(Scsp_dcs *, void *);
75 int scsp_ca_act_08(Scsp_dcs *, void *);
76 int scsp_ca_act_09(Scsp_dcs *, void *);
77 int scsp_ca_act_10(Scsp_dcs *, void *);
78 int scsp_ca_act_11(Scsp_dcs *, void *);
79 int scsp_ca_act_12(Scsp_dcs *, void *);
80 int scsp_ca_act_13(Scsp_dcs *, void *);
81 int scsp_ca_act_14(Scsp_dcs *, void *);
82 int scsp_ca_act_15(Scsp_dcs *, void *);
83 int scsp_ca_act_16(Scsp_dcs *, void *);
84 int scsp_ca_act_17(Scsp_dcs *, void *);
85 int scsp_ca_act_18(Scsp_dcs *, void *);
86 int scsp_ca_act_19(Scsp_dcs *, void *);
88 static int (*scsp_ca_act_vec[CA_ACTION_CNT])() = {
89 scsp_ca_act_00,
90 scsp_ca_act_01,
91 scsp_ca_act_02,
92 scsp_ca_act_03,
93 scsp_ca_act_04,
94 scsp_ca_act_05,
95 scsp_ca_act_06,
96 scsp_ca_act_07,
97 scsp_ca_act_08,
98 scsp_ca_act_09,
99 scsp_ca_act_10,
100 scsp_ca_act_11,
101 scsp_ca_act_12,
102 scsp_ca_act_13,
103 scsp_ca_act_14,
104 scsp_ca_act_15,
105 scsp_ca_act_16,
106 scsp_ca_act_17,
107 scsp_ca_act_18,
108 scsp_ca_act_19
112 * CA FSM state table
114 static int ca_state_table[SCSP_CAFSM_EVENT_CNT][SCSP_CAFSM_STATE_CNT] = {
115 /* 0 1 2 3 4 5 */
116 { 1, 1, 1, 1, 1, 1 }, /* 0 */
117 { 2, 2, 2, 2, 2, 2 }, /* 1 */
118 { 0, 3, 4, 5, 15, 15 }, /* 2 */
119 { 0, 17, 17, 17, 7, 7 }, /* 3 */
120 { 0, 17, 17, 17, 8, 8 }, /* 4 */
121 { 0, 17, 17, 17, 10, 10 }, /* 5 */
122 { 0, 6, 6, 0, 9, 9 }, /* 6 */
123 { 0, 0, 0, 0, 12, 12 }, /* 7 */
124 { 0, 0, 0, 0, 13, 13 }, /* 8 */
125 { 18, 14, 14, 14, 11, 11 }, /* 9 */
126 { 0, 19, 0, 0, 16, 16 }, /* 10 */
131 * Cache Alignment finite state machine
133 * Arguments:
134 * dcsp pointer to a DCS control block for the neighbor
135 * event the event which has occurred
136 * p pointer to further parameter, if there is one
138 * Returns:
139 * 0 success
140 * errno error encountered
144 scsp_cafsm(Scsp_dcs *dcsp, int event, void *p)
146 int action, rc, state;
149 * Select an action from the state table
151 state = dcsp->sd_ca_state;
152 action = ca_state_table[event][state];
153 if (scsp_trace_mode & SCSP_TRACE_CAFSM) {
154 scsp_trace("CAFSM: state=%d, event=%d, action=%d\n",
155 state, event, action);
157 if (action >= CA_ACTION_CNT || action < 0) {
158 scsp_log(LOG_ERR, "CA FSM--invalid action state=%d, event=%d, action=%d",
159 state, event, action);
160 abort();
164 * Perform the selected action
166 rc = scsp_ca_act_vec[action](dcsp, p);
168 return(rc);
173 * CA finite state machine action 0
174 * Unexpected action -- log an error message and go to Master/Slave
175 * Negotiation. The unexpected action is probably from a protocol
176 * error.
178 * Arguments:
179 * dcsp pointer to DCS control block
180 * p ignored
182 * Returns:
183 * EOPNOTSUPP always returns EOPNOTSUPP
187 scsp_ca_act_00(Scsp_dcs *dcsp, void *p)
189 int rc;
192 * Log an error message
194 scsp_log(LOG_ERR, "CA FSM error--unexpected action, state=%d",
195 dcsp->sd_ca_state);
198 * Set the new state
200 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
203 * Clear out the DCS block
205 scsp_dcs_cleanup(dcsp);
208 * Notify the client I/F FSM
210 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_DOWN, NULL, NULL);
212 return(rc);
217 * CA finite state machine action 1
218 * Hello FSM has reached Bidirectional state -- go to Master/Slave
219 * Negotiation state, make a copy of the client's cache, send first CA
220 * message.
222 * Arguments:
223 * dcsp pointer to DCS control block
224 * p ignored
226 * Returns:
227 * 0 success
228 * errno error encountered
232 scsp_ca_act_01(Scsp_dcs *dcsp, void *p)
234 int i, rc;
235 Scsp_cse *csep, *dupp;
238 * Set the new state
240 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
243 * Make a copy of client's cache entries for cache alignment
245 for (i = 0; i < SCSP_HASHSZ; i++) {
246 for (csep = dcsp->sd_server->ss_cache[i];
247 csep; csep = csep->sc_next) {
248 dupp = scsp_dup_cse(csep);
249 LINK2TAIL(dupp, Scsp_cse, dcsp->sd_ca_csas,
250 sc_next);
255 * Select an initial sequence number
257 dcsp->sd_ca_seq = (int)time(NULL);
260 * Send a CA message
262 rc = scsp_send_ca(dcsp);
263 if (rc == 0) {
264 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
265 scsp_ca_retran_timeout);
268 return(rc);
273 * CA finite state machine action 2
274 * Hello FSM has gone down -- go to Down state
276 * Arguments:
277 * dcsp pointer to DCS control block
278 * p ignored
280 * Returns:
281 * 0 success
282 * errno error encountered
286 scsp_ca_act_02(Scsp_dcs *dcsp, void *p)
288 int rc;
291 * Set the new state
293 dcsp->sd_ca_state = SCSP_CAFSM_DOWN;
296 * Clear out the DCS block
298 scsp_dcs_cleanup(dcsp);
301 * Notify the client I/F FSM
303 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_DOWN, NULL, NULL);
305 return(rc);
310 * CA finite state machine action 3
311 * CA message received -- select Cache Summarize Master or Slave state
313 * Arguments:
314 * dcsp pointer to DCS control block
315 * p pointer to received message
317 * Returns:
318 * 0 success
319 * errno error encountered
323 scsp_ca_act_03(Scsp_dcs *dcsp, void *p)
325 int rc = 0;
326 Scsp_msg *msg = (Scsp_msg *)p;
329 * Check for slave role for LS
331 if (msg->sc_ca->ca_m &&
332 msg->sc_ca->ca_i &&
333 msg->sc_ca->ca_o &&
334 msg->sc_ca->ca_mcp.rec_cnt == 0 &&
335 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
336 &msg->sc_ca->ca_mcp.rid) > 0) {
339 * Stop the retransmit timer
341 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
344 * Set the new state
346 dcsp->sd_ca_state = SCSP_CAFSM_SLAVE;
347 scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM, NULL, NULL);
350 * Save the master's sequence number
352 dcsp->sd_ca_seq = msg->sc_ca->ca_seq;
355 * Send a CA message
357 rc = scsp_send_ca(dcsp);
358 } else
360 * Check for master role for LS
362 if (!msg->sc_ca->ca_m &&
363 !msg->sc_ca->ca_i &&
364 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
365 &msg->sc_ca->ca_mcp.rid) < 0) {
367 * Stop the retransmit timer
369 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
372 * Set the new state
374 dcsp->sd_ca_state = SCSP_CAFSM_MASTER;
375 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM, NULL, NULL);
378 * Process the CA message
380 scsp_process_ca(dcsp, msg->sc_ca);
383 * Increment the sequence number
385 dcsp->sd_ca_seq++;
388 * Send a CA in reply
390 rc = scsp_send_ca(dcsp);
391 if (rc == 0) {
392 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
393 dcsp->sd_ca_rexmt_int,
394 scsp_ca_retran_timeout);
396 } else {
398 * Ignore the message, go to Master/Slave Negotiation
400 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
403 return(rc);
408 * CA finite state machine action 4
409 * CA message received while in Cache Summarize Master state -- process
410 * CA message
412 * Arguments:
413 * dcsp pointer to DCS control block
414 * p pointer to received message
416 * Returns:
417 * 0 success
418 * errno error encountered
422 scsp_ca_act_04(Scsp_dcs *dcsp, void *p)
424 int rc = 0;
425 Scsp_msg *msg = (Scsp_msg *)p;
428 * If the other side thinks he's the master, or if the
429 * initialization bit is set, or if the message is out
430 * of sequence, go back to Master/Slave Negotiation state
432 if (msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
433 msg->sc_ca->ca_seq < dcsp->sd_ca_seq - 1 ||
434 msg->sc_ca->ca_seq > dcsp->sd_ca_seq) {
435 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
436 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
437 scsp_dcs_cleanup(dcsp);
438 return(scsp_ca_act_01(dcsp, NULL));
442 * Ignore any duplicate messages
444 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq - 1) {
445 return(0);
449 * Stop the retransmission timer
451 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
454 * Process the CA message
456 scsp_process_ca(dcsp, msg->sc_ca);
459 * Increment the CA sequence number
461 dcsp->sd_ca_seq++;
464 * If we have no more CSAS records to send and the slave sent
465 * a message with the 'O' bit off, we're done with Summarize
466 * state
468 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
470 * Free any CA message saved for retransmission
472 if (dcsp->sd_ca_rexmt_msg) {
473 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
474 dcsp->sd_ca_rexmt_msg = NULL;
478 * If the CRL is empty, we go directly to Aligned state;
479 * otherwise, we go to Update Cache and send a CSUS
481 if (!dcsp->sd_crl) {
483 * Go to Aligned state
485 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
486 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN, NULL, NULL);
487 } else {
489 * Go to Cache Update state
491 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
492 scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD, NULL, NULL);
493 rc = scsp_send_csus(dcsp);
495 } else {
497 * There are more CSAS records to be exchanged--
498 * continue the cache exchange
500 rc = scsp_send_ca(dcsp);
503 return(rc);
508 * CA finite state machine action 5
509 * CA message received while in Cache Summarize Slave state -- process
510 * CA message
512 * Arguments:
513 * dcsp pointer to DCS control block
514 * p pointer to received message
516 * Returns:
517 * 0 success
518 * errno error encountered
522 scsp_ca_act_05(Scsp_dcs *dcsp, void *p)
524 int rc = 0;
525 Scsp_msg *msg = (Scsp_msg *)p;
528 * If the other side thinks we're the master, or if the
529 * initialization bit is set, or if the message is out
530 * of sequence, go back to Master/Slave Negotiation state
532 if (!msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
533 msg->sc_ca->ca_seq < dcsp->sd_ca_seq ||
534 msg->sc_ca->ca_seq > dcsp->sd_ca_seq + 1) {
535 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
536 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
537 scsp_dcs_cleanup(dcsp);
538 return(scsp_ca_act_01(dcsp, NULL));
542 * If this is a duplicate, retransmit the last message
544 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq) {
545 if (dcsp->sd_ca_rexmt_msg) {
546 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
547 if (rc == 0) {
548 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
549 dcsp->sd_ca_rexmt_int,
550 scsp_ca_retran_timeout);
553 return(rc);
557 * Free the last CA message
559 if (dcsp->sd_ca_rexmt_msg) {
560 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
561 dcsp->sd_ca_rexmt_msg = NULL;
565 * Process the CA message
567 scsp_process_ca(dcsp, msg->sc_ca);
570 * Increment the CA sequence number
572 dcsp->sd_ca_seq++;
575 * Answer the CA message
577 rc = scsp_send_ca(dcsp);
578 if (rc)
579 return(rc);
582 * If we're done sending CSAS records and the other side is,
583 * too, we're done with Summarize state
585 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
587 * If the CRL is empty, we go directly to Aligned state;
588 * otherwise, we go to Update Cache and send a CSUS
590 if (!dcsp->sd_crl) {
592 * Go to Aligned state
594 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
595 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN, NULL, NULL);
596 } else {
598 * Go to Cache Update state
600 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
601 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
602 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
603 dcsp->sd_ca_rexmt_int,
604 scsp_ca_retran_timeout);
605 scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD, NULL, NULL);
606 rc = scsp_send_csus(dcsp);
610 return(rc);
615 * CA finite state machine action 6
616 * Retransmit timer expired -- retransmit last CA message
618 * Arguments:
619 * dcsp pointer to DCS control block
620 * p ignored
622 * Returns:
623 * 0 success
624 * errno error encountered
628 scsp_ca_act_06(Scsp_dcs *dcsp, void *p)
630 int rc;
633 * Resend the CA message
635 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
638 * Restart the retransmit timer
640 if (rc == 0) {
641 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
642 scsp_ca_retran_timeout);
645 return(rc);
650 * CA finite state machine action 7
651 * CSU Solicit received -- send it to the client interface FSM
653 * Arguments:
654 * dcsp pointer to DCS control block
655 * p pointer to received message
657 * Returns:
658 * 0 success
659 * errno error encountered
663 scsp_ca_act_07(Scsp_dcs *dcsp, void *p)
665 int rc;
666 Scsp_msg *msg = (Scsp_msg *)p;
669 * Cancel the CA retransmit timer and free any CA message
670 * saved for retransmission
672 if (dcsp->sd_ca_rexmt_msg) {
673 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
674 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
675 dcsp->sd_ca_rexmt_msg = NULL;
679 * Pass the CSUS to the client interface FSM
681 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_SOL, msg, NULL);
683 return(rc);
688 * CA finite state machine action 8
689 * CSU Request received -- pass it to the client interface FSM
691 * Arguments:
692 * dcsp pointer to DCS control block
693 * p pointer to received message
695 * Returns:
696 * 0 success
697 * errno error encountered
701 scsp_ca_act_08(Scsp_dcs *dcsp, void *p)
703 int rc;
704 Scsp_msg *msg = (Scsp_msg *)p;
705 Scsp_csa *csap;
708 * Check whether this messages answers a CSUS
710 scsp_csus_ack(dcsp, msg);
713 * If all CSAs requestd in CSUS messages have been
714 * received, the cache is aligned, so go to Aligned State
716 if (!dcsp->sd_csus_rexmt_msg && !dcsp->sd_crl &&
717 dcsp->sd_ca_state != SCSP_CAFSM_ALIGNED) {
718 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
719 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN, NULL, NULL);
723 * Pass the CSU Req to the client interface FSM
725 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_REQ, msg, NULL);
728 * Move the CSA chain from the message to the list of
729 * requests that need acknowledgements
731 for (csap = msg->sc_csu_msg->csu_csa_rec; csap;
732 csap = csap->next) {
733 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
735 msg->sc_csu_msg->csu_csa_rec = NULL;
737 return(rc);
742 * CA finite state machine action 9
743 * CA Retransmit timer expired in Update Cache or Aligned state--free
744 * the saved CA message
746 * Arguments:
747 * dcsp pointer to DCS control block
748 * p ignored
750 * Returns:
751 * 0 success
752 * errno error encountered
756 scsp_ca_act_09(Scsp_dcs *dcsp, void *p)
759 * Free any CA message saved for retransmission
761 if (dcsp->sd_ca_rexmt_msg) {
762 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
763 dcsp->sd_ca_rexmt_msg = NULL;
766 return(0);
771 * CA finite state machine action 10
772 * CSU Reply received -- Process the message
774 * Arguments:
775 * dcsp pointer to DCS control block
776 * p pointer to received message
778 * Returns:
779 * 0 success
780 * errno error encountered
784 scsp_ca_act_10(Scsp_dcs *dcsp, void *p)
786 int rc = 0;
787 Scsp_msg *msg = (Scsp_msg *)p;
788 Scsp_csu_rexmt *rxp, *next_rxp;
789 Scsp_csa *csap, *next_csap, *mcp;
792 * Dequeue acknowledged CSAs. For each CSAS in the received
793 * message, find the corresponding CSA on the CSU Request
794 * retransmit queue. Remove the CSA from the queue; if this
795 * results in the retransmit queue entry being empty, delete
796 * the entry. If the DCS has a newer CSA, send a CSUS to
797 * request it.
799 * Caution--potentially confusing lack of indentation ahead.
801 for (mcp = msg->sc_csu_msg->csu_csa_rec; mcp;
802 mcp = mcp->next) {
803 for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = next_rxp) {
804 next_rxp = rxp->sr_next;
805 for (csap = rxp->sr_csa; csap; csap = next_csap) {
806 next_csap = csap->next;
807 if (scsp_cmp_key(&csap->key, &mcp->key) ||
808 scsp_cmp_id(&csap->oid, &mcp->oid))
809 continue;
811 * Found a CSA whose key and ID are equal to
812 * those in the CSU Reply
814 if (csap->seq == mcp->seq) {
816 * The queued seq no is equal to the
817 * received seq no--the CSA is acknowledged
819 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
820 SCSP_FREE_CSA(csap);
821 } else if (csap->seq < mcp->seq) {
823 * Queued seq no is less than received.
824 * We must dequeue the CSA and send a
825 * CSUS to request the more-up-to-date
826 * cache entry.
828 UNLINK(mcp, Scsp_csa,
829 msg->sc_csu_msg->csu_csa_rec,
830 next);
831 LINK2TAIL(mcp, Scsp_csa, dcsp->sd_crl, next);
832 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
833 SCSP_FREE_CSA(csap);
834 if (!dcsp->sd_csus_rexmt_msg) {
835 rc = scsp_send_csus(dcsp);
836 if (rc) {
837 return(rc);
842 * Queued seq no is greater than
843 * received. Ignore the received CSAS.
847 * If the retransmission block is empty, stop the
848 * timer and free it
850 if (!rxp->sr_csa) {
851 HARP_CANCEL(&rxp->sr_t);
852 UNLINK(rxp, Scsp_csu_rexmt,
853 dcsp->sd_csu_rexmt, sr_next);
854 UM_FREE(rxp);
857 break;
858 } /* for (csap = ... */
859 } /* for (rxp = ... */
860 } /* for (mcp = ... */
862 return(rc);
867 * CA finite state machine action 11
868 * Updated cache entry -- update the summary cache and send a
869 * CSU Request
871 * Arguments:
872 * dcsp pointer to DCS control block
873 * p pointer to CSA describing new cache entry
875 * Returns:
876 * 0 success
877 * errno error encountered
881 scsp_ca_act_11(Scsp_dcs *dcsp, void *p)
883 int rc, state;
884 Scsp_csa *csap = (Scsp_csa *)p;
885 Scsp_cse *csep;
888 * Get the state of the CSA
890 switch(dcsp->sd_server->ss_pid) {
891 case SCSP_PROTO_ATMARP:
892 state = csap->atmarp_data->sa_state;
893 break;
894 default:
895 SCSP_FREE_CSA(csap);
896 return(EINVAL);
899 if (state < SCSP_ASTATE_NEW || state > SCSP_ASTATE_DEL) {
900 SCSP_FREE_CSA(csap);
901 return(EINVAL);
905 * Look up the cache summary entry for the CSA
907 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
910 * Process ATMARP entries
912 if (dcsp->sd_server->ss_pid == SCSP_PROTO_ATMARP) {
913 switch(state) {
914 case SCSP_ASTATE_NEW:
915 case SCSP_ASTATE_UPD:
917 * Add the entry if we don't have it already
919 if (!csep) {
920 csep = (Scsp_cse *)UM_ALLOC(
921 sizeof(Scsp_cse));
922 if (!csep)
923 scsp_mem_err("scsp_ca_act_11: sizeof(Scsp_cse)");
924 UM_ZERO(csep, sizeof(Scsp_cse));
926 csep->sc_key = csap->key;
927 SCSP_ADD(dcsp->sd_server, csep);
931 * Update the cache summary entry
933 csep->sc_seq = csap->seq;
934 csep->sc_oid = csap->oid;
935 break;
936 case SCSP_ASTATE_DEL:
938 * Delete any entry, but don't send the
939 * delete to the DCS
941 if (csep) {
942 SCSP_DELETE(dcsp->sd_server, csep);
943 UM_FREE(csep);
946 SCSP_FREE_CSA(csap);
947 return(0);
952 * Send the CSA in a CSU Request
954 csap->trans_ct = 0;
955 rc = scsp_send_csu_req(dcsp, csap);
957 return(rc);
962 * CA finite state machine action 12
963 * CSUS retransmit timer expired--send a CSUS with any pending CSA
964 * records
966 * Arguments:
967 * dcsp pointer to DCS control block
968 * p ignored
970 * Returns:
971 * 0 success
972 * errno error encountered
976 scsp_ca_act_12(Scsp_dcs *dcsp, void *p)
978 int rc;
980 rc = scsp_send_csus(dcsp);
982 return(rc);
987 * CA finite state machine action 13
988 * CSU retransmit timer fired in Update or Aligned state--
989 * retransmit CSU Req
991 * Arguments:
992 * dcsp pointer to DCS control block
993 * p pointer to retransmission block whose timer fired
995 * Returns:
996 * 0 success
997 * errno error encountered
1001 scsp_ca_act_13(Scsp_dcs *dcsp, void *p)
1003 int rc = 0;
1004 Scsp_csu_rexmt *rxp = (Scsp_csu_rexmt *)p;
1005 Scsp_csa *csap, *csap1, *next_csap;
1008 * Unlink and free the retransmit request block
1010 csap = rxp->sr_csa;
1011 UNLINK(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
1012 UM_FREE(rxp);
1015 * Increment the transmission count for the CSAs in the request
1017 for (csap1 = csap; csap1; csap1 = next_csap) {
1018 next_csap = csap1->next;
1019 csap1->trans_ct++;
1020 if (csap1->trans_ct >= dcsp->sd_csu_rexmt_max) {
1022 * We've already sent this as many times as
1023 * the limit allows. Drop this CSA.
1025 UNLINK(csap1, Scsp_csa, csap, next);
1026 SCSP_FREE_CSA(csap1);
1031 * Send another CSU Request with the CSA list, if it isn't
1032 * empty now
1034 if (csap) {
1035 rc = scsp_send_csu_req(dcsp, csap);
1038 return(rc);
1043 * CA finite state machine action 14
1044 * Updated cache entry in Master/Slave Negotiation, Master, or
1045 * Slave state--add entry to cache and CSA list
1047 * Arguments:
1048 * dcsp pointer to DCS control block
1049 * p pointer to new cache summary entry
1051 * Returns:
1052 * 0 success
1053 * errno error encountered
1057 scsp_ca_act_14(Scsp_dcs *dcsp, void *p)
1059 Scsp_csa *csap = (Scsp_csa *)p;
1060 Scsp_cse *csep, *csep1;
1063 * Check to see whether we already have this
1065 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
1068 * If we don't already have it and it's not being deleted,
1069 * build a new cache summary entry
1071 if (!csep && !csap->null) {
1073 * Get memory for a new entry
1075 csep = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
1076 if (!csep) {
1077 scsp_mem_err("scsp_ca_act_14: sizeof(Scsp_cse)");
1079 UM_ZERO(csep, sizeof(Scsp_cse));
1082 * Fill out the new cache entry
1084 csep->sc_seq = csap->seq;
1085 csep->sc_key = csap->key;
1086 csep->sc_oid = csap->oid;
1089 * Duplicate the new cache entry
1091 csep1 = scsp_dup_cse(csep);
1094 * Add entry to the summary cache and the CSAS list
1096 SCSP_ADD(dcsp->sd_server, csep);
1097 LINK2TAIL(csep1, Scsp_cse, dcsp->sd_ca_csas, sc_next);
1098 } else {
1100 * We already have the entry. Find it on the CSAS
1101 * list.
1103 for (csep1 = dcsp->sd_ca_csas; csep1;
1104 csep1 = csep1->sc_next) {
1105 if (scsp_cmp_key(&csep->sc_key,
1106 &csep1->sc_key) == 0)
1107 break;
1111 * Update or delete the entry
1113 if (csap->null) {
1115 * The null flag is set--delete the entry
1117 SCSP_DELETE(dcsp->sd_server, csep);
1118 UM_FREE(csep);
1119 if (csep1) {
1120 UNLINK(csep1, Scsp_cse,
1121 dcsp->sd_ca_csas,
1122 sc_next);
1123 UM_FREE(csep1);
1125 } else {
1127 * Update the entry
1129 csep->sc_seq = csap->seq;
1130 csep->sc_oid = csap->oid;
1131 if (!csep1) {
1132 csep1 = scsp_dup_cse(csep);
1133 LINK2TAIL(csep1, Scsp_cse,
1134 dcsp->sd_ca_csas, sc_next);
1135 } else {
1136 csep1->sc_seq = csap->seq;
1137 csep1->sc_oid = csap->oid;
1142 return(0);
1147 * CA finite state machine action 15
1148 * CA message received in Update Cache state--if we have a saved CA
1149 * message, retransmit it; otherwise, go to Master/Slave Negotiation
1150 * state
1152 * Arguments:
1153 * dcsp pointer to DCS control block
1154 * p ignored
1156 * Returns:
1157 * 0 success
1158 * errno error encountered
1162 scsp_ca_act_15(Scsp_dcs *dcsp, void *p)
1164 int rc;
1165 Scsp_msg *msg = (Scsp_msg *)p;
1168 * If we don't have a saved CA message, or the sequence no. in
1169 * the received message isn't right, fall back to Master/Slave
1170 * Negotiation state
1172 if (!dcsp->sd_ca_rexmt_msg ||
1173 msg->sc_ca->ca_seq != dcsp->sd_ca_seq) {
1174 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
1175 scsp_dcs_cleanup(dcsp);
1176 rc = scsp_ca_act_01(dcsp, NULL);
1177 } else {
1179 * Retransmit the saved CA message and reset the
1180 * CA timer
1182 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
1183 if (rc == 0) {
1184 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
1185 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
1186 dcsp->sd_ca_rexmt_int,
1187 scsp_ca_retran_timeout);
1191 return(rc);
1196 * CA finite state machine action 16
1197 * Update Response received from client in Update Cache or Aligned
1198 * state. Move the acknowledged CSA to the acknowledged queue. If
1199 * the list of CSAs pending acknowledgement is empty, send a CSU
1200 * Reply.
1202 * Arguments:
1203 * dcsp pointer to DCS control block
1204 * p pointer to message from client
1206 * Returns:
1207 * 0 success
1208 * errno error encountered
1212 scsp_ca_act_16(Scsp_dcs *dcsp, void *p)
1214 int found, rc = 0;
1215 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1216 Scsp_csa *csap;
1219 * Find the acknowledged CSA
1221 for (csap = dcsp->sd_csu_ack_pend, found = 0; csap && !found;
1222 csap = csap->next) {
1223 switch (dcsp->sd_server->ss_pid) {
1224 case SCSP_PROTO_ATMARP:
1225 found = ((scsp_cmp_key(&csap->key,
1226 &cmsg->si_atmarp.sa_key) == 0) &&
1227 (scsp_cmp_id(&csap->oid,
1228 &cmsg->si_atmarp.sa_oid) == 0));
1229 break;
1230 default:
1232 * Protocol not implemented
1234 return(EPROTONOSUPPORT);
1236 if (found)
1237 break;
1240 if (!found) {
1241 if (scsp_trace_mode & SCSP_TRACE_CAFSM) {
1242 scsp_trace("scsp_ca_act_16: can't find CSA entry for Update Response\n");
1244 return(0);
1247 if (cmsg->si_rc == SCSP_RSP_OK) {
1249 * The server accepted the cache entry
1253 * Update SCSP's cache
1255 scsp_update_cache(dcsp, csap);
1258 * Send this CSA to any other DCSs in the server group
1260 rc = scsp_propagate_csa(dcsp, csap);
1264 * Move the CSA from the ACK pending queue to the
1265 * acknowledged queue
1267 UNLINK(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
1268 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack, next);
1269 if (!dcsp->sd_csu_ack_pend) {
1271 * ACK pending list is empty--send a CSU Reply
1273 csap = dcsp->sd_csu_ack;
1274 dcsp->sd_csu_ack = NULL;
1275 rc = scsp_send_csu_reply(dcsp, csap);
1278 return(rc);
1283 * CA finite state machine action 17
1284 * Ignore an event.
1286 * Arguments:
1287 * dcsp pointer to DCS control block
1288 * p ignored
1290 * Returns:
1291 * always returns 0
1295 scsp_ca_act_17(Scsp_dcs *dcsp, void *p)
1297 return(0);
1302 * CA finite state machine action 18
1303 * Updated cache entry in Down state--add entry to summary cache
1305 * Arguments:
1306 * dcsp pointer to DCS control block
1307 * p pointer to new cache summary entry
1309 * Returns:
1310 * 0 success
1311 * errno error encountered
1315 scsp_ca_act_18(Scsp_dcs *dcsp, void *p)
1317 Scsp_csa *csap = (Scsp_csa *)p;
1320 * Update the cache as appropriate
1322 scsp_update_cache(dcsp, csap);
1324 return(0);
1329 * CA finite state machine action 19
1330 * Update Response received from client in Master/Slave Negotiation
1331 * state. Update the cache as appropriate.
1333 * Arguments:
1334 * dcsp pointer to DCS control block
1335 * p pointer to message from client
1337 * Returns:
1338 * 0 success
1339 * errno error encountered
1343 scsp_ca_act_19(Scsp_dcs *dcsp, void *p)
1345 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1346 Scsp_csa *csap;
1349 * Ignore the message if the client rejected the update
1351 if (cmsg->si_rc != SCSP_RSP_OK) {
1352 return(0);
1356 * Create a CSAS from the client's update
1358 csap = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
1359 if (!csap) {
1360 scsp_mem_err("scsp_ca_act_19: sizeof(Scsp_csa)");
1362 UM_ZERO(csap, sizeof(Scsp_csa));
1364 csap->hops = 1;
1365 switch (dcsp->sd_server->ss_pid) {
1366 case SCSP_PROTO_ATMARP:
1367 csap->null = cmsg->si_atmarp.sa_state ==
1368 SCSP_ASTATE_DEL;
1369 csap->seq = cmsg->si_atmarp.sa_seq;
1370 csap->key = cmsg->si_atmarp.sa_key;
1371 csap->oid = cmsg->si_atmarp.sa_oid;
1372 break;
1373 default:
1374 return(EINVAL);
1378 * Update SCSP's cache
1380 scsp_update_cache(dcsp, csap);
1382 return(0);