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 $
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>
64 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_cafsm.c,v 1.3 1999/08/28 01:15:32 peter Exp $");
71 #define CA_ACTION_CNT 20
72 int scsp_ca_act_00 __P((Scsp_dcs *, void *));
73 int scsp_ca_act_01 __P((Scsp_dcs *, void *));
74 int scsp_ca_act_02 __P((Scsp_dcs *, void *));
75 int scsp_ca_act_03 __P((Scsp_dcs *, void *));
76 int scsp_ca_act_04 __P((Scsp_dcs *, void *));
77 int scsp_ca_act_05 __P((Scsp_dcs *, void *));
78 int scsp_ca_act_06 __P((Scsp_dcs *, void *));
79 int scsp_ca_act_07 __P((Scsp_dcs *, void *));
80 int scsp_ca_act_08 __P((Scsp_dcs *, void *));
81 int scsp_ca_act_09 __P((Scsp_dcs *, void *));
82 int scsp_ca_act_10 __P((Scsp_dcs *, void *));
83 int scsp_ca_act_11 __P((Scsp_dcs *, void *));
84 int scsp_ca_act_12 __P((Scsp_dcs *, void *));
85 int scsp_ca_act_13 __P((Scsp_dcs *, void *));
86 int scsp_ca_act_14 __P((Scsp_dcs *, void *));
87 int scsp_ca_act_15 __P((Scsp_dcs *, void *));
88 int scsp_ca_act_16 __P((Scsp_dcs *, void *));
89 int scsp_ca_act_17 __P((Scsp_dcs *, void *));
90 int scsp_ca_act_18 __P((Scsp_dcs *, void *));
91 int scsp_ca_act_19 __P((Scsp_dcs *, void *));
93 static int (*scsp_ca_act_vec[CA_ACTION_CNT])() = {
119 static int ca_state_table[SCSP_CAFSM_EVENT_CNT][SCSP_CAFSM_STATE_CNT] = {
121 { 1, 1, 1, 1, 1, 1 }, /* 0 */
122 { 2, 2, 2, 2, 2, 2 }, /* 1 */
123 { 0, 3, 4, 5, 15, 15 }, /* 2 */
124 { 0, 17, 17, 17, 7, 7 }, /* 3 */
125 { 0, 17, 17, 17, 8, 8 }, /* 4 */
126 { 0, 17, 17, 17, 10, 10 }, /* 5 */
127 { 0, 6, 6, 0, 9, 9 }, /* 6 */
128 { 0, 0, 0, 0, 12, 12 }, /* 7 */
129 { 0, 0, 0, 0, 13, 13 }, /* 8 */
130 { 18, 14, 14, 14, 11, 11 }, /* 9 */
131 { 0, 19, 0, 0, 16, 16 }, /* 10 */
136 * Cache Alignment finite state machine
139 * dcsp pointer to a DCS control block for the neighbor
140 * event the event which has occurred
141 * p pointer to further parameter, if there is one
145 * errno error encountered
149 scsp_cafsm(dcsp, event, p)
154 int action, rc, state;
157 * Select an action from the state table
159 state = dcsp->sd_ca_state;
160 action = ca_state_table[event][state];
161 if (scsp_trace_mode & SCSP_TRACE_CAFSM) {
162 scsp_trace("CAFSM: state=%d, event=%d, action=%d\n",
163 state, event, action);
165 if (action >= CA_ACTION_CNT || action < 0) {
166 scsp_log(LOG_ERR, "CA FSM--invalid action state=%d, event=%d, action=%d",
167 state, event, action);
172 * Perform the selected action
174 rc = scsp_ca_act_vec[action](dcsp, p);
181 * CA finite state machine action 0
182 * Unexpected action -- log an error message and go to Master/Slave
183 * Negotiation. The unexpected action is probably from a protocol
187 * dcsp pointer to DCS control block
191 * EOPNOTSUPP always returns EOPNOTSUPP
195 scsp_ca_act_00(dcsp, p)
202 * Log an error message
204 scsp_log(LOG_ERR, "CA FSM error--unexpected action, state=%d",
210 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
213 * Clear out the DCS block
215 scsp_dcs_cleanup(dcsp);
218 * Notify the client I/F FSM
220 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_DOWN, (Scsp_msg *)0,
228 * CA finite state machine action 1
229 * Hello FSM has reached Bidirectional state -- go to Master/Slave
230 * Negotiation state, make a copy of the client's cache, send first CA
234 * dcsp pointer to DCS control block
239 * errno error encountered
243 scsp_ca_act_01(dcsp, p)
248 Scsp_cse *csep, *dupp;
253 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
256 * Make a copy of client's cache entries for cache alignment
258 for (i = 0; i < SCSP_HASHSZ; i++) {
259 for (csep = dcsp->sd_server->ss_cache[i];
260 csep; csep = csep->sc_next) {
261 dupp = scsp_dup_cse(csep);
262 LINK2TAIL(dupp, Scsp_cse, dcsp->sd_ca_csas,
268 * Select an initial sequence number
270 dcsp->sd_ca_seq = (int)time((time_t *)0);
275 rc = scsp_send_ca(dcsp);
277 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
278 scsp_ca_retran_timeout);
286 * CA finite state machine action 2
287 * Hello FSM has gone down -- go to Down state
290 * dcsp pointer to DCS control block
295 * errno error encountered
299 scsp_ca_act_02(dcsp, p)
308 dcsp->sd_ca_state = SCSP_CAFSM_DOWN;
311 * Clear out the DCS block
313 scsp_dcs_cleanup(dcsp);
316 * Notify the client I/F FSM
318 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_DOWN, (Scsp_msg *)0,
326 * CA finite state machine action 3
327 * CA message received -- select Cache Summarize Master or Slave state
330 * dcsp pointer to DCS control block
331 * p pointer to received message
335 * errno error encountered
339 scsp_ca_act_03(dcsp, p)
344 Scsp_msg *msg = (Scsp_msg *)p;
347 * Check for slave role for LS
349 if (msg->sc_ca->ca_m &&
352 msg->sc_ca->ca_mcp.rec_cnt == 0 &&
353 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
354 &msg->sc_ca->ca_mcp.rid) > 0) {
357 * Stop the retransmit timer
359 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
364 dcsp->sd_ca_state = SCSP_CAFSM_SLAVE;
365 (void)scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM,
366 (Scsp_msg *)0, (Scsp_if_msg *)0);
369 * Save the master's sequence number
371 dcsp->sd_ca_seq = msg->sc_ca->ca_seq;
376 rc = scsp_send_ca(dcsp);
379 * Check for master role for LS
381 if (!msg->sc_ca->ca_m &&
383 scsp_cmp_id(&msg->sc_ca->ca_mcp.sid,
384 &msg->sc_ca->ca_mcp.rid) < 0) {
386 * Stop the retransmit timer
388 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
393 dcsp->sd_ca_state = SCSP_CAFSM_MASTER;
394 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_SUMM,
395 (Scsp_msg *)0, (Scsp_if_msg *)0);
398 * Process the CA message
400 scsp_process_ca(dcsp, msg->sc_ca);
403 * Increment the sequence number
410 rc = scsp_send_ca(dcsp);
412 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
413 dcsp->sd_ca_rexmt_int,
414 scsp_ca_retran_timeout);
418 * Ignore the message, go to Master/Slave Negotiation
420 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
428 * CA finite state machine action 4
429 * CA message received while in Cache Summarize Master state -- process
433 * dcsp pointer to DCS control block
434 * p pointer to received message
438 * errno error encountered
442 scsp_ca_act_04(dcsp, p)
447 Scsp_msg *msg = (Scsp_msg *)p;
450 * If the other side thinks he's the master, or if the
451 * initialization bit is set, or if the message is out
452 * of sequence, go back to Master/Slave Negotiation state
454 if (msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
455 msg->sc_ca->ca_seq < dcsp->sd_ca_seq - 1 ||
456 msg->sc_ca->ca_seq > dcsp->sd_ca_seq) {
457 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
458 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
459 scsp_dcs_cleanup(dcsp);
460 return(scsp_ca_act_01(dcsp, (Scsp_msg *)0));
464 * Ignore any duplicate messages
466 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq - 1) {
471 * Stop the retransmission timer
473 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
476 * Process the CA message
478 scsp_process_ca(dcsp, msg->sc_ca);
481 * Increment the CA sequence number
486 * If we have no more CSAS records to send and the slave sent
487 * a message with the 'O' bit off, we're done with Summarize
490 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
492 * Free any CA message saved for retransmission
494 if (dcsp->sd_ca_rexmt_msg) {
495 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
496 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
500 * If the CRL is empty, we go directly to Aligned state;
501 * otherwise, we go to Update Cache and send a CSUS
505 * Go to Aligned state
507 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
508 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
513 * Go to Cache Update state
515 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
516 (void)scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD,
519 rc = scsp_send_csus(dcsp);
523 * There are more CSAS records to be exchanged--
524 * continue the cache exchange
526 rc = scsp_send_ca(dcsp);
534 * CA finite state machine action 5
535 * CA message received while in Cache Summarize Slave state -- process
539 * dcsp pointer to DCS control block
540 * p pointer to received message
544 * errno error encountered
548 scsp_ca_act_05(dcsp, p)
553 Scsp_msg *msg = (Scsp_msg *)p;
556 * If the other side thinks we're the master, or if the
557 * initialization bit is set, or if the message is out
558 * of sequence, go back to Master/Slave Negotiation state
560 if (!msg->sc_ca->ca_m || msg->sc_ca->ca_i ||
561 msg->sc_ca->ca_seq < dcsp->sd_ca_seq ||
562 msg->sc_ca->ca_seq > dcsp->sd_ca_seq + 1) {
563 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
564 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
565 scsp_dcs_cleanup(dcsp);
566 return(scsp_ca_act_01(dcsp, (Scsp_msg *)0));
570 * If this is a duplicate, retransmit the last message
572 if (msg->sc_ca->ca_seq == dcsp->sd_ca_seq) {
573 if (dcsp->sd_ca_rexmt_msg) {
574 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
576 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
577 dcsp->sd_ca_rexmt_int,
578 scsp_ca_retran_timeout);
585 * Free the last CA message
587 if (dcsp->sd_ca_rexmt_msg) {
588 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
589 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
593 * Process the CA message
595 scsp_process_ca(dcsp, msg->sc_ca);
598 * Increment the CA sequence number
603 * Answer the CA message
605 rc = scsp_send_ca(dcsp);
610 * If we're done sending CSAS records and the other side is,
611 * too, we're done with Summarize state
613 if (!dcsp->sd_ca_csas && !msg->sc_ca->ca_o) {
615 * If the CRL is empty, we go directly to Aligned state;
616 * otherwise, we go to Update Cache and send a CSUS
620 * Go to Aligned state
622 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
623 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
628 * Go to Cache Update state
630 dcsp->sd_ca_state = SCSP_CAFSM_UPDATE;
631 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
632 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
633 dcsp->sd_ca_rexmt_int,
634 scsp_ca_retran_timeout);
635 (void)scsp_cfsm(dcsp, SCSP_CIFSM_CA_UPD,
638 rc = scsp_send_csus(dcsp);
647 * CA finite state machine action 6
648 * Retransmit timer expired -- retransmit last CA message
651 * dcsp pointer to DCS control block
656 * errno error encountered
660 scsp_ca_act_06(dcsp, p)
667 * Resend the CA message
669 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
672 * Restart the retransmit timer
675 HARP_TIMER(&dcsp->sd_ca_rexmt_t, dcsp->sd_ca_rexmt_int,
676 scsp_ca_retran_timeout);
684 * CA finite state machine action 7
685 * CSU Solicit received -- send it to the client interface FSM
688 * dcsp pointer to DCS control block
689 * p pointer to received message
693 * errno error encountered
697 scsp_ca_act_07(dcsp, p)
702 Scsp_msg *msg = (Scsp_msg *)p;
705 * Cancel the CA retransmit timer and free any CA message
706 * saved for retransmission
708 if (dcsp->sd_ca_rexmt_msg) {
709 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
710 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
711 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
715 * Pass the CSUS to the client interface FSM
717 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_SOL, msg,
725 * CA finite state machine action 8
726 * CSU Request received -- pass it to the client interface FSM
729 * dcsp pointer to DCS control block
730 * p pointer to received message
734 * errno error encountered
738 scsp_ca_act_08(dcsp, p)
743 Scsp_msg *msg = (Scsp_msg *)p;
747 * Check whether this messages answers a CSUS
749 scsp_csus_ack(dcsp, msg);
752 * If all CSAs requestd in CSUS messages have been
753 * received, the cache is aligned, so go to Aligned State
755 if (!dcsp->sd_csus_rexmt_msg && !dcsp->sd_crl &&
756 dcsp->sd_ca_state != SCSP_CAFSM_ALIGNED) {
757 dcsp->sd_ca_state = SCSP_CAFSM_ALIGNED;
758 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CA_ALIGN,
759 (Scsp_msg *)0, (Scsp_if_msg *)0);
763 * Pass the CSU Req to the client interface FSM
765 rc = scsp_cfsm(dcsp, SCSP_CIFSM_CSU_REQ, msg,
769 * Move the CSA chain from the message to the list of
770 * requests that need acknowledgements
772 for (csap = msg->sc_csu_msg->csu_csa_rec; csap;
774 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
776 msg->sc_csu_msg->csu_csa_rec = (Scsp_csa *)0;
783 * CA finite state machine action 9
784 * CA Retransmit timer expired in Update Cache or Aligned state--free
785 * the saved CA message
788 * dcsp pointer to DCS control block
793 * errno error encountered
797 scsp_ca_act_09(dcsp, p)
802 * Free any CA message saved for retransmission
804 if (dcsp->sd_ca_rexmt_msg) {
805 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
806 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
814 * CA finite state machine action 10
815 * CSU Reply received -- Process the message
818 * dcsp pointer to DCS control block
819 * p pointer to received message
823 * errno error encountered
827 scsp_ca_act_10(dcsp, p)
832 Scsp_msg *msg = (Scsp_msg *)p;
833 Scsp_csu_rexmt *rxp, *next_rxp;
834 Scsp_csa *csap, *next_csap, *mcp;
837 * Dequeue acknowledged CSAs. For each CSAS in the received
838 * message, find the corresponding CSA on the CSU Request
839 * retransmit queue. Remove the CSA from the queue; if this
840 * results in the retransmit queue entry being empty, delete
841 * the entry. If the DCS has a newer CSA, send a CSUS to
844 * Caution--potentially confusing lack of indentation ahead.
846 for (mcp = msg->sc_csu_msg->csu_csa_rec; mcp;
848 for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = next_rxp) {
849 next_rxp = rxp->sr_next;
850 for (csap = rxp->sr_csa; csap; csap = next_csap) {
851 next_csap = csap->next;
852 if (scsp_cmp_key(&csap->key, &mcp->key) ||
853 scsp_cmp_id(&csap->oid, &mcp->oid))
856 * Found a CSA whose key and ID are equal to
857 * those in the CSU Reply
859 if (csap->seq == mcp->seq) {
861 * The queued seq no is equal to the
862 * received seq no--the CSA is acknowledged
864 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
866 } else if (csap->seq < mcp->seq) {
868 * Queued seq no is less than received.
869 * We must dequeue the CSA and send a
870 * CSUS to request the more-up-to-date
873 UNLINK(mcp, Scsp_csa,
874 msg->sc_csu_msg->csu_csa_rec,
876 LINK2TAIL(mcp, Scsp_csa, dcsp->sd_crl, next);
877 UNLINK(csap, Scsp_csa, rxp->sr_csa, next);
879 if (!dcsp->sd_csus_rexmt_msg) {
880 rc = scsp_send_csus(dcsp);
887 * Queued seq no is greater than
888 * received. Ignore the received CSAS.
892 * If the retransmission block is empty, stop the
896 HARP_CANCEL(&rxp->sr_t);
897 UNLINK(rxp, Scsp_csu_rexmt,
898 dcsp->sd_csu_rexmt, sr_next);
903 } /* for (csap = ... */
904 } /* for (rxp = ... */
905 } /* for (mcp = ... */
912 * CA finite state machine action 11
913 * Updated cache entry -- update the summary cache and send a
917 * dcsp pointer to DCS control block
918 * p pointer to CSA describing new cache entry
922 * errno error encountered
926 scsp_ca_act_11(dcsp, p)
931 Scsp_csa *csap = (Scsp_csa *)p;
935 * Get the state of the CSA
937 switch(dcsp->sd_server->ss_pid) {
938 case SCSP_PROTO_ATMARP:
939 state = csap->atmarp_data->sa_state;
946 if (state < SCSP_ASTATE_NEW || state > SCSP_ASTATE_DEL) {
952 * Look up the cache summary entry for the CSA
954 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
957 * Process ATMARP entries
959 if (dcsp->sd_server->ss_pid == SCSP_PROTO_ATMARP) {
961 case SCSP_ASTATE_NEW:
962 case SCSP_ASTATE_UPD:
964 * Add the entry if we don't have it already
967 csep = (Scsp_cse *)UM_ALLOC(
970 scsp_mem_err("scsp_ca_act_11: sizeof(Scsp_cse)");
971 UM_ZERO(csep, sizeof(Scsp_cse));
973 csep->sc_key = csap->key;
974 SCSP_ADD(dcsp->sd_server, csep);
978 * Update the cache summary entry
980 csep->sc_seq = csap->seq;
981 csep->sc_oid = csap->oid;
983 case SCSP_ASTATE_DEL:
985 * Delete any entry, but don't send the
989 SCSP_DELETE(dcsp->sd_server, csep);
999 * Send the CSA in a CSU Request
1002 rc = scsp_send_csu_req(dcsp, csap);
1009 * CA finite state machine action 12
1010 * CSUS retransmit timer expired--send a CSUS with any pending CSA
1014 * dcsp pointer to DCS control block
1019 * errno error encountered
1023 scsp_ca_act_12(dcsp, p)
1029 rc = scsp_send_csus(dcsp);
1036 * CA finite state machine action 13
1037 * CSU retransmit timer fired in Update or Aligned state--
1038 * retransmit CSU Req
1041 * dcsp pointer to DCS control block
1042 * p pointer to retransmission block whose timer fired
1046 * errno error encountered
1050 scsp_ca_act_13(dcsp, p)
1055 Scsp_csu_rexmt *rxp = (Scsp_csu_rexmt *)p;
1056 Scsp_csa *csap, *csap1, *next_csap;
1059 * Unlink and free the retransmit request block
1062 UNLINK(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
1066 * Increment the transmission count for the CSAs in the request
1068 for (csap1 = csap; csap1; csap1 = next_csap) {
1069 next_csap = csap1->next;
1071 if (csap1->trans_ct >= dcsp->sd_csu_rexmt_max) {
1073 * We've already sent this as many times as
1074 * the limit allows. Drop this CSA.
1076 UNLINK(csap1, Scsp_csa, csap, next);
1077 SCSP_FREE_CSA(csap1);
1082 * Send another CSU Request with the CSA list, if it isn't
1086 rc = scsp_send_csu_req(dcsp, csap);
1094 * CA finite state machine action 14
1095 * Updated cache entry in Master/Slave Negotiation, Master, or
1096 * Slave state--add entry to cache and CSA list
1099 * dcsp pointer to DCS control block
1100 * p pointer to new cache summary entry
1104 * errno error encountered
1108 scsp_ca_act_14(dcsp, p)
1112 Scsp_csa *csap = (Scsp_csa *)p;
1113 Scsp_cse *csep, *csep1;
1116 * Check to see whether we already have this
1118 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
1121 * If we don't already have it and it's not being deleted,
1122 * build a new cache summary entry
1124 if (!csep && !csap->null) {
1126 * Get memory for a new entry
1128 csep = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
1130 scsp_mem_err("scsp_ca_act_14: sizeof(Scsp_cse)");
1132 UM_ZERO(csep, sizeof(Scsp_cse));
1135 * Fill out the new cache entry
1137 csep->sc_seq = csap->seq;
1138 csep->sc_key = csap->key;
1139 csep->sc_oid = csap->oid;
1142 * Duplicate the new cache entry
1144 csep1 = scsp_dup_cse(csep);
1147 * Add entry to the summary cache and the CSAS list
1149 SCSP_ADD(dcsp->sd_server, csep);
1150 LINK2TAIL(csep1, Scsp_cse, dcsp->sd_ca_csas, sc_next);
1153 * We already have the entry. Find it on the CSAS
1156 for (csep1 = dcsp->sd_ca_csas; csep1;
1157 csep1 = csep1->sc_next) {
1158 if (scsp_cmp_key(&csep->sc_key,
1159 &csep1->sc_key) == 0)
1164 * Update or delete the entry
1168 * The null flag is set--delete the entry
1170 SCSP_DELETE(dcsp->sd_server, csep);
1173 UNLINK(csep1, Scsp_cse,
1182 csep->sc_seq = csap->seq;
1183 csep->sc_oid = csap->oid;
1185 csep1 = scsp_dup_cse(csep);
1186 LINK2TAIL(csep1, Scsp_cse,
1187 dcsp->sd_ca_csas, sc_next);
1189 csep1->sc_seq = csap->seq;
1190 csep1->sc_oid = csap->oid;
1200 * CA finite state machine action 15
1201 * CA message received in Update Cache state--if we have a saved CA
1202 * message, retransmit it; otherwise, go to Master/Slave Negotiation
1206 * dcsp pointer to DCS control block
1211 * errno error encountered
1215 scsp_ca_act_15(dcsp, p)
1220 Scsp_msg *msg = (Scsp_msg *)p;
1223 * If we don't have a saved CA message, or the sequence no. in
1224 * the received message isn't right, fall back to Master/Slave
1227 if (!dcsp->sd_ca_rexmt_msg ||
1228 msg->sc_ca->ca_seq != dcsp->sd_ca_seq) {
1229 dcsp->sd_ca_state = SCSP_CAFSM_NEG;
1230 scsp_dcs_cleanup(dcsp);
1231 rc = scsp_ca_act_01(dcsp, (Scsp_msg *)0);
1234 * Retransmit the saved CA message and reset the
1237 rc = scsp_send_msg(dcsp, dcsp->sd_ca_rexmt_msg);
1239 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
1240 HARP_TIMER(&dcsp->sd_ca_rexmt_t,
1241 dcsp->sd_ca_rexmt_int,
1242 scsp_ca_retran_timeout);
1251 * CA finite state machine action 16
1252 * Update Response received from client in Update Cache or Aligned
1253 * state. Move the acknowledged CSA to the acknowledged queue. If
1254 * the list of CSAs pending acknowledgement is empty, send a CSU
1258 * dcsp pointer to DCS control block
1259 * p pointer to message from client
1263 * errno error encountered
1267 scsp_ca_act_16(dcsp, p)
1272 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1276 * Find the acknowledged CSA
1278 for (csap = dcsp->sd_csu_ack_pend, found = 0; csap && !found;
1279 csap = csap->next) {
1280 switch (dcsp->sd_server->ss_pid) {
1281 case SCSP_PROTO_ATMARP:
1282 found = ((scsp_cmp_key(&csap->key,
1283 &cmsg->si_atmarp.sa_key) == 0) &&
1284 (scsp_cmp_id(&csap->oid,
1285 &cmsg->si_atmarp.sa_oid) == 0));
1289 * Protocol not implemented
1291 return(EPROTONOSUPPORT);
1298 if (scsp_trace_mode & SCSP_TRACE_CAFSM) {
1299 scsp_trace("scsp_ca_act_16: can't find CSA entry for Update Response\n");
1304 if (cmsg->si_rc == SCSP_RSP_OK) {
1306 * The server accepted the cache entry
1310 * Update SCSP's cache
1312 scsp_update_cache(dcsp, csap);
1315 * Send this CSA to any other DCSs in the server group
1317 rc = scsp_propagate_csa(dcsp, csap);
1321 * Move the CSA from the ACK pending queue to the
1322 * acknowledged queue
1324 UNLINK(csap, Scsp_csa, dcsp->sd_csu_ack_pend, next);
1325 LINK2TAIL(csap, Scsp_csa, dcsp->sd_csu_ack, next);
1326 if (!dcsp->sd_csu_ack_pend) {
1328 * ACK pending list is empty--send a CSU Reply
1330 csap = dcsp->sd_csu_ack;
1331 dcsp->sd_csu_ack = (Scsp_csa *)0;
1332 rc = scsp_send_csu_reply(dcsp, csap);
1340 * CA finite state machine action 17
1344 * dcsp pointer to DCS control block
1352 scsp_ca_act_17(dcsp, p)
1361 * CA finite state machine action 18
1362 * Updated cache entry in Down state--add entry to summary cache
1365 * dcsp pointer to DCS control block
1366 * p pointer to new cache summary entry
1370 * errno error encountered
1374 scsp_ca_act_18(dcsp, p)
1378 Scsp_csa *csap = (Scsp_csa *)p;
1381 * Update the cache as appropriate
1383 scsp_update_cache(dcsp, csap);
1390 * CA finite state machine action 19
1391 * Update Response received from client in Master/Slave Negotiation
1392 * state. Update the cache as appropriate.
1395 * dcsp pointer to DCS control block
1396 * p pointer to message from client
1400 * errno error encountered
1404 scsp_ca_act_19(dcsp, p)
1408 Scsp_if_msg *cmsg = (Scsp_if_msg *)p;
1412 * Ignore the message if the client rejected the update
1414 if (cmsg->si_rc != SCSP_RSP_OK) {
1419 * Create a CSAS from the client's update
1421 csap = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
1423 scsp_mem_err("scsp_ca_act_19: sizeof(Scsp_csa)");
1425 UM_ZERO(csap, sizeof(Scsp_csa));
1428 switch (dcsp->sd_server->ss_pid) {
1429 case SCSP_PROTO_ATMARP:
1430 csap->null = cmsg->si_atmarp.sa_state ==
1432 csap->seq = cmsg->si_atmarp.sa_seq;
1433 csap->key = cmsg->si_atmarp.sa_key;
1434 csap->oid = cmsg->si_atmarp.sa_oid;
1441 * Update SCSP's cache
1443 scsp_update_cache(dcsp, csap);