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>
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>
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])() = {
114 static int ca_state_table[SCSP_CAFSM_EVENT_CNT][SCSP_CAFSM_STATE_CNT] = {
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
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
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);
164 * Perform the selected action
166 rc = scsp_ca_act_vec[action](dcsp, p);
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
179 * dcsp pointer to DCS control block
183 * EOPNOTSUPP always returns EOPNOTSUPP
187 scsp_ca_act_00(Scsp_dcs *dcsp, void *p)
192 * Log an error message
194 scsp_log(LOG_ERR, "CA FSM error--unexpected action, state=%d",
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, (Scsp_msg *)0,
218 * CA finite state machine action 1
219 * Hello FSM has reached Bidirectional state -- go to Master/Slave
220 * Negotiation state, make a copy of the client's cache, send first CA
224 * dcsp pointer to DCS control block
229 * errno error encountered
233 scsp_ca_act_01(Scsp_dcs *dcsp, void *p)
236 Scsp_cse *csep, *dupp;
241 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
244 * Make a copy of client's cache entries for cache alignment
246 for (i = 0; i < SCSP_HASHSZ; i++) {
247 for (csep = dcsp->sd_server->ss_cache[i];
248 csep; csep = csep->sc_next) {
249 dupp = scsp_dup_cse(csep);
250 LINK2TAIL(dupp, Scsp_cse, dcsp->sd_ca_csas,
256 * Select an initial sequence number
258 dcsp->sd_ca_seq = (int)time((time_t *)0);
263 rc = scsp_send_ca(dcsp);
265 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
266 scsp_ca_retran_timeout);
274 * CA finite state machine action 2
275 * Hello FSM has gone down -- go to Down state
278 * dcsp pointer to DCS control block
283 * errno error encountered
287 scsp_ca_act_02(Scsp_dcs *dcsp, void *p)
294 dcsp->sd_ca_state = SCSP_CAFSM_DOWN;
297 * Clear out the DCS block
299 scsp_dcs_cleanup(dcsp);
302 * Notify the client I/F FSM
304 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_DOWN, (Scsp_msg *)0,
312 * CA finite state machine action 3
313 * CA message received -- select Cache Summarize Master or Slave state
316 * dcsp pointer to DCS control block
317 * p pointer to received message
321 * errno error encountered
325 scsp_ca_act_03(Scsp_dcs *dcsp, void *p)
328 Scsp_msg *msg = (Scsp_msg *)p;
331 * Check for slave role for LS
333 if (msg->sc_ca->ca_m &&
336 msg->sc_ca->ca_mcp.rec_cnt == 0 &&
337 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
338 &msg->sc_ca->ca_mcp.rid) > 0) {
341 * Stop the retransmit timer
343 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
348 dcsp->sd_ca_state = SCSP_CAFSM_SLAVE;
349 scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM,
350 (Scsp_msg *)0, (Scsp_if_msg *)0);
353 * Save the master's sequence number
355 dcsp->sd_ca_seq = msg->sc_ca->ca_seq;
360 rc = scsp_send_ca(dcsp);
363 * Check for master role for LS
365 if (!msg->sc_ca->ca_m &&
367 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
368 &msg->sc_ca->ca_mcp.rid) < 0) {
370 * Stop the retransmit timer
372 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
377 dcsp->sd_ca_state = SCSP_CAFSM_MASTER;
378 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM,
379 (Scsp_msg *)0, (Scsp_if_msg *)0);
382 * Process the CA message
384 scsp_process_ca(dcsp, msg->sc_ca);
387 * Increment the sequence number
394 rc = scsp_send_ca(dcsp);
396 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
397 dcsp->sd_ca_rexmt_int,
398 scsp_ca_retran_timeout);
402 * Ignore the message, go to Master/Slave Negotiation
404 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
412 * CA finite state machine action 4
413 * CA message received while in Cache Summarize Master state -- process
417 * dcsp pointer to DCS control block
418 * p pointer to received message
422 * errno error encountered
426 scsp_ca_act_04(Scsp_dcs *dcsp, void *p)
429 Scsp_msg *msg = (Scsp_msg *)p;
432 * If the other side thinks he's the master, or if the
433 * initialization bit is set, or if the message is out
434 * of sequence, go back to Master/Slave Negotiation state
436 if (msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
437 msg->sc_ca->ca_seq < dcsp->sd_ca_seq - 1 ||
438 msg->sc_ca->ca_seq > dcsp->sd_ca_seq) {
439 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
440 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
441 scsp_dcs_cleanup(dcsp);
442 return(scsp_ca_act_01(dcsp, (Scsp_msg *)0));
446 * Ignore any duplicate messages
448 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq - 1) {
453 * Stop the retransmission timer
455 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
458 * Process the CA message
460 scsp_process_ca(dcsp, msg->sc_ca);
463 * Increment the CA sequence number
468 * If we have no more CSAS records to send and the slave sent
469 * a message with the 'O' bit off, we're done with Summarize
472 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
474 * Free any CA message saved for retransmission
476 if (dcsp->sd_ca_rexmt_msg) {
477 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
478 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
482 * If the CRL is empty, we go directly to Aligned state;
483 * otherwise, we go to Update Cache and send a CSUS
487 * Go to Aligned state
489 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
490 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
495 * Go to Cache Update state
497 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
498 scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD,
501 rc = scsp_send_csus(dcsp);
505 * There are more CSAS records to be exchanged--
506 * continue the cache exchange
508 rc = scsp_send_ca(dcsp);
516 * CA finite state machine action 5
517 * CA message received while in Cache Summarize Slave state -- process
521 * dcsp pointer to DCS control block
522 * p pointer to received message
526 * errno error encountered
530 scsp_ca_act_05(Scsp_dcs *dcsp, void *p)
533 Scsp_msg *msg = (Scsp_msg *)p;
536 * If the other side thinks we're the master, or if the
537 * initialization bit is set, or if the message is out
538 * of sequence, go back to Master/Slave Negotiation state
540 if (!msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
541 msg->sc_ca->ca_seq < dcsp->sd_ca_seq ||
542 msg->sc_ca->ca_seq > dcsp->sd_ca_seq + 1) {
543 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
544 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
545 scsp_dcs_cleanup(dcsp);
546 return(scsp_ca_act_01(dcsp, (Scsp_msg *)0));
550 * If this is a duplicate, retransmit the last message
552 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq) {
553 if (dcsp->sd_ca_rexmt_msg) {
554 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
556 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
557 dcsp->sd_ca_rexmt_int,
558 scsp_ca_retran_timeout);
565 * Free the last CA message
567 if (dcsp->sd_ca_rexmt_msg) {
568 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
569 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
573 * Process the CA message
575 scsp_process_ca(dcsp, msg->sc_ca);
578 * Increment the CA sequence number
583 * Answer the CA message
585 rc = scsp_send_ca(dcsp);
590 * If we're done sending CSAS records and the other side is,
591 * too, we're done with Summarize state
593 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
595 * If the CRL is empty, we go directly to Aligned state;
596 * otherwise, we go to Update Cache and send a CSUS
600 * Go to Aligned state
602 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
603 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
608 * Go to Cache Update state
610 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
611 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
612 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
613 dcsp->sd_ca_rexmt_int,
614 scsp_ca_retran_timeout);
615 scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD,
618 rc = scsp_send_csus(dcsp);
627 * CA finite state machine action 6
628 * Retransmit timer expired -- retransmit last CA message
631 * dcsp pointer to DCS control block
636 * errno error encountered
640 scsp_ca_act_06(Scsp_dcs *dcsp, void *p)
645 * Resend the CA message
647 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
650 * Restart the retransmit timer
653 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
654 scsp_ca_retran_timeout);
662 * CA finite state machine action 7
663 * CSU Solicit received -- send it to the client interface FSM
666 * dcsp pointer to DCS control block
667 * p pointer to received message
671 * errno error encountered
675 scsp_ca_act_07(Scsp_dcs *dcsp, void *p)
678 Scsp_msg *msg = (Scsp_msg *)p;
681 * Cancel the CA retransmit timer and free any CA message
682 * saved for retransmission
684 if (dcsp->sd_ca_rexmt_msg) {
685 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
686 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
687 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
691 * Pass the CSUS to the client interface FSM
693 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_SOL, msg,
701 * CA finite state machine action 8
702 * CSU Request received -- pass it to the client interface FSM
705 * dcsp pointer to DCS control block
706 * p pointer to received message
710 * errno error encountered
714 scsp_ca_act_08(Scsp_dcs *dcsp, void *p)
717 Scsp_msg *msg = (Scsp_msg *)p;
721 * Check whether this messages answers a CSUS
723 scsp_csus_ack(dcsp, msg);
726 * If all CSAs requestd in CSUS messages have been
727 * received, the cache is aligned, so go to Aligned State
729 if (!dcsp->sd_csus_rexmt_msg && !dcsp->sd_crl &&
730 dcsp->sd_ca_state != SCSP_CAFSM_ALIGNED) {
731 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
732 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
733 (Scsp_msg *)0, (Scsp_if_msg *)0);
737 * Pass the CSU Req to the client interface FSM
739 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_REQ, msg,
743 * Move the CSA chain from the message to the list of
744 * requests that need acknowledgements
746 for (csap = msg->sc_csu_msg->csu_csa_rec; csap;
748 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
750 msg->sc_csu_msg->csu_csa_rec = (Scsp_csa *)0;
757 * CA finite state machine action 9
758 * CA Retransmit timer expired in Update Cache or Aligned state--free
759 * the saved CA message
762 * dcsp pointer to DCS control block
767 * errno error encountered
771 scsp_ca_act_09(Scsp_dcs *dcsp, void *p)
774 * Free any CA message saved for retransmission
776 if (dcsp->sd_ca_rexmt_msg) {
777 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
778 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
786 * CA finite state machine action 10
787 * CSU Reply received -- Process the message
790 * dcsp pointer to DCS control block
791 * p pointer to received message
795 * errno error encountered
799 scsp_ca_act_10(Scsp_dcs *dcsp, void *p)
802 Scsp_msg *msg = (Scsp_msg *)p;
803 Scsp_csu_rexmt *rxp, *next_rxp;
804 Scsp_csa *csap, *next_csap, *mcp;
807 * Dequeue acknowledged CSAs. For each CSAS in the received
808 * message, find the corresponding CSA on the CSU Request
809 * retransmit queue. Remove the CSA from the queue; if this
810 * results in the retransmit queue entry being empty, delete
811 * the entry. If the DCS has a newer CSA, send a CSUS to
814 * Caution--potentially confusing lack of indentation ahead.
816 for (mcp = msg->sc_csu_msg->csu_csa_rec; mcp;
818 for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = next_rxp) {
819 next_rxp = rxp->sr_next;
820 for (csap = rxp->sr_csa; csap; csap = next_csap) {
821 next_csap = csap->next;
822 if (scsp_cmp_key(&csap->key, &mcp->key) ||
823 scsp_cmp_id(&csap->oid, &mcp->oid))
826 * Found a CSA whose key and ID are equal to
827 * those in the CSU Reply
829 if (csap->seq == mcp->seq) {
831 * The queued seq no is equal to the
832 * received seq no--the CSA is acknowledged
834 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
836 } else if (csap->seq < mcp->seq) {
838 * Queued seq no is less than received.
839 * We must dequeue the CSA and send a
840 * CSUS to request the more-up-to-date
843 UNLINK(mcp, Scsp_csa,
844 msg->sc_csu_msg->csu_csa_rec,
846 LINK2TAIL(mcp, Scsp_csa, dcsp->sd_crl, next);
847 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
849 if (!dcsp->sd_csus_rexmt_msg) {
850 rc = scsp_send_csus(dcsp);
857 * Queued seq no is greater than
858 * received. Ignore the received CSAS.
862 * If the retransmission block is empty, stop the
866 HARP_CANCEL(&rxp->sr_t);
867 UNLINK(rxp, Scsp_csu_rexmt,
868 dcsp->sd_csu_rexmt, sr_next);
873 } /* for (csap = ... */
874 } /* for (rxp = ... */
875 } /* for (mcp = ... */
882 * CA finite state machine action 11
883 * Updated cache entry -- update the summary cache and send a
887 * dcsp pointer to DCS control block
888 * p pointer to CSA describing new cache entry
892 * errno error encountered
896 scsp_ca_act_11(Scsp_dcs *dcsp, void *p)
899 Scsp_csa *csap = (Scsp_csa *)p;
903 * Get the state of the CSA
905 switch(dcsp->sd_server->ss_pid) {
906 case SCSP_PROTO_ATMARP:
907 state = csap->atmarp_data->sa_state;
914 if (state < SCSP_ASTATE_NEW || state > SCSP_ASTATE_DEL) {
920 * Look up the cache summary entry for the CSA
922 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
925 * Process ATMARP entries
927 if (dcsp->sd_server->ss_pid == SCSP_PROTO_ATMARP) {
929 case SCSP_ASTATE_NEW:
930 case SCSP_ASTATE_UPD:
932 * Add the entry if we don't have it already
935 csep = (Scsp_cse *)UM_ALLOC(
938 scsp_mem_err("scsp_ca_act_11: sizeof(Scsp_cse)");
939 UM_ZERO(csep, sizeof(Scsp_cse));
941 csep->sc_key = csap->key;
942 SCSP_ADD(dcsp->sd_server, csep);
946 * Update the cache summary entry
948 csep->sc_seq = csap->seq;
949 csep->sc_oid = csap->oid;
951 case SCSP_ASTATE_DEL:
953 * Delete any entry, but don't send the
957 SCSP_DELETE(dcsp->sd_server, csep);
967 * Send the CSA in a CSU Request
970 rc = scsp_send_csu_req(dcsp, csap);
977 * CA finite state machine action 12
978 * CSUS retransmit timer expired--send a CSUS with any pending CSA
982 * dcsp pointer to DCS control block
987 * errno error encountered
991 scsp_ca_act_12(Scsp_dcs *dcsp, void *p)
995 rc = scsp_send_csus(dcsp);
1002 * CA finite state machine action 13
1003 * CSU retransmit timer fired in Update or Aligned state--
1004 * retransmit CSU Req
1007 * dcsp pointer to DCS control block
1008 * p pointer to retransmission block whose timer fired
1012 * errno error encountered
1016 scsp_ca_act_13(Scsp_dcs *dcsp, void *p)
1019 Scsp_csu_rexmt *rxp = (Scsp_csu_rexmt *)p;
1020 Scsp_csa *csap, *csap1, *next_csap;
1023 * Unlink and free the retransmit request block
1026 UNLINK(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
1030 * Increment the transmission count for the CSAs in the request
1032 for (csap1 = csap; csap1; csap1 = next_csap) {
1033 next_csap = csap1->next;
1035 if (csap1->trans_ct >= dcsp->sd_csu_rexmt_max) {
1037 * We've already sent this as many times as
1038 * the limit allows. Drop this CSA.
1040 UNLINK(csap1, Scsp_csa, csap, next);
1041 SCSP_FREE_CSA(csap1);
1046 * Send another CSU Request with the CSA list, if it isn't
1050 rc = scsp_send_csu_req(dcsp, csap);
1058 * CA finite state machine action 14
1059 * Updated cache entry in Master/Slave Negotiation, Master, or
1060 * Slave state--add entry to cache and CSA list
1063 * dcsp pointer to DCS control block
1064 * p pointer to new cache summary entry
1068 * errno error encountered
1072 scsp_ca_act_14(Scsp_dcs *dcsp, void *p)
1074 Scsp_csa *csap = (Scsp_csa *)p;
1075 Scsp_cse *csep, *csep1;
1078 * Check to see whether we already have this
1080 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
1083 * If we don't already have it and it's not being deleted,
1084 * build a new cache summary entry
1086 if (!csep && !csap->null) {
1088 * Get memory for a new entry
1090 csep = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
1092 scsp_mem_err("scsp_ca_act_14: sizeof(Scsp_cse)");
1094 UM_ZERO(csep, sizeof(Scsp_cse));
1097 * Fill out the new cache entry
1099 csep->sc_seq = csap->seq;
1100 csep->sc_key = csap->key;
1101 csep->sc_oid = csap->oid;
1104 * Duplicate the new cache entry
1106 csep1 = scsp_dup_cse(csep);
1109 * Add entry to the summary cache and the CSAS list
1111 SCSP_ADD(dcsp->sd_server, csep);
1112 LINK2TAIL(csep1, Scsp_cse, dcsp->sd_ca_csas, sc_next);
1115 * We already have the entry. Find it on the CSAS
1118 for (csep1 = dcsp->sd_ca_csas; csep1;
1119 csep1 = csep1->sc_next) {
1120 if (scsp_cmp_key(&csep->sc_key,
1121 &csep1->sc_key) == 0)
1126 * Update or delete the entry
1130 * The null flag is set--delete the entry
1132 SCSP_DELETE(dcsp->sd_server, csep);
1135 UNLINK(csep1, Scsp_cse,
1144 csep->sc_seq = csap->seq;
1145 csep->sc_oid = csap->oid;
1147 csep1 = scsp_dup_cse(csep);
1148 LINK2TAIL(csep1, Scsp_cse,
1149 dcsp->sd_ca_csas, sc_next);
1151 csep1->sc_seq = csap->seq;
1152 csep1->sc_oid = csap->oid;
1162 * CA finite state machine action 15
1163 * CA message received in Update Cache state--if we have a saved CA
1164 * message, retransmit it; otherwise, go to Master/Slave Negotiation
1168 * dcsp pointer to DCS control block
1173 * errno error encountered
1177 scsp_ca_act_15(Scsp_dcs *dcsp, void *p)
1180 Scsp_msg *msg = (Scsp_msg *)p;
1183 * If we don't have a saved CA message, or the sequence no. in
1184 * the received message isn't right, fall back to Master/Slave
1187 if (!dcsp->sd_ca_rexmt_msg ||
1188 msg->sc_ca->ca_seq != dcsp->sd_ca_seq) {
1189 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
1190 scsp_dcs_cleanup(dcsp);
1191 rc = scsp_ca_act_01(dcsp, (Scsp_msg *)0);
1194 * Retransmit the saved CA message and reset the
1197 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
1199 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
1200 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
1201 dcsp->sd_ca_rexmt_int,
1202 scsp_ca_retran_timeout);
1211 * CA finite state machine action 16
1212 * Update Response received from client in Update Cache or Aligned
1213 * state. Move the acknowledged CSA to the acknowledged queue. If
1214 * the list of CSAs pending acknowledgement is empty, send a CSU
1218 * dcsp pointer to DCS control block
1219 * p pointer to message from client
1223 * errno error encountered
1227 scsp_ca_act_16(Scsp_dcs *dcsp, void *p)
1230 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1234 * Find the acknowledged CSA
1236 for (csap = dcsp->sd_csu_ack_pend, found = 0; csap && !found;
1237 csap = csap->next) {
1238 switch (dcsp->sd_server->ss_pid) {
1239 case SCSP_PROTO_ATMARP:
1240 found = ((scsp_cmp_key(&csap->key,
1241 &cmsg->si_atmarp.sa_key) == 0) &&
1242 (scsp_cmp_id(&csap->oid,
1243 &cmsg->si_atmarp.sa_oid) == 0));
1247 * Protocol not implemented
1249 return(EPROTONOSUPPORT);
1256 if (scsp_trace_mode & SCSP_TRACE_CAFSM) {
1257 scsp_trace("scsp_ca_act_16: can't find CSA entry for Update Response\n");
1262 if (cmsg->si_rc == SCSP_RSP_OK) {
1264 * The server accepted the cache entry
1268 * Update SCSP's cache
1270 scsp_update_cache(dcsp, csap);
1273 * Send this CSA to any other DCSs in the server group
1275 rc = scsp_propagate_csa(dcsp, csap);
1279 * Move the CSA from the ACK pending queue to the
1280 * acknowledged queue
1282 UNLINK(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
1283 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack, next);
1284 if (!dcsp->sd_csu_ack_pend) {
1286 * ACK pending list is empty--send a CSU Reply
1288 csap = dcsp->sd_csu_ack;
1289 dcsp->sd_csu_ack = (Scsp_csa *)0;
1290 rc = scsp_send_csu_reply(dcsp, csap);
1298 * CA finite state machine action 17
1302 * dcsp pointer to DCS control block
1310 scsp_ca_act_17(Scsp_dcs *dcsp, void *p)
1317 * CA finite state machine action 18
1318 * Updated cache entry in Down state--add entry to summary cache
1321 * dcsp pointer to DCS control block
1322 * p pointer to new cache summary entry
1326 * errno error encountered
1330 scsp_ca_act_18(Scsp_dcs *dcsp, void *p)
1332 Scsp_csa *csap = (Scsp_csa *)p;
1335 * Update the cache as appropriate
1337 scsp_update_cache(dcsp, csap);
1344 * CA finite state machine action 19
1345 * Update Response received from client in Master/Slave Negotiation
1346 * state. Update the cache as appropriate.
1349 * dcsp pointer to DCS control block
1350 * p pointer to message from client
1354 * errno error encountered
1358 scsp_ca_act_19(Scsp_dcs *dcsp, void *p)
1360 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1364 * Ignore the message if the client rejected the update
1366 if (cmsg->si_rc != SCSP_RSP_OK) {
1371 * Create a CSAS from the client's update
1373 csap = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
1375 scsp_mem_err("scsp_ca_act_19: sizeof(Scsp_csa)");
1377 UM_ZERO(csap, sizeof(Scsp_csa));
1380 switch (dcsp->sd_server->ss_pid) {
1381 case SCSP_PROTO_ATMARP:
1382 csap->null = cmsg->si_atmarp.sa_state ==
1384 csap->seq = cmsg->si_atmarp.sa_seq;
1385 csap->key = cmsg->si_atmarp.sa_key;
1386 csap->oid = cmsg->si_atmarp.sa_oid;
1393 * Update SCSP's cache
1395 scsp_update_cache(dcsp, csap);