brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 4cad68c Raw
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