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
, NULL
, NULL
);
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
223 * dcsp pointer to DCS control block
228 * errno error encountered
232 scsp_ca_act_01(Scsp_dcs
*dcsp
, void *p
)
235 Scsp_cse
*csep
, *dupp
;
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
,
255 * Select an initial sequence number
257 dcsp
->sd_ca_seq
= (int)time(NULL
);
262 rc
= scsp_send_ca(dcsp
);
264 HARP_TIMER(&dcsp
->sd_ca_rexmt_t
, dcsp
->sd_ca_rexmt_int
,
265 scsp_ca_retran_timeout
);
273 * CA finite state machine action 2
274 * Hello FSM has gone down -- go to Down state
277 * dcsp pointer to DCS control block
282 * errno error encountered
286 scsp_ca_act_02(Scsp_dcs
*dcsp
, void *p
)
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
);
310 * CA finite state machine action 3
311 * CA message received -- select Cache Summarize Master or Slave state
314 * dcsp pointer to DCS control block
315 * p pointer to received message
319 * errno error encountered
323 scsp_ca_act_03(Scsp_dcs
*dcsp
, void *p
)
326 Scsp_msg
*msg
= (Scsp_msg
*)p
;
329 * Check for slave role for LS
331 if (msg
->sc_ca
->ca_m
&&
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
);
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
;
357 rc
= scsp_send_ca(dcsp
);
360 * Check for master role for LS
362 if (!msg
->sc_ca
->ca_m
&&
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
);
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
390 rc
= scsp_send_ca(dcsp
);
392 HARP_TIMER(&dcsp
->sd_ca_rexmt_t
,
393 dcsp
->sd_ca_rexmt_int
,
394 scsp_ca_retran_timeout
);
398 * Ignore the message, go to Master/Slave Negotiation
400 dcsp
->sd_ca_state
= SCSP_CAFSM_NEG
;
408 * CA finite state machine action 4
409 * CA message received while in Cache Summarize Master state -- process
413 * dcsp pointer to DCS control block
414 * p pointer to received message
418 * errno error encountered
422 scsp_ca_act_04(Scsp_dcs
*dcsp
, void *p
)
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) {
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
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
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
483 * Go to Aligned state
485 dcsp
->sd_ca_state
= SCSP_CAFSM_ALIGNED
;
486 rc
= scsp_cfsm(dcsp
, SCSP_CIFSM_CA_ALIGN
, NULL
, NULL
);
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
);
497 * There are more CSAS records to be exchanged--
498 * continue the cache exchange
500 rc
= scsp_send_ca(dcsp
);
508 * CA finite state machine action 5
509 * CA message received while in Cache Summarize Slave state -- process
513 * dcsp pointer to DCS control block
514 * p pointer to received message
518 * errno error encountered
522 scsp_ca_act_05(Scsp_dcs
*dcsp
, void *p
)
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
);
548 HARP_TIMER(&dcsp
->sd_ca_rexmt_t
,
549 dcsp
->sd_ca_rexmt_int
,
550 scsp_ca_retran_timeout
);
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
575 * Answer the CA message
577 rc
= scsp_send_ca(dcsp
);
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
592 * Go to Aligned state
594 dcsp
->sd_ca_state
= SCSP_CAFSM_ALIGNED
;
595 rc
= scsp_cfsm(dcsp
, SCSP_CIFSM_CA_ALIGN
, NULL
, NULL
);
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
);
615 * CA finite state machine action 6
616 * Retransmit timer expired -- retransmit last CA message
619 * dcsp pointer to DCS control block
624 * errno error encountered
628 scsp_ca_act_06(Scsp_dcs
*dcsp
, void *p
)
633 * Resend the CA message
635 rc
= scsp_send_msg(dcsp
, dcsp
->sd_ca_rexmt_msg
);
638 * Restart the retransmit timer
641 HARP_TIMER(&dcsp
->sd_ca_rexmt_t
, dcsp
->sd_ca_rexmt_int
,
642 scsp_ca_retran_timeout
);
650 * CA finite state machine action 7
651 * CSU Solicit received -- send it to the client interface FSM
654 * dcsp pointer to DCS control block
655 * p pointer to received message
659 * errno error encountered
663 scsp_ca_act_07(Scsp_dcs
*dcsp
, void *p
)
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
);
688 * CA finite state machine action 8
689 * CSU Request received -- pass it to the client interface FSM
692 * dcsp pointer to DCS control block
693 * p pointer to received message
697 * errno error encountered
701 scsp_ca_act_08(Scsp_dcs
*dcsp
, void *p
)
704 Scsp_msg
*msg
= (Scsp_msg
*)p
;
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
;
733 LINK2TAIL(csap
, Scsp_csa
, dcsp
->sd_csu_ack_pend
, next
);
735 msg
->sc_csu_msg
->csu_csa_rec
= NULL
;
742 * CA finite state machine action 9
743 * CA Retransmit timer expired in Update Cache or Aligned state--free
744 * the saved CA message
747 * dcsp pointer to DCS control block
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
;
771 * CA finite state machine action 10
772 * CSU Reply received -- Process the message
775 * dcsp pointer to DCS control block
776 * p pointer to received message
780 * errno error encountered
784 scsp_ca_act_10(Scsp_dcs
*dcsp
, void *p
)
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
799 * Caution--potentially confusing lack of indentation ahead.
801 for (mcp
= msg
->sc_csu_msg
->csu_csa_rec
; mcp
;
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
))
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
);
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
828 UNLINK(mcp
, Scsp_csa
,
829 msg
->sc_csu_msg
->csu_csa_rec
,
831 LINK2TAIL(mcp
, Scsp_csa
, dcsp
->sd_crl
, next
);
832 UNLINK(csap
, Scsp_csa
, rxp
->sr_csa
, next
);
834 if (!dcsp
->sd_csus_rexmt_msg
) {
835 rc
= scsp_send_csus(dcsp
);
842 * Queued seq no is greater than
843 * received. Ignore the received CSAS.
847 * If the retransmission block is empty, stop the
851 HARP_CANCEL(&rxp
->sr_t
);
852 UNLINK(rxp
, Scsp_csu_rexmt
,
853 dcsp
->sd_csu_rexmt
, sr_next
);
858 } /* for (csap = ... */
859 } /* for (rxp = ... */
860 } /* for (mcp = ... */
867 * CA finite state machine action 11
868 * Updated cache entry -- update the summary cache and send a
872 * dcsp pointer to DCS control block
873 * p pointer to CSA describing new cache entry
877 * errno error encountered
881 scsp_ca_act_11(Scsp_dcs
*dcsp
, void *p
)
884 Scsp_csa
*csap
= (Scsp_csa
*)p
;
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
;
899 if (state
< SCSP_ASTATE_NEW
|| state
> SCSP_ASTATE_DEL
) {
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
) {
914 case SCSP_ASTATE_NEW
:
915 case SCSP_ASTATE_UPD
:
917 * Add the entry if we don't have it already
920 csep
= (Scsp_cse
*)UM_ALLOC(
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
;
936 case SCSP_ASTATE_DEL
:
938 * Delete any entry, but don't send the
942 SCSP_DELETE(dcsp
->sd_server
, csep
);
952 * Send the CSA in a CSU Request
955 rc
= scsp_send_csu_req(dcsp
, csap
);
962 * CA finite state machine action 12
963 * CSUS retransmit timer expired--send a CSUS with any pending CSA
967 * dcsp pointer to DCS control block
972 * errno error encountered
976 scsp_ca_act_12(Scsp_dcs
*dcsp
, void *p
)
980 rc
= scsp_send_csus(dcsp
);
987 * CA finite state machine action 13
988 * CSU retransmit timer fired in Update or Aligned state--
992 * dcsp pointer to DCS control block
993 * p pointer to retransmission block whose timer fired
997 * errno error encountered
1001 scsp_ca_act_13(Scsp_dcs
*dcsp
, void *p
)
1004 Scsp_csu_rexmt
*rxp
= (Scsp_csu_rexmt
*)p
;
1005 Scsp_csa
*csap
, *csap1
, *next_csap
;
1008 * Unlink and free the retransmit request block
1011 UNLINK(rxp
, Scsp_csu_rexmt
, dcsp
->sd_csu_rexmt
, sr_next
);
1015 * Increment the transmission count for the CSAs in the request
1017 for (csap1
= csap
; csap1
; csap1
= next_csap
) {
1018 next_csap
= csap1
->next
;
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
1035 rc
= scsp_send_csu_req(dcsp
, csap
);
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
1048 * dcsp pointer to DCS control block
1049 * p pointer to new cache summary entry
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
));
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
);
1100 * We already have the entry. Find it on the CSAS
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)
1111 * Update or delete the entry
1115 * The null flag is set--delete the entry
1117 SCSP_DELETE(dcsp
->sd_server
, csep
);
1120 UNLINK(csep1
, Scsp_cse
,
1129 csep
->sc_seq
= csap
->seq
;
1130 csep
->sc_oid
= csap
->oid
;
1132 csep1
= scsp_dup_cse(csep
);
1133 LINK2TAIL(csep1
, Scsp_cse
,
1134 dcsp
->sd_ca_csas
, sc_next
);
1136 csep1
->sc_seq
= csap
->seq
;
1137 csep1
->sc_oid
= csap
->oid
;
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
1153 * dcsp pointer to DCS control block
1158 * errno error encountered
1162 scsp_ca_act_15(Scsp_dcs
*dcsp
, void *p
)
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
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
);
1179 * Retransmit the saved CA message and reset the
1182 rc
= scsp_send_msg(dcsp
, dcsp
->sd_ca_rexmt_msg
);
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
);
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
1203 * dcsp pointer to DCS control block
1204 * p pointer to message from client
1208 * errno error encountered
1212 scsp_ca_act_16(Scsp_dcs
*dcsp
, void *p
)
1215 Scsp_if_msg
*cmsg
= (Scsp_if_msg
*)p
;
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));
1232 * Protocol not implemented
1234 return(EPROTONOSUPPORT
);
1241 if (scsp_trace_mode
& SCSP_TRACE_CAFSM
) {
1242 scsp_trace("scsp_ca_act_16: can't find CSA entry for Update Response\n");
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
);
1283 * CA finite state machine action 17
1287 * dcsp pointer to DCS control block
1295 scsp_ca_act_17(Scsp_dcs
*dcsp
, void *p
)
1302 * CA finite state machine action 18
1303 * Updated cache entry in Down state--add entry to summary cache
1306 * dcsp pointer to DCS control block
1307 * p pointer to new cache summary entry
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
);
1329 * CA finite state machine action 19
1330 * Update Response received from client in Master/Slave Negotiation
1331 * state. Update the cache as appropriate.
1334 * dcsp pointer to DCS control block
1335 * p pointer to message from client
1339 * errno error encountered
1343 scsp_ca_act_19(Scsp_dcs
*dcsp
, void *p
)
1345 Scsp_if_msg
*cmsg
= (Scsp_if_msg
*)p
;
1349 * Ignore the message if the client rejected the update
1351 if (cmsg
->si_rc
!= SCSP_RSP_OK
) {
1356 * Create a CSAS from the client's update
1358 csap
= (Scsp_csa
*)UM_ALLOC(sizeof(Scsp_csa
));
1360 scsp_mem_err("scsp_ca_act_19: sizeof(Scsp_csa)");
1362 UM_ZERO(csap
, sizeof(Scsp_csa
));
1365 switch (dcsp
->sd_server
->ss_pid
) {
1366 case SCSP_PROTO_ATMARP
:
1367 csap
->null
= cmsg
->si_atmarp
.sa_state
==
1369 csap
->seq
= cmsg
->si_atmarp
.sa_seq
;
1370 csap
->key
= cmsg
->si_atmarp
.sa_key
;
1371 csap
->oid
= cmsg
->si_atmarp
.sa_oid
;
1378 * Update SCSP's cache
1380 scsp_update_cache(dcsp
, csap
);