1 /******************************************************************************
3 * (C)Copyright 1998,1999 SysKonnect,
4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6 * See the file "skfddi.c" for further information.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * The information in this file is provided "AS IS" without warranty.
15 ******************************************************************************/
18 SMT 7.2 Status Response Frame Implementation
19 SRF state machine and frame generation
28 #include "h/smtstate.h"
34 static const char ID_sccs
[] = "@(#)srf.c 1.18 97/08/04 (C) SK " ;
39 * function declarations
41 static void clear_all_rep(struct s_smc
*smc
);
42 static void clear_reported(struct s_smc
*smc
);
43 static void smt_send_srf(struct s_smc
*smc
);
44 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
);
46 #define MAX_EVCS ARRAY_SIZE(smc->evcs)
55 static const struct evc_init evc_inits
[] = {
56 { SMT_COND_SMT_PEER_WRAP
, 0,1,SMT_P1048
} ,
58 { SMT_COND_MAC_DUP_ADDR
, INDEX_MAC
, NUMMACS
,SMT_P208C
} ,
59 { SMT_COND_MAC_FRAME_ERROR
, INDEX_MAC
, NUMMACS
,SMT_P208D
} ,
60 { SMT_COND_MAC_NOT_COPIED
, INDEX_MAC
, NUMMACS
,SMT_P208E
} ,
61 { SMT_EVENT_MAC_NEIGHBOR_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P208F
} ,
62 { SMT_EVENT_MAC_PATH_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P2090
} ,
64 { SMT_COND_PORT_LER
, INDEX_PORT
,NUMPHYS
,SMT_P4050
} ,
65 { SMT_COND_PORT_EB_ERROR
, INDEX_PORT
,NUMPHYS
,SMT_P4052
} ,
66 { SMT_EVENT_PORT_CONNECTION
, INDEX_PORT
,NUMPHYS
,SMT_P4051
} ,
67 { SMT_EVENT_PORT_PATH_CHANGE
, INDEX_PORT
,NUMPHYS
,SMT_P4053
} ,
70 #define MAX_INIT_EVC ARRAY_SIZE(evc_inits)
72 void smt_init_evc(struct s_smc
*smc
)
74 struct s_srf_evc
*evc
;
75 const struct evc_init
*init
;
80 static u_char fail_safe
= FALSE
;
82 memset((char *)smc
->evcs
,0,sizeof(smc
->evcs
)) ;
87 for (i
= 0 ; i
< MAX_INIT_EVC
; i
++) {
88 for (index
= 0 ; index
< init
->n
; index
++) {
89 evc
->evc_code
= init
->code
;
90 evc
->evc_para
= init
->para
;
91 evc
->evc_index
= init
->index
+ index
;
93 evc
->evc_multiple
= &fail_safe
;
94 evc
->evc_cond_state
= &fail_safe
;
101 if ((unsigned int) (evc
- smc
->evcs
) > MAX_EVCS
) {
102 SMT_PANIC(smc
,SMT_E0127
, SMT_E0127_MSG
) ;
108 smc
->evcs
[0].evc_cond_state
= &smc
->mib
.fddiSMTPeerWrapFlag
;
109 smc
->evcs
[1].evc_cond_state
=
110 &smc
->mib
.m
[MAC0
].fddiMACDuplicateAddressCond
;
111 smc
->evcs
[2].evc_cond_state
=
112 &smc
->mib
.m
[MAC0
].fddiMACFrameErrorFlag
;
113 smc
->evcs
[3].evc_cond_state
=
114 &smc
->mib
.m
[MAC0
].fddiMACNotCopiedFlag
;
119 smc
->evcs
[4].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_N
;
120 smc
->evcs
[5].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_P
;
123 for (i
= 0 ; i
< NUMPHYS
; i
++) {
127 smc
->evcs
[offset
+ 0*NUMPHYS
].evc_cond_state
=
128 &smc
->mib
.p
[i
].fddiPORTLerFlag
;
129 smc
->evcs
[offset
+ 1*NUMPHYS
].evc_cond_state
=
130 &smc
->mib
.p
[i
].fddiPORTEB_Condition
;
135 smc
->evcs
[offset
+ 2*NUMPHYS
].evc_multiple
=
136 &smc
->mib
.p
[i
].fddiPORTMultiple_U
;
137 smc
->evcs
[offset
+ 3*NUMPHYS
].evc_multiple
=
138 &smc
->mib
.p
[i
].fddiPORTMultiple_P
;
142 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
143 if (SMT_IS_CONDITION(evc
->evc_code
)) {
144 if (!evc
->evc_cond_state
) {
145 SMT_PANIC(smc
,SMT_E0128
, SMT_E0128_MSG
) ;
147 evc
->evc_multiple
= &fail_safe
;
150 if (!evc
->evc_multiple
) {
151 SMT_PANIC(smc
,SMT_E0129
, SMT_E0129_MSG
) ;
153 evc
->evc_cond_state
= &fail_safe
;
157 smc
->srf
.TSR
= smt_get_time() ;
158 smc
->srf
.sr_state
= SR0_WAIT
;
161 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
)
164 struct s_srf_evc
*evc
;
166 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
167 if (evc
->evc_code
== code
&& evc
->evc_index
== index
)
173 #define THRESHOLD_2 (2*TICKS_PER_SECOND)
174 #define THRESHOLD_32 (32*TICKS_PER_SECOND)
177 static const char * const srf_names
[] = {
178 "None","MACPathChangeEvent", "MACNeighborChangeEvent",
179 "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent",
180 "SMTPeerWrapCondition", "SMTHoldCondition",
181 "MACFrameErrorCondition", "MACDuplicateAddressCondition",
182 "MACNotCopiedCondition", "PORTEBErrorCondition",
187 void smt_srf_event(struct s_smc
*smc
, int code
, int index
, int cond
)
189 struct s_srf_evc
*evc
;
190 int cond_asserted
= 0 ;
191 int cond_deasserted
= 0 ;
192 int event_occurred
= 0 ;
194 int T_Limit
= 2*TICKS_PER_SECOND
;
196 if (code
== SMT_COND_MAC_DUP_ADDR
&& cond
) {
197 RS_SET(smc
,RS_DUPADDR
) ;
201 DB_SMT("SRF: %s index %d\n",srf_names
[code
],index
) ;
203 if (!(evc
= smt_get_evc(smc
,code
,index
))) {
204 DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
208 * ignore condition if no change
210 if (SMT_IS_CONDITION(code
)) {
211 if (*evc
->evc_cond_state
== cond
)
216 * set transition time stamp
218 smt_set_timestamp(smc
,smc
->mib
.fddiSMTTransitionTimeStamp
) ;
219 if (SMT_IS_CONDITION(code
)) {
220 DB_SMT("SRF: condition is %s\n",cond
? "ON":"OFF",0) ;
222 *evc
->evc_cond_state
= TRUE
;
223 evc
->evc_rep_required
= TRUE
;
224 smc
->srf
.any_report
= TRUE
;
225 cond_asserted
= TRUE
;
228 *evc
->evc_cond_state
= FALSE
;
229 cond_deasserted
= TRUE
;
233 if (evc
->evc_rep_required
) {
234 *evc
->evc_multiple
= TRUE
;
237 evc
->evc_rep_required
= TRUE
;
238 *evc
->evc_multiple
= FALSE
;
240 smc
->srf
.any_report
= TRUE
;
241 event_occurred
= TRUE
;
244 snmp_srf_event(smc
,evc
) ;
245 #endif /* FDDI_MIB */
247 tsr
= smt_get_time() - smc
->srf
.TSR
;
249 switch (smc
->srf
.sr_state
) {
252 if (cond_asserted
&& tsr
< T_Limit
) {
253 smc
->srf
.SRThreshold
= THRESHOLD_2
;
254 smc
->srf
.sr_state
= SR1_HOLDOFF
;
258 if (cond_deasserted
&& tsr
< T_Limit
) {
259 smc
->srf
.sr_state
= SR1_HOLDOFF
;
263 if (event_occurred
&& tsr
< T_Limit
) {
264 smc
->srf
.sr_state
= SR1_HOLDOFF
;
268 if (cond_asserted
&& tsr
>= T_Limit
) {
269 smc
->srf
.SRThreshold
= THRESHOLD_2
;
270 smc
->srf
.TSR
= smt_get_time() ;
275 if (cond_deasserted
&& tsr
>= T_Limit
) {
276 smc
->srf
.TSR
= smt_get_time() ;
281 if (event_occurred
&& tsr
>= T_Limit
) {
282 smc
->srf
.TSR
= smt_get_time() ;
287 if (smc
->srf
.any_report
&& (u_long
) tsr
>=
288 smc
->srf
.SRThreshold
) {
289 smc
->srf
.SRThreshold
*= 2 ;
290 if (smc
->srf
.SRThreshold
> THRESHOLD_32
)
291 smc
->srf
.SRThreshold
= THRESHOLD_32
;
292 smc
->srf
.TSR
= smt_get_time() ;
297 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
298 smc
->srf
.sr_state
= SR2_DISABLED
;
304 if (tsr
>= T_Limit
) {
305 smc
->srf
.sr_state
= SR0_WAIT
;
306 smc
->srf
.TSR
= smt_get_time() ;
312 smc
->srf
.SRThreshold
= THRESHOLD_2
;
318 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
319 smc
->srf
.sr_state
= SR2_DISABLED
;
324 if (smc
->mib
.fddiSMTStatRptPolicy
) {
325 smc
->srf
.sr_state
= SR0_WAIT
;
326 smc
->srf
.TSR
= smt_get_time() ;
327 smc
->srf
.SRThreshold
= THRESHOLD_2
;
335 static void clear_all_rep(struct s_smc
*smc
)
337 struct s_srf_evc
*evc
;
340 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
341 evc
->evc_rep_required
= FALSE
;
342 if (SMT_IS_CONDITION(evc
->evc_code
))
343 *evc
->evc_cond_state
= FALSE
;
345 smc
->srf
.any_report
= FALSE
;
348 static void clear_reported(struct s_smc
*smc
)
350 struct s_srf_evc
*evc
;
353 smc
->srf
.any_report
= FALSE
;
354 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
355 if (SMT_IS_CONDITION(evc
->evc_code
)) {
356 if (*evc
->evc_cond_state
== FALSE
)
357 evc
->evc_rep_required
= FALSE
;
359 smc
->srf
.any_report
= TRUE
;
362 evc
->evc_rep_required
= FALSE
;
363 *evc
->evc_multiple
= FALSE
;
369 * build and send SMT SRF frame
371 static void smt_send_srf(struct s_smc
*smc
)
374 struct smt_header
*smt
;
375 struct s_srf_evc
*evc
;
376 SK_LOC_DECL(struct s_pcon
,pcon
) ;
380 static const struct fddi_addr SMT_SRF_DA
= {
381 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
387 if (!smc
->r
.sm_ma_avail
)
389 if (!(mb
= smt_build_frame(smc
,SMT_SRF
,SMT_ANNOUNCE
,0)))
392 RS_SET(smc
,RS_SOFTERROR
) ;
394 smt
= smtod(mb
, struct smt_header
*) ;
395 smt
->smt_dest
= SMT_SRF_DA
; /* DA == SRF multicast */
398 * setup parameter status
400 pcon
.pc_len
= SMT_MAX_INFO_LEN
; /* max para length */
401 pcon
.pc_err
= 0 ; /* no error */
402 pcon
.pc_badset
= 0 ; /* no bad set count */
403 pcon
.pc_p
= (void *) (smt
+ 1) ; /* paras start here */
405 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1033
,0,0) ;
406 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1034
,0,0) ;
408 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
409 if (evc
->evc_rep_required
) {
410 smt_add_para(smc
,&pcon
,evc
->evc_para
,
411 (int)evc
->evc_index
,0) ;
414 smt
->smt_len
= SMT_MAX_INFO_LEN
- pcon
.pc_len
;
415 mb
->sm_len
= smt
->smt_len
+ sizeof(struct smt_header
) ;
417 DB_SMT("SRF: sending SRF at %p, len %d\n",smt
,mb
->sm_len
) ;
418 DB_SMT("SRF: state SR%d Threshold %d\n",
419 smc
->srf
.sr_state
,smc
->srf
.SRThreshold
/TICKS_PER_SECOND
) ;
421 dump_smt(smc
,smt
,"SRF Send") ;
423 smt_send_frame(smc
,mb
,FC_SMT_INFO
,0) ;
424 clear_reported(smc
) ;
428 #endif /* no SLIM_SMT */