419 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************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 Implementation15 SRF state machine and frame generation16*/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 KERNEL24#include "h/smtstate.h"25 26#ifndef SLIM_SMT27#ifndef BOOT28 29/*30 * function declarations31 */32static void clear_all_rep(struct s_smc *smc);33static void clear_reported(struct s_smc *smc);34static void smt_send_srf(struct s_smc *smc);35static 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 39struct evc_init {40 u_char code ;41 u_char index ;42 u_char n ;43 u_short para ;44} ;45 46static 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 63void 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 DEBUG84 evc->evc_multiple = &fail_safe ;85 evc->evc_cond_state = &fail_safe ;86#endif87 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 * conditions98 */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 * events109 */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 * conditions117 */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 * events125 */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 DEBUG133 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#endif148 smc->srf.TSR = smt_get_time() ;149 smc->srf.sr_state = SR0_WAIT ;150}151 152static 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 167static 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 176void 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 change198 */199 if (SMT_IS_CONDITION(code)) {200 if (*evc->evc_cond_state == cond)201 return ;202 }203 204 /*205 * set transition time stamp206 */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_MIB233 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 324static 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 337static 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 else348 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 frame359 */360static 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 header375 */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 status388 */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 DEBUG410 dump_smt(smc,smt,"SRF Send") ;411#endif412 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