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 46 #define MAX_EVCS ARRAY_SIZE(smc->evcs) 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 70 #define MAX_INIT_EVC ARRAY_SIZE(evc_inits) 71 72 void smt_init_evc(struct s_smc *smc) 73 { 74 struct s_srf_evc *evc ; 75 const struct evc_init *init ; 76 unsigned 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 ; 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 int) (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 ; 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 unsigned int i ; 164 struct s_srf_evc *evc ; 165 166 for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { 167 if (evc->evc_code == code && evc->evc_index == index) 168 return evc; 169 } 170 return NULL; 171 } 172 173 #define THRESHOLD_2 (2*TICKS_PER_SECOND) 174 #define THRESHOLD_32 (32*TICKS_PER_SECOND) 175 176 static const char * const srf_names[] = { 177 "None","MACPathChangeEvent", "MACNeighborChangeEvent", 178 "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent", 179 "SMTPeerWrapCondition", "SMTHoldCondition", 180 "MACFrameErrorCondition", "MACDuplicateAddressCondition", 181 "MACNotCopiedCondition", "PORTEBErrorCondition", 182 "PORTLerCondition" 183 } ; 184 185 void smt_srf_event(struct s_smc *smc, int code, int index, int cond) 186 { 187 struct s_srf_evc *evc ; 188 int cond_asserted = 0 ; 189 int cond_deasserted = 0 ; 190 int event_occurred = 0 ; 191 int tsr ; 192 int T_Limit = 2*TICKS_PER_SECOND ; 193 194 if (code == SMT_COND_MAC_DUP_ADDR && cond) { 195 RS_SET(smc,RS_DUPADDR) ; 196 } 197 198 if (code) { 199 DB_SMT("SRF: %s index %d", srf_names[code], index); 200 201 if (!(evc = smt_get_evc(smc,code,index))) { 202 DB_SMT("SRF : smt_get_evc() failed"); 203 return ; 204 } 205 /* 206 * ignore condition if no change 207 */ 208 if (SMT_IS_CONDITION(code)) { 209 if (*evc->evc_cond_state == cond) 210 return ; 211 } 212 213 /* 214 * set transition time stamp 215 */ 216 smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ; 217 if (SMT_IS_CONDITION(code)) { 218 DB_SMT("SRF: condition is %s", cond ? "ON" : "OFF"); 219 if (cond) { 220 *evc->evc_cond_state = TRUE ; 221 evc->evc_rep_required = TRUE ; 222 smc->srf.any_report = TRUE ; 223 cond_asserted = TRUE ; 224 } 225 else { 226 *evc->evc_cond_state = FALSE ; 227 cond_deasserted = TRUE ; 228 } 229 } 230 else { 231 if (evc->evc_rep_required) { 232 *evc->evc_multiple = TRUE ; 233 } 234 else { 235 evc->evc_rep_required = TRUE ; 236 *evc->evc_multiple = FALSE ; 237 } 238 smc->srf.any_report = TRUE ; 239 event_occurred = TRUE ; 240 } 241 #ifdef FDDI_MIB 242 snmp_srf_event(smc,evc) ; 243 #endif /* FDDI_MIB */ 244 } 245 tsr = smt_get_time() - smc->srf.TSR ; 246 247 switch (smc->srf.sr_state) { 248 case SR0_WAIT : 249 /* SR01a */ 250 if (cond_asserted && tsr < T_Limit) { 251 smc->srf.SRThreshold = THRESHOLD_2 ; 252 smc->srf.sr_state = SR1_HOLDOFF ; 253 break ; 254 } 255 /* SR01b */ 256 if (cond_deasserted && tsr < T_Limit) { 257 smc->srf.sr_state = SR1_HOLDOFF ; 258 break ; 259 } 260 /* SR01c */ 261 if (event_occurred && tsr < T_Limit) { 262 smc->srf.sr_state = SR1_HOLDOFF ; 263 break ; 264 } 265 /* SR00b */ 266 if (cond_asserted && tsr >= T_Limit) { 267 smc->srf.SRThreshold = THRESHOLD_2 ; 268 smc->srf.TSR = smt_get_time() ; 269 smt_send_srf(smc) ; 270 break ; 271 } 272 /* SR00c */ 273 if (cond_deasserted && tsr >= T_Limit) { 274 smc->srf.TSR = smt_get_time() ; 275 smt_send_srf(smc) ; 276 break ; 277 } 278 /* SR00d */ 279 if (event_occurred && tsr >= T_Limit) { 280 smc->srf.TSR = smt_get_time() ; 281 smt_send_srf(smc) ; 282 break ; 283 } 284 /* SR00e */ 285 if (smc->srf.any_report && (u_long) tsr >= 286 smc->srf.SRThreshold) { 287 smc->srf.SRThreshold *= 2 ; 288 if (smc->srf.SRThreshold > THRESHOLD_32) 289 smc->srf.SRThreshold = THRESHOLD_32 ; 290 smc->srf.TSR = smt_get_time() ; 291 smt_send_srf(smc) ; 292 break ; 293 } 294 /* SR02 */ 295 if (!smc->mib.fddiSMTStatRptPolicy) { 296 smc->srf.sr_state = SR2_DISABLED ; 297 break ; 298 } 299 break ; 300 case SR1_HOLDOFF : 301 /* SR10b */ 302 if (tsr >= T_Limit) { 303 smc->srf.sr_state = SR0_WAIT ; 304 smc->srf.TSR = smt_get_time() ; 305 smt_send_srf(smc) ; 306 break ; 307 } 308 /* SR11a */ 309 if (cond_asserted) { 310 smc->srf.SRThreshold = THRESHOLD_2 ; 311 } 312 /* SR11b */ 313 /* SR11c */ 314 /* handled above */ 315 /* SR12 */ 316 if (!smc->mib.fddiSMTStatRptPolicy) { 317 smc->srf.sr_state = SR2_DISABLED ; 318 break ; 319 } 320 break ; 321 case SR2_DISABLED : 322 if (smc->mib.fddiSMTStatRptPolicy) { 323 smc->srf.sr_state = SR0_WAIT ; 324 smc->srf.TSR = smt_get_time() ; 325 smc->srf.SRThreshold = THRESHOLD_2 ; 326 clear_all_rep(smc) ; 327 break ; 328 } 329 break ; 330 } 331 } 332 333 static void clear_all_rep(struct s_smc *smc) 334 { 335 struct s_srf_evc *evc ; 336 unsigned int i ; 337 338 for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { 339 evc->evc_rep_required = FALSE ; 340 if (SMT_IS_CONDITION(evc->evc_code)) 341 *evc->evc_cond_state = FALSE ; 342 } 343 smc->srf.any_report = FALSE ; 344 } 345 346 static void clear_reported(struct s_smc *smc) 347 { 348 struct s_srf_evc *evc ; 349 unsigned int i ; 350 351 smc->srf.any_report = FALSE ; 352 for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { 353 if (SMT_IS_CONDITION(evc->evc_code)) { 354 if (*evc->evc_cond_state == FALSE) 355 evc->evc_rep_required = FALSE ; 356 else 357 smc->srf.any_report = TRUE ; 358 } 359 else { 360 evc->evc_rep_required = FALSE ; 361 *evc->evc_multiple = FALSE ; 362 } 363 } 364 } 365 366 /* 367 * build and send SMT SRF frame 368 */ 369 static void smt_send_srf(struct s_smc *smc) 370 { 371 372 struct smt_header *smt ; 373 struct s_srf_evc *evc ; 374 SK_LOC_DECL(struct s_pcon,pcon) ; 375 SMbuf *mb ; 376 unsigned int i ; 377 378 static const struct fddi_addr SMT_SRF_DA = { 379 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 } 380 } ; 381 382 /* 383 * build SMT header 384 */ 385 if (!smc->r.sm_ma_avail) 386 return ; 387 if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0))) 388 return ; 389 390 RS_SET(smc,RS_SOFTERROR) ; 391 392 smt = smtod(mb, struct smt_header *) ; 393 smt->smt_dest = SMT_SRF_DA ; /* DA == SRF multicast */ 394 395 /* 396 * setup parameter status 397 */ 398 pcon.pc_len = SMT_MAX_INFO_LEN ; /* max para length */ 399 pcon.pc_err = 0 ; /* no error */ 400 pcon.pc_badset = 0 ; /* no bad set count */ 401 pcon.pc_p = (void *) (smt + 1) ; /* paras start here */ 402 403 smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ; 404 smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ; 405 406 for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) { 407 if (evc->evc_rep_required) { 408 smt_add_para(smc,&pcon,evc->evc_para, 409 (int)evc->evc_index,0) ; 410 } 411 } 412 smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ; 413 mb->sm_len = smt->smt_len + sizeof(struct smt_header) ; 414 415 DB_SMT("SRF: sending SRF at %p, len %d", smt, mb->sm_len); 416 DB_SMT("SRF: state SR%d Threshold %lu", 417 smc->srf.sr_state, smc->srf.SRThreshold / TICKS_PER_SECOND); 418 #ifdef DEBUG 419 dump_smt(smc,smt,"SRF Send") ; 420 #endif 421 smt_send_frame(smc,mb,FC_SMT_INFO,0) ; 422 clear_reported(smc) ; 423 } 424 425 #endif /* no BOOT */ 426 #endif /* no SLIM_SMT */ 427 428