Mention branches and keyring.
[releases.git] / fddi / skfp / srf.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /******************************************************************************
3  *
4  *      (C)Copyright 1998,1999 SysKonnect,
5  *      a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6  *
7  *      See the file "skfddi.c" for further information.
8  *
9  *      The information in this file is provided "AS IS" without warranty.
10  *
11  ******************************************************************************/
12
13 /*
14         SMT 7.2 Status Response Frame Implementation
15         SRF state machine and frame generation
16 */
17
18 #include "h/types.h"
19 #include "h/fddi.h"
20 #include "h/smc.h"
21 #include "h/smt_p.h"
22
23 #define KERNEL
24 #include "h/smtstate.h"
25
26 #ifndef SLIM_SMT
27 #ifndef BOOT
28
29 /*
30  * function declarations
31  */
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);
36
37 #define MAX_EVCS        ARRAY_SIZE(smc->evcs)
38
39 struct evc_init {
40         u_char code ;
41         u_char index ;
42         u_char n ;
43         u_short para ;
44 }  ;
45
46 static const struct evc_init evc_inits[] = {
47         { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
48
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 } ,
54
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 } ,
59 } ;
60
61 #define MAX_INIT_EVC    ARRAY_SIZE(evc_inits)
62
63 void smt_init_evc(struct s_smc *smc)
64 {
65         struct s_srf_evc        *evc ;
66         const struct evc_init   *init ;
67         unsigned int            i ;
68         int                     index ;
69         int                     offset ;
70
71         static u_char           fail_safe = FALSE ;
72
73         memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
74
75         evc = smc->evcs ;
76         init = evc_inits ;
77
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 ;
83 #ifndef DEBUG
84                         evc->evc_multiple = &fail_safe ;
85                         evc->evc_cond_state = &fail_safe ;
86 #endif
87                         evc++ ;
88                 }
89                 init++ ;
90         }
91
92         if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
93                 SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
94         }
95
96         /*
97          * conditions
98          */
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 ;
106
107         /*
108          * events
109          */
110         smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
111         smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
112
113         offset = 6 ;
114         for (i = 0 ; i < NUMPHYS ; i++) {
115                 /*
116                  * conditions
117                  */
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 ;
122
123                 /*
124                  * events
125                  */
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 ;
130                 offset++ ;
131         }
132 #ifdef  DEBUG
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) ;
137                         }
138                         evc->evc_multiple = &fail_safe ;
139                 }
140                 else {
141                         if (!evc->evc_multiple) {
142                                 SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
143                         }
144                         evc->evc_cond_state = &fail_safe ;
145                 }
146         }
147 #endif
148         smc->srf.TSR = smt_get_time() ;
149         smc->srf.sr_state = SR0_WAIT ;
150 }
151
152 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
153 {
154         unsigned int            i ;
155         struct s_srf_evc        *evc ;
156
157         for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
158                 if (evc->evc_code == code && evc->evc_index == index)
159                         return evc;
160         }
161         return NULL;
162 }
163
164 #define THRESHOLD_2     (2*TICKS_PER_SECOND)
165 #define THRESHOLD_32    (32*TICKS_PER_SECOND)
166
167 static const char * const srf_names[] = {
168         "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
169         "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
170         "SMTPeerWrapCondition",         "SMTHoldCondition",
171         "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
172         "MACNotCopiedCondition",        "PORTEBErrorCondition",
173         "PORTLerCondition"
174 } ;
175
176 void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
177 {
178         struct s_srf_evc        *evc ;
179         int                     cond_asserted = 0 ;
180         int                     cond_deasserted = 0 ;
181         int                     event_occurred = 0 ;
182         int                     tsr ;
183         int                     T_Limit = 2*TICKS_PER_SECOND ;
184
185         if (code == SMT_COND_MAC_DUP_ADDR && cond) {
186                 RS_SET(smc,RS_DUPADDR) ;
187         }
188
189         if (code) {
190                 DB_SMT("SRF: %s index %d", srf_names[code], index);
191
192                 if (!(evc = smt_get_evc(smc,code,index))) {
193                         DB_SMT("SRF : smt_get_evc() failed");
194                         return ;
195                 }
196                 /*
197                  * ignore condition if no change
198                  */
199                 if (SMT_IS_CONDITION(code)) {
200                         if (*evc->evc_cond_state == cond)
201                                 return ;
202                 }
203
204                 /*
205                  * set transition time stamp
206                  */
207                 smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
208                 if (SMT_IS_CONDITION(code)) {
209                         DB_SMT("SRF: condition is %s", cond ? "ON" : "OFF");
210                         if (cond) {
211                                 *evc->evc_cond_state = TRUE ;
212                                 evc->evc_rep_required = TRUE ;
213                                 smc->srf.any_report = TRUE ;
214                                 cond_asserted = TRUE ;
215                         }
216                         else {
217                                 *evc->evc_cond_state = FALSE ;
218                                 cond_deasserted = TRUE ;
219                         }
220                 }
221                 else {
222                         if (evc->evc_rep_required) {
223                                 *evc->evc_multiple  = TRUE ;
224                         }
225                         else {
226                                 evc->evc_rep_required = TRUE ;
227                                 *evc->evc_multiple  = FALSE ;
228                         }
229                         smc->srf.any_report = TRUE ;
230                         event_occurred = TRUE ;
231                 }
232 #ifdef  FDDI_MIB
233                 snmp_srf_event(smc,evc) ;
234 #endif  /* FDDI_MIB */
235         }
236         tsr = smt_get_time() - smc->srf.TSR ;
237
238         switch (smc->srf.sr_state) {
239         case SR0_WAIT :
240                 /* SR01a */
241                 if (cond_asserted && tsr < T_Limit) {
242                         smc->srf.SRThreshold = THRESHOLD_2 ;
243                         smc->srf.sr_state = SR1_HOLDOFF ;
244                         break ;
245                 }
246                 /* SR01b */
247                 if (cond_deasserted && tsr < T_Limit) {
248                         smc->srf.sr_state = SR1_HOLDOFF ;
249                         break ;
250                 }
251                 /* SR01c */
252                 if (event_occurred && tsr < T_Limit) {
253                         smc->srf.sr_state = SR1_HOLDOFF ;
254                         break ;
255                 }
256                 /* SR00b */
257                 if (cond_asserted && tsr >= T_Limit) {
258                         smc->srf.SRThreshold = THRESHOLD_2 ;
259                         smc->srf.TSR = smt_get_time() ;
260                         smt_send_srf(smc) ;
261                         break ;
262                 }
263                 /* SR00c */
264                 if (cond_deasserted && tsr >= T_Limit) {
265                         smc->srf.TSR = smt_get_time() ;
266                         smt_send_srf(smc) ;
267                         break ;
268                 }
269                 /* SR00d */
270                 if (event_occurred && tsr >= T_Limit) {
271                         smc->srf.TSR = smt_get_time() ;
272                         smt_send_srf(smc) ;
273                         break ;
274                 }
275                 /* SR00e */
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() ;
282                         smt_send_srf(smc) ;
283                         break ;
284                 }
285                 /* SR02 */
286                 if (!smc->mib.fddiSMTStatRptPolicy) {
287                         smc->srf.sr_state = SR2_DISABLED ;
288                         break ;
289                 }
290                 break ;
291         case SR1_HOLDOFF :
292                 /* SR10b */
293                 if (tsr >= T_Limit) {
294                         smc->srf.sr_state = SR0_WAIT ;
295                         smc->srf.TSR = smt_get_time() ;
296                         smt_send_srf(smc) ;
297                         break ;
298                 }
299                 /* SR11a */
300                 if (cond_asserted) {
301                         smc->srf.SRThreshold = THRESHOLD_2 ;
302                 }
303                 /* SR11b */
304                 /* SR11c */
305                 /* handled above */
306                 /* SR12 */
307                 if (!smc->mib.fddiSMTStatRptPolicy) {
308                         smc->srf.sr_state = SR2_DISABLED ;
309                         break ;
310                 }
311                 break ;
312         case 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 ;
317                         clear_all_rep(smc) ;
318                         break ;
319                 }
320                 break ;
321         }
322 }
323
324 static void clear_all_rep(struct s_smc *smc)
325 {
326         struct s_srf_evc        *evc ;
327         unsigned int            i ;
328
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 ;
333         }
334         smc->srf.any_report = FALSE ;
335 }
336
337 static void clear_reported(struct s_smc *smc)
338 {
339         struct s_srf_evc        *evc ;
340         unsigned int            i ;
341
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 ;
347                         else
348                                 smc->srf.any_report = TRUE ;
349                 }
350                 else {
351                         evc->evc_rep_required = FALSE ;
352                         *evc->evc_multiple = FALSE ;
353                 }
354         }
355 }
356
357 /*
358  * build and send SMT SRF frame
359  */
360 static void smt_send_srf(struct s_smc *smc)
361 {
362
363         struct smt_header       *smt ;
364         struct s_srf_evc        *evc ;
365         SK_LOC_DECL(struct s_pcon,pcon) ;
366         SMbuf                   *mb ;
367         unsigned int            i ;
368
369         static const struct fddi_addr SMT_SRF_DA = {
370                 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
371         } ;
372
373         /*
374          * build SMT header
375          */
376         if (!smc->r.sm_ma_avail)
377                 return ;
378         if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
379                 return ;
380
381         RS_SET(smc,RS_SOFTERROR) ;
382
383         smt = smtod(mb, struct smt_header *) ;
384         smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
385
386         /*
387          * setup parameter status
388          */
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 */
393
394         smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
395         smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
396
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) ;
401                 }
402         }
403         smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
404         mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
405
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);
409 #ifdef  DEBUG
410         dump_smt(smc,smt,"SRF Send") ;
411 #endif
412         smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
413         clear_reported(smc) ;
414 }
415
416 #endif  /* no BOOT */
417 #endif  /* no SLIM_SMT */
418