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 * function declarations
32 static void clear_all_rep(struct s_smc
*smc
);
33 static void clear_reported(struct s_smc
*smc
);
34 static void smt_send_srf(struct s_smc
*smc
);
35 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
);
37 #define MAX_EVCS ARRAY_SIZE(smc->evcs)
46 static const struct evc_init evc_inits
[] = {
47 { SMT_COND_SMT_PEER_WRAP
, 0,1,SMT_P1048
} ,
49 { SMT_COND_MAC_DUP_ADDR
, INDEX_MAC
, NUMMACS
,SMT_P208C
} ,
50 { SMT_COND_MAC_FRAME_ERROR
, INDEX_MAC
, NUMMACS
,SMT_P208D
} ,
51 { SMT_COND_MAC_NOT_COPIED
, INDEX_MAC
, NUMMACS
,SMT_P208E
} ,
52 { SMT_EVENT_MAC_NEIGHBOR_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P208F
} ,
53 { SMT_EVENT_MAC_PATH_CHANGE
, INDEX_MAC
, NUMMACS
,SMT_P2090
} ,
55 { SMT_COND_PORT_LER
, INDEX_PORT
,NUMPHYS
,SMT_P4050
} ,
56 { SMT_COND_PORT_EB_ERROR
, INDEX_PORT
,NUMPHYS
,SMT_P4052
} ,
57 { SMT_EVENT_PORT_CONNECTION
, INDEX_PORT
,NUMPHYS
,SMT_P4051
} ,
58 { SMT_EVENT_PORT_PATH_CHANGE
, INDEX_PORT
,NUMPHYS
,SMT_P4053
} ,
61 #define MAX_INIT_EVC ARRAY_SIZE(evc_inits)
63 void smt_init_evc(struct s_smc
*smc
)
65 struct s_srf_evc
*evc
;
66 const struct evc_init
*init
;
71 static u_char fail_safe
= FALSE
;
73 memset((char *)smc
->evcs
,0,sizeof(smc
->evcs
)) ;
78 for (i
= 0 ; i
< MAX_INIT_EVC
; i
++) {
79 for (index
= 0 ; index
< init
->n
; index
++) {
80 evc
->evc_code
= init
->code
;
81 evc
->evc_para
= init
->para
;
82 evc
->evc_index
= init
->index
+ index
;
84 evc
->evc_multiple
= &fail_safe
;
85 evc
->evc_cond_state
= &fail_safe
;
92 if ((unsigned int) (evc
- smc
->evcs
) > MAX_EVCS
) {
93 SMT_PANIC(smc
,SMT_E0127
, SMT_E0127_MSG
) ;
99 smc
->evcs
[0].evc_cond_state
= &smc
->mib
.fddiSMTPeerWrapFlag
;
100 smc
->evcs
[1].evc_cond_state
=
101 &smc
->mib
.m
[MAC0
].fddiMACDuplicateAddressCond
;
102 smc
->evcs
[2].evc_cond_state
=
103 &smc
->mib
.m
[MAC0
].fddiMACFrameErrorFlag
;
104 smc
->evcs
[3].evc_cond_state
=
105 &smc
->mib
.m
[MAC0
].fddiMACNotCopiedFlag
;
110 smc
->evcs
[4].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_N
;
111 smc
->evcs
[5].evc_multiple
= &smc
->mib
.m
[MAC0
].fddiMACMultiple_P
;
114 for (i
= 0 ; i
< NUMPHYS
; i
++) {
118 smc
->evcs
[offset
+ 0*NUMPHYS
].evc_cond_state
=
119 &smc
->mib
.p
[i
].fddiPORTLerFlag
;
120 smc
->evcs
[offset
+ 1*NUMPHYS
].evc_cond_state
=
121 &smc
->mib
.p
[i
].fddiPORTEB_Condition
;
126 smc
->evcs
[offset
+ 2*NUMPHYS
].evc_multiple
=
127 &smc
->mib
.p
[i
].fddiPORTMultiple_U
;
128 smc
->evcs
[offset
+ 3*NUMPHYS
].evc_multiple
=
129 &smc
->mib
.p
[i
].fddiPORTMultiple_P
;
133 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
134 if (SMT_IS_CONDITION(evc
->evc_code
)) {
135 if (!evc
->evc_cond_state
) {
136 SMT_PANIC(smc
,SMT_E0128
, SMT_E0128_MSG
) ;
138 evc
->evc_multiple
= &fail_safe
;
141 if (!evc
->evc_multiple
) {
142 SMT_PANIC(smc
,SMT_E0129
, SMT_E0129_MSG
) ;
144 evc
->evc_cond_state
= &fail_safe
;
148 smc
->srf
.TSR
= smt_get_time() ;
149 smc
->srf
.sr_state
= SR0_WAIT
;
152 static struct s_srf_evc
*smt_get_evc(struct s_smc
*smc
, int code
, int index
)
155 struct s_srf_evc
*evc
;
157 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
158 if (evc
->evc_code
== code
&& evc
->evc_index
== index
)
164 #define THRESHOLD_2 (2*TICKS_PER_SECOND)
165 #define THRESHOLD_32 (32*TICKS_PER_SECOND)
167 static const char * const srf_names
[] = {
168 "None","MACPathChangeEvent", "MACNeighborChangeEvent",
169 "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent",
170 "SMTPeerWrapCondition", "SMTHoldCondition",
171 "MACFrameErrorCondition", "MACDuplicateAddressCondition",
172 "MACNotCopiedCondition", "PORTEBErrorCondition",
176 void smt_srf_event(struct s_smc
*smc
, int code
, int index
, int cond
)
178 struct s_srf_evc
*evc
;
179 int cond_asserted
= 0 ;
180 int cond_deasserted
= 0 ;
181 int event_occurred
= 0 ;
183 int T_Limit
= 2*TICKS_PER_SECOND
;
185 if (code
== SMT_COND_MAC_DUP_ADDR
&& cond
) {
186 RS_SET(smc
,RS_DUPADDR
) ;
190 DB_SMT("SRF: %s index %d", srf_names
[code
], index
);
192 if (!(evc
= smt_get_evc(smc
,code
,index
))) {
193 DB_SMT("SRF : smt_get_evc() failed");
197 * ignore condition if no change
199 if (SMT_IS_CONDITION(code
)) {
200 if (*evc
->evc_cond_state
== cond
)
205 * set transition time stamp
207 smt_set_timestamp(smc
,smc
->mib
.fddiSMTTransitionTimeStamp
) ;
208 if (SMT_IS_CONDITION(code
)) {
209 DB_SMT("SRF: condition is %s", cond
? "ON" : "OFF");
211 *evc
->evc_cond_state
= TRUE
;
212 evc
->evc_rep_required
= TRUE
;
213 smc
->srf
.any_report
= TRUE
;
214 cond_asserted
= TRUE
;
217 *evc
->evc_cond_state
= FALSE
;
218 cond_deasserted
= TRUE
;
222 if (evc
->evc_rep_required
) {
223 *evc
->evc_multiple
= TRUE
;
226 evc
->evc_rep_required
= TRUE
;
227 *evc
->evc_multiple
= FALSE
;
229 smc
->srf
.any_report
= TRUE
;
230 event_occurred
= TRUE
;
233 snmp_srf_event(smc
,evc
) ;
234 #endif /* FDDI_MIB */
236 tsr
= smt_get_time() - smc
->srf
.TSR
;
238 switch (smc
->srf
.sr_state
) {
241 if (cond_asserted
&& tsr
< T_Limit
) {
242 smc
->srf
.SRThreshold
= THRESHOLD_2
;
243 smc
->srf
.sr_state
= SR1_HOLDOFF
;
247 if (cond_deasserted
&& tsr
< T_Limit
) {
248 smc
->srf
.sr_state
= SR1_HOLDOFF
;
252 if (event_occurred
&& tsr
< T_Limit
) {
253 smc
->srf
.sr_state
= SR1_HOLDOFF
;
257 if (cond_asserted
&& tsr
>= T_Limit
) {
258 smc
->srf
.SRThreshold
= THRESHOLD_2
;
259 smc
->srf
.TSR
= smt_get_time() ;
264 if (cond_deasserted
&& tsr
>= T_Limit
) {
265 smc
->srf
.TSR
= smt_get_time() ;
270 if (event_occurred
&& tsr
>= T_Limit
) {
271 smc
->srf
.TSR
= smt_get_time() ;
276 if (smc
->srf
.any_report
&& (u_long
) tsr
>=
277 smc
->srf
.SRThreshold
) {
278 smc
->srf
.SRThreshold
*= 2 ;
279 if (smc
->srf
.SRThreshold
> THRESHOLD_32
)
280 smc
->srf
.SRThreshold
= THRESHOLD_32
;
281 smc
->srf
.TSR
= smt_get_time() ;
286 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
287 smc
->srf
.sr_state
= SR2_DISABLED
;
293 if (tsr
>= T_Limit
) {
294 smc
->srf
.sr_state
= SR0_WAIT
;
295 smc
->srf
.TSR
= smt_get_time() ;
301 smc
->srf
.SRThreshold
= THRESHOLD_2
;
307 if (!smc
->mib
.fddiSMTStatRptPolicy
) {
308 smc
->srf
.sr_state
= SR2_DISABLED
;
313 if (smc
->mib
.fddiSMTStatRptPolicy
) {
314 smc
->srf
.sr_state
= SR0_WAIT
;
315 smc
->srf
.TSR
= smt_get_time() ;
316 smc
->srf
.SRThreshold
= THRESHOLD_2
;
324 static void clear_all_rep(struct s_smc
*smc
)
326 struct s_srf_evc
*evc
;
329 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
330 evc
->evc_rep_required
= FALSE
;
331 if (SMT_IS_CONDITION(evc
->evc_code
))
332 *evc
->evc_cond_state
= FALSE
;
334 smc
->srf
.any_report
= FALSE
;
337 static void clear_reported(struct s_smc
*smc
)
339 struct s_srf_evc
*evc
;
342 smc
->srf
.any_report
= FALSE
;
343 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
344 if (SMT_IS_CONDITION(evc
->evc_code
)) {
345 if (*evc
->evc_cond_state
== FALSE
)
346 evc
->evc_rep_required
= FALSE
;
348 smc
->srf
.any_report
= TRUE
;
351 evc
->evc_rep_required
= FALSE
;
352 *evc
->evc_multiple
= FALSE
;
358 * build and send SMT SRF frame
360 static void smt_send_srf(struct s_smc
*smc
)
363 struct smt_header
*smt
;
364 struct s_srf_evc
*evc
;
365 SK_LOC_DECL(struct s_pcon
,pcon
) ;
369 static const struct fddi_addr SMT_SRF_DA
= {
370 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
376 if (!smc
->r
.sm_ma_avail
)
378 if (!(mb
= smt_build_frame(smc
,SMT_SRF
,SMT_ANNOUNCE
,0)))
381 RS_SET(smc
,RS_SOFTERROR
) ;
383 smt
= smtod(mb
, struct smt_header
*) ;
384 smt
->smt_dest
= SMT_SRF_DA
; /* DA == SRF multicast */
387 * setup parameter status
389 pcon
.pc_len
= SMT_MAX_INFO_LEN
; /* max para length */
390 pcon
.pc_err
= 0 ; /* no error */
391 pcon
.pc_badset
= 0 ; /* no bad set count */
392 pcon
.pc_p
= (void *) (smt
+ 1) ; /* paras start here */
394 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1033
,0,0) ;
395 smt_add_para(smc
,&pcon
,(u_short
) SMT_P1034
,0,0) ;
397 for (i
= 0, evc
= smc
->evcs
; i
< MAX_EVCS
; i
++, evc
++) {
398 if (evc
->evc_rep_required
) {
399 smt_add_para(smc
,&pcon
,evc
->evc_para
,
400 (int)evc
->evc_index
,0) ;
403 smt
->smt_len
= SMT_MAX_INFO_LEN
- pcon
.pc_len
;
404 mb
->sm_len
= smt
->smt_len
+ sizeof(struct smt_header
) ;
406 DB_SMT("SRF: sending SRF at %p, len %d", smt
, mb
->sm_len
);
407 DB_SMT("SRF: state SR%d Threshold %lu",
408 smc
->srf
.sr_state
, smc
->srf
.SRThreshold
/ TICKS_PER_SECOND
);
410 dump_smt(smc
,smt
,"SRF Send") ;
412 smt_send_frame(smc
,mb
,FC_SMT_INFO
,0) ;
413 clear_reported(smc
) ;
417 #endif /* no SLIM_SMT */