1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /******************************************************************************
4 * (C)Copyright 1998,1999 SysKonnect,
5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
7 * See the file "skfddi.c" for further information.
9 * The information in this file is provided "AS IS" without warranty.
11 ******************************************************************************/
14 SMT 7.2 Status Response Frame Implementation
15 SRF state machine and frame generation
24 #include "h/smtstate.h"
30 static const char ID_sccs
[] = "@(#)srf.c 1.18 97/08/04 (C) SK " ;
35 * function declarations
37 static void clear_all_rep(struct s_smc
*smc
);
38 static void clear_reported(struct s_smc
*smc
);
39 static void smt_send_srf(struct s_smc
*smc
);
40 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
);
42 #define MAX_EVCS ARRAY_SIZE(smc->evcs)
51 static const struct evc_init evc_inits
[] = {
52 { SMT_COND_SMT_PEER_WRAP
, 0,1,SMT_P1048
} ,
54 { SMT_COND_MAC_DUP_ADDR
, INDEX_MAC
, NUMMACS
,SMT_P208C
} ,
55 { SMT_COND_MAC_FRAME_ERROR
, INDEX_MAC
, NUMMACS
,SMT_P208D
} ,
56 { SMT_COND_MAC_NOT_COPIED
, INDEX_MAC
, NUMMACS
,SMT_P208E
} ,
57 { SMT_EVENT_MAC_NEIGHBOR_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P208F
} ,
58 { SMT_EVENT_MAC_PATH_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P2090
} ,
60 { SMT_COND_PORT_LER
, INDEX_PORT
,NUMPHYS
,SMT_P4050
} ,
61 { SMT_COND_PORT_EB_ERROR
, INDEX_PORT
,NUMPHYS
,SMT_P4052
} ,
62 { SMT_EVENT_PORT_CONNECTION
, INDEX_PORT
,NUMPHYS
,SMT_P4051
} ,
63 { SMT_EVENT_PORT_PATH_CHANGE
, INDEX_PORT
,NUMPHYS
,SMT_P4053
} ,
66 #define MAX_INIT_EVC ARRAY_SIZE(evc_inits)
68 void smt_init_evc(struct s_smc
*smc
)
70 struct s_srf_evc
*evc
;
71 const struct evc_init
*init
;
76 static u_char fail_safe
= FALSE
;
78 memset((char *)smc
->evcs
,0,sizeof(smc
->evcs
)) ;
83 for (i
= 0 ; i
< MAX_INIT_EVC
; i
++) {
84 for (index
= 0 ; index
< init
->n
; index
++) {
85 evc
->evc_code
= init
->code
;
86 evc
->evc_para
= init
->para
;
87 evc
->evc_index
= init
->index
+ index
;
89 evc
->evc_multiple
= &fail_safe
;
90 evc
->evc_cond_state
= &fail_safe
;
97 if ((unsigned int) (evc
- smc
->evcs
) > MAX_EVCS
) {
98 SMT_PANIC(smc
,SMT_E0127
, SMT_E0127_MSG
) ;
104 smc
->evcs
[0].evc_cond_state
= &smc
->mib
.fddiSMTPeerWrapFlag
;
105 smc
->evcs
[1].evc_cond_state
=
106 &smc
->mib
.m
[MAC0
].fddiMACDuplicateAddressCond
;
107 smc
->evcs
[2].evc_cond_state
=
108 &smc
->mib
.m
[MAC0
].fddiMACFrameErrorFlag
;
109 smc
->evcs
[3].evc_cond_state
=
110 &smc
->mib
.m
[MAC0
].fddiMACNotCopiedFlag
;
115 smc
->evcs
[4].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_N
;
116 smc
->evcs
[5].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_P
;
119 for (i
= 0 ; i
< NUMPHYS
; i
++) {
123 smc
->evcs
[offset
+ 0*NUMPHYS
].evc_cond_state
=
124 &smc
->mib
.p
[i
].fddiPORTLerFlag
;
125 smc
->evcs
[offset
+ 1*NUMPHYS
].evc_cond_state
=
126 &smc
->mib
.p
[i
].fddiPORTEB_Condition
;
131 smc
->evcs
[offset
+ 2*NUMPHYS
].evc_multiple
=
132 &smc
->mib
.p
[i
].fddiPORTMultiple_U
;
133 smc
->evcs
[offset
+ 3*NUMPHYS
].evc_multiple
=
134 &smc
->mib
.p
[i
].fddiPORTMultiple_P
;
138 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
139 if (SMT_IS_CONDITION(evc
->evc_code
)) {
140 if (!evc
->evc_cond_state
) {
141 SMT_PANIC(smc
,SMT_E0128
, SMT_E0128_MSG
) ;
143 evc
->evc_multiple
= &fail_safe
;
146 if (!evc
->evc_multiple
) {
147 SMT_PANIC(smc
,SMT_E0129
, SMT_E0129_MSG
) ;
149 evc
->evc_cond_state
= &fail_safe
;
153 smc
->srf
.TSR
= smt_get_time() ;
154 smc
->srf
.sr_state
= SR0_WAIT
;
157 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
)
160 struct s_srf_evc
*evc
;
162 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
163 if (evc
->evc_code
== code
&& evc
->evc_index
== index
)
169 #define THRESHOLD_2 (2*TICKS_PER_SECOND)
170 #define THRESHOLD_32 (32*TICKS_PER_SECOND)
172 static const char * const srf_names
[] = {
173 "None","MACPathChangeEvent", "MACNeighborChangeEvent",
174 "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent",
175 "SMTPeerWrapCondition", "SMTHoldCondition",
176 "MACFrameErrorCondition", "MACDuplicateAddressCondition",
177 "MACNotCopiedCondition", "PORTEBErrorCondition",
181 void smt_srf_event(struct s_smc
*smc
, int code
, int index
, int cond
)
183 struct s_srf_evc
*evc
;
184 int cond_asserted
= 0 ;
185 int cond_deasserted
= 0 ;
186 int event_occurred
= 0 ;
188 int T_Limit
= 2*TICKS_PER_SECOND
;
190 if (code
== SMT_COND_MAC_DUP_ADDR
&& cond
) {
191 RS_SET(smc
,RS_DUPADDR
) ;
195 DB_SMT("SRF: %s index %d", srf_names
[code
], index
);
197 if (!(evc
= smt_get_evc(smc
,code
,index
))) {
198 DB_SMT("SRF : smt_get_evc() failed");
202 * ignore condition if no change
204 if (SMT_IS_CONDITION(code
)) {
205 if (*evc
->evc_cond_state
== cond
)
210 * set transition time stamp
212 smt_set_timestamp(smc
,smc
->mib
.fddiSMTTransitionTimeStamp
) ;
213 if (SMT_IS_CONDITION(code
)) {
214 DB_SMT("SRF: condition is %s", cond
? "ON" : "OFF");
216 *evc
->evc_cond_state
= TRUE
;
217 evc
->evc_rep_required
= TRUE
;
218 smc
->srf
.any_report
= TRUE
;
219 cond_asserted
= TRUE
;
222 *evc
->evc_cond_state
= FALSE
;
223 cond_deasserted
= TRUE
;
227 if (evc
->evc_rep_required
) {
228 *evc
->evc_multiple
= TRUE
;
231 evc
->evc_rep_required
= TRUE
;
232 *evc
->evc_multiple
= FALSE
;
234 smc
->srf
.any_report
= TRUE
;
235 event_occurred
= TRUE
;
238 snmp_srf_event(smc
,evc
) ;
239 #endif /* FDDI_MIB */
241 tsr
= smt_get_time() - smc
->srf
.TSR
;
243 switch (smc
->srf
.sr_state
) {
246 if (cond_asserted
&& tsr
< T_Limit
) {
247 smc
->srf
.SRThreshold
= THRESHOLD_2
;
248 smc
->srf
.sr_state
= SR1_HOLDOFF
;
252 if (cond_deasserted
&& tsr
< T_Limit
) {
253 smc
->srf
.sr_state
= SR1_HOLDOFF
;
257 if (event_occurred
&& tsr
< T_Limit
) {
258 smc
->srf
.sr_state
= SR1_HOLDOFF
;
262 if (cond_asserted
&& tsr
>= T_Limit
) {
263 smc
->srf
.SRThreshold
= THRESHOLD_2
;
264 smc
->srf
.TSR
= smt_get_time() ;
269 if (cond_deasserted
&& tsr
>= T_Limit
) {
270 smc
->srf
.TSR
= smt_get_time() ;
275 if (event_occurred
&& tsr
>= T_Limit
) {
276 smc
->srf
.TSR
= smt_get_time() ;
281 if (smc
->srf
.any_report
&& (u_long
) tsr
>=
282 smc
->srf
.SRThreshold
) {
283 smc
->srf
.SRThreshold
*= 2 ;
284 if (smc
->srf
.SRThreshold
> THRESHOLD_32
)
285 smc
->srf
.SRThreshold
= THRESHOLD_32
;
286 smc
->srf
.TSR
= smt_get_time() ;
291 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
292 smc
->srf
.sr_state
= SR2_DISABLED
;
298 if (tsr
>= T_Limit
) {
299 smc
->srf
.sr_state
= SR0_WAIT
;
300 smc
->srf
.TSR
= smt_get_time() ;
306 smc
->srf
.SRThreshold
= THRESHOLD_2
;
312 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
313 smc
->srf
.sr_state
= SR2_DISABLED
;
318 if (smc
->mib
.fddiSMTStatRptPolicy
) {
319 smc
->srf
.sr_state
= SR0_WAIT
;
320 smc
->srf
.TSR
= smt_get_time() ;
321 smc
->srf
.SRThreshold
= THRESHOLD_2
;
329 static void clear_all_rep(struct s_smc
*smc
)
331 struct s_srf_evc
*evc
;
334 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
335 evc
->evc_rep_required
= FALSE
;
336 if (SMT_IS_CONDITION(evc
->evc_code
))
337 *evc
->evc_cond_state
= FALSE
;
339 smc
->srf
.any_report
= FALSE
;
342 static void clear_reported(struct s_smc
*smc
)
344 struct s_srf_evc
*evc
;
347 smc
->srf
.any_report
= FALSE
;
348 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
349 if (SMT_IS_CONDITION(evc
->evc_code
)) {
350 if (*evc
->evc_cond_state
== FALSE
)
351 evc
->evc_rep_required
= FALSE
;
353 smc
->srf
.any_report
= TRUE
;
356 evc
->evc_rep_required
= FALSE
;
357 *evc
->evc_multiple
= FALSE
;
363 * build and send SMT SRF frame
365 static void smt_send_srf(struct s_smc
*smc
)
368 struct smt_header
*smt
;
369 struct s_srf_evc
*evc
;
370 SK_LOC_DECL(struct s_pcon
,pcon
) ;
374 static const struct fddi_addr SMT_SRF_DA
= {
375 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
381 if (!smc
->r
.sm_ma_avail
)
383 if (!(mb
= smt_build_frame(smc
,SMT_SRF
,SMT_ANNOUNCE
,0)))
386 RS_SET(smc
,RS_SOFTERROR
) ;
388 smt
= smtod(mb
, struct smt_header
*) ;
389 smt
->smt_dest
= SMT_SRF_DA
; /* DA == SRF multicast */
392 * setup parameter status
394 pcon
.pc_len
= SMT_MAX_INFO_LEN
; /* max para length */
395 pcon
.pc_err
= 0 ; /* no error */
396 pcon
.pc_badset
= 0 ; /* no bad set count */
397 pcon
.pc_p
= (void *) (smt
+ 1) ; /* paras start here */
399 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1033
,0,0) ;
400 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1034
,0,0) ;
402 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
403 if (evc
->evc_rep_required
) {
404 smt_add_para(smc
,&pcon
,evc
->evc_para
,
405 (int)evc
->evc_index
,0) ;
408 smt
->smt_len
= SMT_MAX_INFO_LEN
- pcon
.pc_len
;
409 mb
->sm_len
= smt
->smt_len
+ sizeof(struct smt_header
) ;
411 DB_SMT("SRF: sending SRF at %p, len %d", smt
, mb
->sm_len
);
412 DB_SMT("SRF: state SR%d Threshold %lu",
413 smc
->srf
.sr_state
, smc
->srf
.SRThreshold
/ TICKS_PER_SECOND
);
415 dump_smt(smc
,smt
,"SRF Send") ;
417 smt_send_frame(smc
,mb
,FC_SMT_INFO
,0) ;
418 clear_reported(smc
) ;
422 #endif /* no SLIM_SMT */