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 419