Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
3 | * (C)Copyright 1998,1999 SysKonnect, | |
4 | * a business unit of Schneider & Koch & Co. Datensysteme GmbH. | |
5 | * | |
6 | * See the file "skfddi.c" for further information. | |
7 | * | |
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. | |
12 | * | |
13 | * The information in this file is provided "AS IS" without warranty. | |
14 | * | |
15 | ******************************************************************************/ | |
16 | ||
17 | /* | |
18 | SMT 7.2 Status Response Frame Implementation | |
19 | SRF state machine and frame generation | |
20 | */ | |
21 | ||
22 | #include "h/types.h" | |
23 | #include "h/fddi.h" | |
24 | #include "h/smc.h" | |
25 | #include "h/smt_p.h" | |
26 | ||
27 | #define KERNEL | |
28 | #include "h/smtstate.h" | |
29 | ||
30 | #ifndef SLIM_SMT | |
31 | #ifndef BOOT | |
32 | ||
33 | #ifndef lint | |
34 | static const char ID_sccs[] = "@(#)srf.c 1.18 97/08/04 (C) SK " ; | |
35 | #endif | |
36 | ||
37 | ||
38 | /* | |
39 | * function declarations | |
40 | */ | |
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); | |
45 | ||
ff8ac609 | 46 | #define MAX_EVCS ARRAY_SIZE(smc->evcs) |
1da177e4 LT |
47 | |
48 | struct evc_init { | |
49 | u_char code ; | |
50 | u_char index ; | |
51 | u_char n ; | |
52 | u_short para ; | |
53 | } ; | |
54 | ||
55 | static const struct evc_init evc_inits[] = { | |
56 | { SMT_COND_SMT_PEER_WRAP, 0,1,SMT_P1048 } , | |
57 | ||
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 } , | |
63 | ||
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 } , | |
68 | } ; | |
69 | ||
ff8ac609 | 70 | #define MAX_INIT_EVC ARRAY_SIZE(evc_inits) |
1da177e4 LT |
71 | |
72 | void smt_init_evc(struct s_smc *smc) | |
73 | { | |
74 | struct s_srf_evc *evc ; | |
75 | const struct evc_init *init ; | |
76 | int i ; | |
77 | int index ; | |
78 | int offset ; | |
79 | ||
80 | static u_char fail_safe = FALSE ; | |
81 | ||
82 | memset((char *)smc->evcs,0,sizeof(smc->evcs)) ; | |
83 | ||
84 | evc = smc->evcs ; | |
85 | init = evc_inits ; | |
86 | ||
87 | for (i = 0 ; (unsigned) 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 ; | |
92 | #ifndef DEBUG | |
93 | evc->evc_multiple = &fail_safe ; | |
94 | evc->evc_cond_state = &fail_safe ; | |
95 | #endif | |
96 | evc++ ; | |
97 | } | |
98 | init++ ; | |
99 | } | |
100 | ||
101 | if ((unsigned) (evc - smc->evcs) > MAX_EVCS) { | |
102 | SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ; | |
103 | } | |
104 | ||
105 | /* | |
106 | * conditions | |
107 | */ | |
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 ; | |
115 | ||
116 | /* | |
117 | * events | |
118 | */ | |
119 | smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ; | |
120 | smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ; | |
121 | ||
122 | offset = 6 ; | |
123 | for (i = 0 ; i < NUMPHYS ; i++) { | |
124 | /* | |
125 | * conditions | |
126 | */ | |
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 ; | |
131 | ||
132 | /* | |
133 | * events | |
134 | */ | |
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 ; | |
139 | offset++ ; | |
140 | } | |
141 | #ifdef DEBUG | |
142 | for (i = 0, evc = smc->evcs ; (unsigned) 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) ; | |
146 | } | |
147 | evc->evc_multiple = &fail_safe ; | |
148 | } | |
149 | else { | |
150 | if (!evc->evc_multiple) { | |
151 | SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ; | |
152 | } | |
153 | evc->evc_cond_state = &fail_safe ; | |
154 | } | |
155 | } | |
156 | #endif | |
157 | smc->srf.TSR = smt_get_time() ; | |
158 | smc->srf.sr_state = SR0_WAIT ; | |
159 | } | |
160 | ||
161 | static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index) | |
162 | { | |
163 | int i ; | |
164 | struct s_srf_evc *evc ; | |
165 | ||
166 | for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) { | |
167 | if (evc->evc_code == code && evc->evc_index == index) | |
807540ba | 168 | return evc; |
1da177e4 LT |
169 | } |
170 | return NULL; | |
171 | } | |
172 | ||
173 | #define THRESHOLD_2 (2*TICKS_PER_SECOND) | |
174 | #define THRESHOLD_32 (32*TICKS_PER_SECOND) | |
175 | ||
176 | #ifdef DEBUG | |
177 | static const char * const srf_names[] = { | |
178 | "None","MACPathChangeEvent", "MACNeighborChangeEvent", | |
179 | "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent", | |
180 | "SMTPeerWrapCondition", "SMTHoldCondition", | |
181 | "MACFrameErrorCondition", "MACDuplicateAddressCondition", | |
182 | "MACNotCopiedCondition", "PORTEBErrorCondition", | |
183 | "PORTLerCondition" | |
184 | } ; | |
185 | #endif | |
186 | ||
187 | void smt_srf_event(struct s_smc *smc, int code, int index, int cond) | |
188 | { | |
189 | struct s_srf_evc *evc ; | |
190 | int cond_asserted = 0 ; | |
191 | int cond_deasserted = 0 ; | |
192 | int event_occurred = 0 ; | |
193 | int tsr ; | |
194 | int T_Limit = 2*TICKS_PER_SECOND ; | |
195 | ||
196 | if (code == SMT_COND_MAC_DUP_ADDR && cond) { | |
197 | RS_SET(smc,RS_DUPADDR) ; | |
198 | } | |
199 | ||
200 | if (code) { | |
201 | DB_SMT("SRF: %s index %d\n",srf_names[code],index) ; | |
202 | ||
203 | if (!(evc = smt_get_evc(smc,code,index))) { | |
204 | DB_SMT("SRF : smt_get_evc() failed\n",0,0) ; | |
205 | return ; | |
206 | } | |
207 | /* | |
208 | * ignore condition if no change | |
209 | */ | |
210 | if (SMT_IS_CONDITION(code)) { | |
211 | if (*evc->evc_cond_state == cond) | |
212 | return ; | |
213 | } | |
214 | ||
215 | /* | |
216 | * set transition time stamp | |
217 | */ | |
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) ; | |
221 | if (cond) { | |
222 | *evc->evc_cond_state = TRUE ; | |
223 | evc->evc_rep_required = TRUE ; | |
224 | smc->srf.any_report = TRUE ; | |
225 | cond_asserted = TRUE ; | |
226 | } | |
227 | else { | |
228 | *evc->evc_cond_state = FALSE ; | |
229 | cond_deasserted = TRUE ; | |
230 | } | |
231 | } | |
232 | else { | |
233 | if (evc->evc_rep_required) { | |
234 | *evc->evc_multiple = TRUE ; | |
235 | } | |
236 | else { | |
237 | evc->evc_rep_required = TRUE ; | |
238 | *evc->evc_multiple = FALSE ; | |
239 | } | |
240 | smc->srf.any_report = TRUE ; | |
241 | event_occurred = TRUE ; | |
242 | } | |
243 | #ifdef FDDI_MIB | |
244 | snmp_srf_event(smc,evc) ; | |
245 | #endif /* FDDI_MIB */ | |
246 | } | |
247 | tsr = smt_get_time() - smc->srf.TSR ; | |
248 | ||
249 | switch (smc->srf.sr_state) { | |
250 | case SR0_WAIT : | |
251 | /* SR01a */ | |
252 | if (cond_asserted && tsr < T_Limit) { | |
253 | smc->srf.SRThreshold = THRESHOLD_2 ; | |
254 | smc->srf.sr_state = SR1_HOLDOFF ; | |
255 | break ; | |
256 | } | |
257 | /* SR01b */ | |
258 | if (cond_deasserted && tsr < T_Limit) { | |
259 | smc->srf.sr_state = SR1_HOLDOFF ; | |
260 | break ; | |
261 | } | |
262 | /* SR01c */ | |
263 | if (event_occurred && tsr < T_Limit) { | |
264 | smc->srf.sr_state = SR1_HOLDOFF ; | |
265 | break ; | |
266 | } | |
267 | /* SR00b */ | |
268 | if (cond_asserted && tsr >= T_Limit) { | |
269 | smc->srf.SRThreshold = THRESHOLD_2 ; | |
270 | smc->srf.TSR = smt_get_time() ; | |
271 | smt_send_srf(smc) ; | |
272 | break ; | |
273 | } | |
274 | /* SR00c */ | |
275 | if (cond_deasserted && tsr >= T_Limit) { | |
276 | smc->srf.TSR = smt_get_time() ; | |
277 | smt_send_srf(smc) ; | |
278 | break ; | |
279 | } | |
280 | /* SR00d */ | |
281 | if (event_occurred && tsr >= T_Limit) { | |
282 | smc->srf.TSR = smt_get_time() ; | |
283 | smt_send_srf(smc) ; | |
284 | break ; | |
285 | } | |
286 | /* SR00e */ | |
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() ; | |
293 | smt_send_srf(smc) ; | |
294 | break ; | |
295 | } | |
296 | /* SR02 */ | |
297 | if (!smc->mib.fddiSMTStatRptPolicy) { | |
298 | smc->srf.sr_state = SR2_DISABLED ; | |
299 | break ; | |
300 | } | |
301 | break ; | |
302 | case SR1_HOLDOFF : | |
303 | /* SR10b */ | |
304 | if (tsr >= T_Limit) { | |
305 | smc->srf.sr_state = SR0_WAIT ; | |
306 | smc->srf.TSR = smt_get_time() ; | |
307 | smt_send_srf(smc) ; | |
308 | break ; | |
309 | } | |
310 | /* SR11a */ | |
311 | if (cond_asserted) { | |
312 | smc->srf.SRThreshold = THRESHOLD_2 ; | |
313 | } | |
314 | /* SR11b */ | |
315 | /* SR11c */ | |
316 | /* handled above */ | |
317 | /* SR12 */ | |
318 | if (!smc->mib.fddiSMTStatRptPolicy) { | |
319 | smc->srf.sr_state = SR2_DISABLED ; | |
320 | break ; | |
321 | } | |
322 | break ; | |
323 | case 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 ; | |
328 | clear_all_rep(smc) ; | |
329 | break ; | |
330 | } | |
331 | break ; | |
332 | } | |
333 | } | |
334 | ||
335 | static void clear_all_rep(struct s_smc *smc) | |
336 | { | |
337 | struct s_srf_evc *evc ; | |
338 | int i ; | |
339 | ||
340 | for (i = 0, evc = smc->evcs ; (unsigned) 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 ; | |
344 | } | |
345 | smc->srf.any_report = FALSE ; | |
346 | } | |
347 | ||
348 | static void clear_reported(struct s_smc *smc) | |
349 | { | |
350 | struct s_srf_evc *evc ; | |
351 | int i ; | |
352 | ||
353 | smc->srf.any_report = FALSE ; | |
354 | for (i = 0, evc = smc->evcs ; (unsigned) 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 ; | |
358 | else | |
359 | smc->srf.any_report = TRUE ; | |
360 | } | |
361 | else { | |
362 | evc->evc_rep_required = FALSE ; | |
363 | *evc->evc_multiple = FALSE ; | |
364 | } | |
365 | } | |
366 | } | |
367 | ||
368 | /* | |
369 | * build and send SMT SRF frame | |
370 | */ | |
371 | static void smt_send_srf(struct s_smc *smc) | |
372 | { | |
373 | ||
374 | struct smt_header *smt ; | |
375 | struct s_srf_evc *evc ; | |
376 | SK_LOC_DECL(struct s_pcon,pcon) ; | |
377 | SMbuf *mb ; | |
378 | int i ; | |
379 | ||
380 | static const struct fddi_addr SMT_SRF_DA = { | |
381 | { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 } | |
382 | } ; | |
383 | ||
384 | /* | |
385 | * build SMT header | |
386 | */ | |
387 | if (!smc->r.sm_ma_avail) | |
388 | return ; | |
389 | if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0))) | |
390 | return ; | |
391 | ||
392 | RS_SET(smc,RS_SOFTERROR) ; | |
393 | ||
394 | smt = smtod(mb, struct smt_header *) ; | |
395 | smt->smt_dest = SMT_SRF_DA ; /* DA == SRF multicast */ | |
396 | ||
397 | /* | |
398 | * setup parameter status | |
399 | */ | |
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 */ | |
404 | ||
405 | smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ; | |
406 | smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ; | |
407 | ||
408 | for (i = 0, evc = smc->evcs ; (unsigned) 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) ; | |
412 | } | |
413 | } | |
414 | smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ; | |
415 | mb->sm_len = smt->smt_len + sizeof(struct smt_header) ; | |
416 | ||
2381a55c | 417 | DB_SMT("SRF: sending SRF at %x, len %d\n",smt,mb->sm_len) ; |
1da177e4 LT |
418 | DB_SMT("SRF: state SR%d Threshold %d\n", |
419 | smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ; | |
420 | #ifdef DEBUG | |
421 | dump_smt(smc,smt,"SRF Send") ; | |
422 | #endif | |
423 | smt_send_frame(smc,mb,FC_SMT_INFO,0) ; | |
424 | clear_reported(smc) ; | |
425 | } | |
426 | ||
427 | #endif /* no BOOT */ | |
428 | #endif /* no SLIM_SMT */ | |
429 |