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)
176 static const char * const srf_names
[] = {
177 "None","MACPathChangeEvent", "MACNeighborChangeEvent",
178 "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent",
179 "SMTPeerWrapCondition", "SMTHoldCondition",
180 "MACFrameErrorCondition", "MACDuplicateAddressCondition",
181 "MACNotCopiedCondition", "PORTEBErrorCondition",
185 void smt_srf_event(struct s_smc
*smc
, int code
, int index
, int cond
)
187 struct s_srf_evc
*evc
;
188 int cond_asserted
= 0 ;
189 int cond_deasserted
= 0 ;
190 int event_occurred
= 0 ;
192 int T_Limit
= 2*TICKS_PER_SECOND
;
194 if (code
== SMT_COND_MAC_DUP_ADDR
&& cond
) {
195 RS_SET(smc
,RS_DUPADDR
) ;
199 DB_SMT("SRF: %s index %d", srf_names
[code
], index
);
201 if (!(evc
= smt_get_evc(smc
,code
,index
))) {
202 DB_SMT("SRF : smt_get_evc() failed");
206 * ignore condition if no change
208 if (SMT_IS_CONDITION(code
)) {
209 if (*evc
->evc_cond_state
== cond
)
214 * set transition time stamp
216 smt_set_timestamp(smc
,smc
->mib
.fddiSMTTransitionTimeStamp
) ;
217 if (SMT_IS_CONDITION(code
)) {
218 DB_SMT("SRF: condition is %s", cond
? "ON" : "OFF");
220 *evc
->evc_cond_state
= TRUE
;
221 evc
->evc_rep_required
= TRUE
;
222 smc
->srf
.any_report
= TRUE
;
223 cond_asserted
= TRUE
;
226 *evc
->evc_cond_state
= FALSE
;
227 cond_deasserted
= TRUE
;
231 if (evc
->evc_rep_required
) {
232 *evc
->evc_multiple
= TRUE
;
235 evc
->evc_rep_required
= TRUE
;
236 *evc
->evc_multiple
= FALSE
;
238 smc
->srf
.any_report
= TRUE
;
239 event_occurred
= TRUE
;
242 snmp_srf_event(smc
,evc
) ;
243 #endif /* FDDI_MIB */
245 tsr
= smt_get_time() - smc
->srf
.TSR
;
247 switch (smc
->srf
.sr_state
) {
250 if (cond_asserted
&& tsr
< T_Limit
) {
251 smc
->srf
.SRThreshold
= THRESHOLD_2
;
252 smc
->srf
.sr_state
= SR1_HOLDOFF
;
256 if (cond_deasserted
&& tsr
< T_Limit
) {
257 smc
->srf
.sr_state
= SR1_HOLDOFF
;
261 if (event_occurred
&& tsr
< T_Limit
) {
262 smc
->srf
.sr_state
= SR1_HOLDOFF
;
266 if (cond_asserted
&& tsr
>= T_Limit
) {
267 smc
->srf
.SRThreshold
= THRESHOLD_2
;
268 smc
->srf
.TSR
= smt_get_time() ;
273 if (cond_deasserted
&& tsr
>= T_Limit
) {
274 smc
->srf
.TSR
= smt_get_time() ;
279 if (event_occurred
&& tsr
>= T_Limit
) {
280 smc
->srf
.TSR
= smt_get_time() ;
285 if (smc
->srf
.any_report
&& (u_long
) tsr
>=
286 smc
->srf
.SRThreshold
) {
287 smc
->srf
.SRThreshold
*= 2 ;
288 if (smc
->srf
.SRThreshold
> THRESHOLD_32
)
289 smc
->srf
.SRThreshold
= THRESHOLD_32
;
290 smc
->srf
.TSR
= smt_get_time() ;
295 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
296 smc
->srf
.sr_state
= SR2_DISABLED
;
302 if (tsr
>= T_Limit
) {
303 smc
->srf
.sr_state
= SR0_WAIT
;
304 smc
->srf
.TSR
= smt_get_time() ;
310 smc
->srf
.SRThreshold
= THRESHOLD_2
;
316 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
317 smc
->srf
.sr_state
= SR2_DISABLED
;
322 if (smc
->mib
.fddiSMTStatRptPolicy
) {
323 smc
->srf
.sr_state
= SR0_WAIT
;
324 smc
->srf
.TSR
= smt_get_time() ;
325 smc
->srf
.SRThreshold
= THRESHOLD_2
;
333 static void clear_all_rep(struct s_smc
*smc
)
335 struct s_srf_evc
*evc
;
338 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
339 evc
->evc_rep_required
= FALSE
;
340 if (SMT_IS_CONDITION(evc
->evc_code
))
341 *evc
->evc_cond_state
= FALSE
;
343 smc
->srf
.any_report
= FALSE
;
346 static void clear_reported(struct s_smc
*smc
)
348 struct s_srf_evc
*evc
;
351 smc
->srf
.any_report
= FALSE
;
352 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
353 if (SMT_IS_CONDITION(evc
->evc_code
)) {
354 if (*evc
->evc_cond_state
== FALSE
)
355 evc
->evc_rep_required
= FALSE
;
357 smc
->srf
.any_report
= TRUE
;
360 evc
->evc_rep_required
= FALSE
;
361 *evc
->evc_multiple
= FALSE
;
367 * build and send SMT SRF frame
369 static void smt_send_srf(struct s_smc
*smc
)
372 struct smt_header
*smt
;
373 struct s_srf_evc
*evc
;
374 SK_LOC_DECL(struct s_pcon
,pcon
) ;
378 static const struct fddi_addr SMT_SRF_DA
= {
379 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
385 if (!smc
->r
.sm_ma_avail
)
387 if (!(mb
= smt_build_frame(smc
,SMT_SRF
,SMT_ANNOUNCE
,0)))
390 RS_SET(smc
,RS_SOFTERROR
) ;
392 smt
= smtod(mb
, struct smt_header
*) ;
393 smt
->smt_dest
= SMT_SRF_DA
; /* DA == SRF multicast */
396 * setup parameter status
398 pcon
.pc_len
= SMT_MAX_INFO_LEN
; /* max para length */
399 pcon
.pc_err
= 0 ; /* no error */
400 pcon
.pc_badset
= 0 ; /* no bad set count */
401 pcon
.pc_p
= (void *) (smt
+ 1) ; /* paras start here */
403 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1033
,0,0) ;
404 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1034
,0,0) ;
406 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
407 if (evc
->evc_rep_required
) {
408 smt_add_para(smc
,&pcon
,evc
->evc_para
,
409 (int)evc
->evc_index
,0) ;
412 smt
->smt_len
= SMT_MAX_INFO_LEN
- pcon
.pc_len
;
413 mb
->sm_len
= smt
->smt_len
+ sizeof(struct smt_header
) ;
415 DB_SMT("SRF: sending SRF at %p, len %d", smt
, mb
->sm_len
);
416 DB_SMT("SRF: state SR%d Threshold %lu",
417 smc
->srf
.sr_state
, smc
->srf
.SRThreshold
/ TICKS_PER_SECOND
);
419 dump_smt(smc
,smt
,"SRF Send") ;
421 smt_send_frame(smc
,mb
,FC_SMT_INFO
,0) ;
422 clear_reported(smc
) ;
426 #endif /* no SLIM_SMT */