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 #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 unsigned int i ; 339 340 for (i = 0, evc = smc->evcs ; 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 unsigned int i ; 352 353 smc->srf.any_report = FALSE ; 354 for (i = 0, evc = smc->evcs ; 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 unsigned 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 ; 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 417 DB_SMT("SRF: sending SRF at %p, len %d\n",smt,mb->sm_len) ; 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 430