Exemplo n.º 1
0
static void update_dac(struct s_smc *smc, int report)
{
	int	cond ;

	cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |
		smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;
	if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))
		smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;
	else
		smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;
}
Exemplo n.º 2
0
/*
	PCM state machine
	called by dispatcher  & fddi_init() (driver)
	do
		display state change
		process event
	until SM is stable
*/
void pcm(struct s_smc *smc, const int np, int event)
{
	int	state ;
	int	oldstate ;
	struct s_phy	*phy ;
	struct fddi_mib_p	*mib ;

#ifndef	CONCENTRATOR
	/*
	 * ignore 2nd PHY if SAS
	 */
	if ((np != PS) && (smc->s.sas == SMT_SAS))
		return ;
#endif
	phy = &smc->y[np] ;
	mib = phy->mib ;
	oldstate = mib->fddiPORTPCMState ;
	do {
		DB_PCM("PCM %c: state %s",
			phy->phy_name,
			(mib->fddiPORTPCMState & AFLAG) ? "ACTIONS " : "") ;
		DB_PCM("%s, event %s\n",
			pcm_states[mib->fddiPORTPCMState & ~AFLAG],
			pcm_events[event]) ;
		state = mib->fddiPORTPCMState ;
		pcm_fsm(smc,phy,event) ;
		event = 0 ;
	} while (state != mib->fddiPORTPCMState) ;
	/*
	 * because the PLC does the bit signaling for us,
	 * we're always in SIGNAL state
	 * the MIB want's to see CONNECT
	 * we therefore fake an entry in the MIB
	 */
	if (state == PC5_SIGNAL)
		mib->fddiPORTPCMStateX = PC3_CONNECT ;
	else
		mib->fddiPORTPCMStateX = state ;

#ifndef	SLIM_SMT
	/*
	 * path change
	 */
	if (	mib->fddiPORTPCMState != oldstate &&
		((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
		smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
			(int) (INDEX_PORT+ phy->np),0) ;
	}
#endif

#ifdef FDDI_MIB
	/* check whether a snmp-trap has to be sent */

	if ( mib->fddiPORTPCMState != oldstate ) {
		/* a real state change took place */
		DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
		if ( mib->fddiPORTPCMState == PC0_OFF ) {
			/* send first trap */
			snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
		} else if ( oldstate == PC0_OFF ) {
			/* send second trap */
			snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
		} else if ( mib->fddiPORTPCMState != PC2_TRACE &&
			oldstate == PC8_ACTIVE ) {
			/* send third trap */
			snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
		} else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
			/* send fourth trap */
			snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
		}
	}
#endif

	pcm_state_change(smc,np,state) ;
}
Exemplo n.º 3
0
/*
 * PCM pseudo code 5.1 .. 6.1
 */
static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
{
	int	np = phy->np ;
	struct fddi_mib_p	*mib ;

	mib = phy->mib ;

	switch(bit) {
	case 0:
		phy->t_val[0] = 0 ;		/* no escape used */
		break ;
	case 1:
		if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
			phy->t_val[1] = 1 ;
		else
			phy->t_val[1] = 0 ;
		break ;
	case 2 :
		if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
			phy->t_val[2] = 1 ;
		else
			phy->t_val[2] = 0 ;
		break ;
	case 3:
		{
		int	type,ne ;
		int	policy ;

		type = mib->fddiPORTMy_Type ;
		ne = mib->fddiPORTNeighborType ;
		policy = smc->mib.fddiSMTConnectionPolicy ;

		phy->t_val[3] = 1 ;	/* Accept connection */
		switch (type) {
		case TA :
			if (
				((policy & POLICY_AA) && ne == TA) ||
				((policy & POLICY_AB) && ne == TB) ||
				((policy & POLICY_AS) && ne == TS) ||
				((policy & POLICY_AM) && ne == TM) )
				phy->t_val[3] = 0 ;	/* Reject */
			break ;
		case TB :
			if (
				((policy & POLICY_BA) && ne == TA) ||
				((policy & POLICY_BB) && ne == TB) ||
				((policy & POLICY_BS) && ne == TS) ||
				((policy & POLICY_BM) && ne == TM) )
				phy->t_val[3] = 0 ;	/* Reject */
			break ;
		case TS :
			if (
				((policy & POLICY_SA) && ne == TA) ||
				((policy & POLICY_SB) && ne == TB) ||
				((policy & POLICY_SS) && ne == TS) ||
				((policy & POLICY_SM) && ne == TM) )
				phy->t_val[3] = 0 ;	/* Reject */
			break ;
		case TM :
			if (	ne == TM ||
				((policy & POLICY_MA) && ne == TA) ||
				((policy & POLICY_MB) && ne == TB) ||
				((policy & POLICY_MS) && ne == TS) ||
				((policy & POLICY_MM) && ne == TM) )
				phy->t_val[3] = 0 ;	/* Reject */
			break ;
		}
#ifndef	SLIM_SMT
		/*
		 * detect undesirable connection attempt event
		 */
		if (	(type == TA && ne == TA ) ||
			(type == TA && ne == TS ) ||
			(type == TB && ne == TB ) ||
			(type == TB && ne == TS ) ||
			(type == TS && ne == TA ) ||
			(type == TS && ne == TB ) ) {
			smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
				(int) (INDEX_PORT+ phy->np) ,0) ;
		}
#endif
		}
		break ;
	case 4:
		if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
			if (phy->pc_lem_fail) {
				phy->t_val[4] = 1 ;	/* long */
				phy->t_val[5] = 0 ;
			}
			else {
				phy->t_val[4] = 0 ;
				if (mib->fddiPORTLCTFail_Ct > 0)
					phy->t_val[5] = 1 ;	/* medium */
				else
					phy->t_val[5] = 0 ;	/* short */

				/*
				 * Implementers choice: use medium
				 * instead of short when undesired
				 * connection attempt is made.
				 */
				if (phy->wc_flag)
					phy->t_val[5] = 1 ;	/* medium */
			}
			mib->fddiPORTConnectState = PCM_CONNECTING ;
		}
		else {
			mib->fddiPORTConnectState = PCM_STANDBY ;
			phy->t_val[4] = 1 ;	/* extended */
			phy->t_val[5] = 1 ;
		}
		break ;
	case 5:
		break ;
	case 6:
		/* we do NOT have a MAC for LCT */
		phy->t_val[6] = 0 ;
		break ;
	case 7:
		phy->cf_loop = FALSE ;
		lem_check_lct(smc,phy) ;
		if (phy->pc_lem_fail) {
			DB_PCMN(1,"PCM %c : E104 LCT failed\n",
				phy->phy_name,0) ;
			phy->t_val[7] = 1 ;
		}
		else
			phy->t_val[7] = 0 ;
		break ;
	case 8:
		phy->t_val[8] = 0 ;	/* Don't request MAC loopback */
		break ;
	case 9:
		phy->cf_loop = 0 ;
		if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
		     ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
			queue_event(smc,EVENT_PCM+np,PC_START) ;
			break ;
		}
		phy->t_val[9] = FALSE ;
		switch (smc->s.sas) {
		case SMT_DAS :
			/*
			 * MAC intended on output
			 */
			if (phy->pc_mode == PM_TREE) {
				if ((np == PB) || ((np == PA) &&
				(smc->y[PB].mib->fddiPORTConnectState !=
					PCM_ACTIVE)))
					phy->t_val[9] = TRUE ;
			}
			else {
				if (np == PB)
					phy->t_val[9] = TRUE ;
			}
			break ;
		case SMT_SAS :
			if (np == PS)
				phy->t_val[9] = TRUE ;
			break ;
#ifdef	CONCENTRATOR
		case SMT_NAC :
			/*
			 * MAC intended on output
			 */
			if (np == PB)
				phy->t_val[9] = TRUE ;
			break ;
#endif
		}
		mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
		break ;
	}
	DB_PCMN(1,"SIG snd %x %x:\n", bit,phy->t_val[bit] ) ;
}
Exemplo n.º 4
0
/*
 * link error monitor
 */
static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
{
	int ber ;
	u_long errors ;
	struct lem_counter *lem = &phy->lem ;
	struct fddi_mib_p	*mib ;
	int			cond ;

	mib = phy->mib ;

	if (!lem->lem_on)
		return ;

	errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
	lem->lem_errors += errors ;
	mib->fddiPORTLem_Ct += errors ;

	errors = lem->lem_errors ;
	/*
	 * calculation is called on a intervall of 8 seconds
	 *	-> this means, that one error in 8 sec. is one of 8*125*10E6
	 *	the same as BER = 10E-9
	 * Please note:
	 *	-> 9 errors in 8 seconds mean:
	 *	   BER = 9 * 10E-9  and this is
	 *	    < 10E-8, so the limit of 10E-8 is not reached!
	 */

		if (!errors)		ber = 15 ;
	else	if (errors <= 9)	ber = 9 ;
	else	if (errors <= 99)	ber = 8 ;
	else	if (errors <= 999)	ber = 7 ;
	else	if (errors <= 9999)	ber = 6 ;
	else	if (errors <= 99999)	ber = 5 ;
	else	if (errors <= 999999)	ber = 4 ;
	else	if (errors <= 9999999)	ber = 3 ;
	else	if (errors <= 99999999)	ber = 2 ;
	else	if (errors <= 999999999) ber = 1 ;
	else				ber = 0 ;

	/*
	 * weighted average
	 */
	ber *= 100 ;
	lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
	lem->lem_float_ber /= 10 ;
	mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
	if (mib->fddiPORTLer_Estimate < 4) {
		mib->fddiPORTLer_Estimate = 4 ;
	}

	if (lem->lem_errors) {
		DB_PCMN(1,"LEM %c :\n",phy->np == PB? 'B' : 'A',0) ;
		DB_PCMN(1,"errors      : %ld\n",lem->lem_errors,0) ;
		DB_PCMN(1,"sum_errors  : %ld\n",mib->fddiPORTLem_Ct,0) ;
		DB_PCMN(1,"current BER : 10E-%d\n",ber/100,0) ;
		DB_PCMN(1,"float BER   : 10E-(%d/100)\n",lem->lem_float_ber,0) ;
		DB_PCMN(1,"avg. BER    : 10E-%d\n",
			mib->fddiPORTLer_Estimate,0) ;
	}

	lem->lem_errors = 0L ;

#ifndef	SLIM_SMT
	cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
		TRUE : FALSE ;
#ifdef	SMT_EXT_CUTOFF
	smt_ler_alarm_check(smc,phy,cond) ;
#endif	/* nSMT_EXT_CUTOFF */
	if (cond != mib->fddiPORTLerFlag) {
		smt_srf_event(smc,SMT_COND_PORT_LER,
			(int) (INDEX_PORT+ phy->np) ,cond) ;
	}
#endif

	if (	mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
		phy->pc_lem_fail = TRUE ;		/* flag */
		mib->fddiPORTLem_Reject_Ct++ ;
		/*
		 * "forgive 10e-2" if we cutoff so we can come
		 * up again ..
		 */
		lem->lem_float_ber += 2*100 ;

		/*PC81b*/
#ifdef	CONCENTRATOR
		DB_PCMN(1,"PCM: LER cutoff on port %d cutoff %d\n",
			phy->np, mib->fddiPORTLer_Cutoff) ;
#endif
#ifdef	SMT_EXT_CUTOFF
		smt_port_off_event(smc,phy->np);
#else	/* nSMT_EXT_CUTOFF */
		queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
#endif	/* nSMT_EXT_CUTOFF */
	}
}
Exemplo n.º 5
0
/*
	CFM state machine
	called by dispatcher

	do
		display state change
		process event
	until SM is stable
*/
void cfm(struct s_smc *smc, int event)
{
	int	state ;		/* remember last state */
	int	cond ;
	int	oldstate ;

	/* We will do the following: */
	/*  - compute the variable WC_Flag for every port (This is where */
	/*    we can extend the requested path checking !!) */
	/*  - do the old (SMT 6.2 like) state machine */
	/*  - do the resulting station states */

	all_selection_criteria (smc);

	/* We will check now whether a state transition is allowed or not */
	/*  - change the portstates */
	cem_priv_state (smc, event);

	oldstate = smc->mib.fddiSMTCF_State ;
	do {
		DB_CFM("CFM : state %s%s",
			(smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "",
			cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ;
		DB_CFM(" event %s\n",cfm_events[event],0) ;
		state = smc->mib.fddiSMTCF_State ;
		cfm_fsm(smc,event) ;
		event = 0 ;
	} while (state != smc->mib.fddiSMTCF_State) ;

#ifndef	SLIM_SMT
	/*
	 * check peer wrap condition
	 */
	cond = FALSE ;
	if (	(smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
		smc->y[PA].pc_mode == PM_PEER) 	||
		(smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
		smc->y[PB].pc_mode == PM_PEER) 	||
		(smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
		smc->y[PS].pc_mode == PM_PEER &&
		smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
			cond = TRUE ;
	}
	if (cond != smc->mib.fddiSMTPeerWrapFlag)
		smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;

#if	0
	/*
	 * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
	 * to the primary path.
	 */
	/*
	 * path change
	 */
	if (smc->mib.fddiSMTCF_State != oldstate) {
		smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ;
	}
#endif
#endif	/* no SLIM_SMT */

	/*
	 * set MAC port type
	 */
	smc->mib.m[MAC0].fddiMACDownstreamPORTType =
		cf_to_ptype[smc->mib.fddiSMTCF_State] ;
	cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
}
Exemplo n.º 6
0
void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)

{
	struct smt_header	*sm ;
	int			local ;

	int			illegal = 0 ;

	switch (m_fc(mb)) {
	case FC_SMT_INFO :
	case FC_SMT_LAN_LOC :
	case FC_SMT_LOC :
	case FC_SMT_NSA :
		break ;
	default :
		smt_free_mbuf(smc,mb) ;
		return ;
	}

	smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;
	sm = smtod(mb,struct smt_header *) ;
	local = ((fs & L_INDICATOR) != 0) ;
	hwm_conv_can(smc,(char *)sm,12) ;

	
	if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {
		smt_free_mbuf(smc,mb) ;
		return ;
	}
#if	0		
	
	if (is_my_addr(smc,&sm->smt_source) && !local) {
		smt_free_mbuf(smc,mb) ;
		return ;
	}
#endif

	smt_swap_para(sm,(int) mb->sm_len,1) ;
	DB_SMT("SMT : received packet [%s] at 0x%x\n",
		smt_type_name[m_fc(mb) & 0xf],sm) ;
	DB_SMT("SMT : version %d, class %s\n",sm->smt_version,
		smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;

#ifdef	SBA
	
	if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&
		(sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {
			smc->sba.sm = sm ;
			sba(smc,NIF) ;
	}
#endif

	
	if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {
		DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",
			addr_to_string(&sm->smt_source),0) ;
		smt_free_mbuf(smc,mb) ;
		return ;
	}

	
	if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||
	    ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {
		smt_free_mbuf(smc,mb) ;
		return ;
	}

	
	switch (sm->smt_class) {
	case SMT_NIF :
	case SMT_SIF_CONFIG :
	case SMT_SIF_OPER :
	case SMT_ECF :
		if (sm->smt_version != SMT_VID)
			illegal = 1;
		break ;
	default :
		if (sm->smt_version != SMT_VID_2)
			illegal = 1;
		break ;
	}
	if (illegal) {
		DB_SMT("SMT : version = %d, dest = %s\n",
			sm->smt_version,addr_to_string(&sm->smt_source)) ;
		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;
		smt_free_mbuf(smc,mb) ;
		return ;
	}
	if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||
	    ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {
		DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ;
		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;
		smt_free_mbuf(smc,mb) ;
		return ;
	}
	switch (sm->smt_class) {
	case SMT_NIF :
		if (smt_check_para(smc,sm,plist_nif)) {
			DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;
			break ;
		} ;
		switch (sm->smt_type) {
		case SMT_ANNOUNCE :
		case SMT_REQUEST :
			if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA
				&& is_broadcast(&sm->smt_dest)) {
				struct smt_p_state	*st ;

				
				if (!is_equal(
					&smc->mib.m[MAC0].fddiMACUpstreamNbr,
					&sm->smt_source)) {
					DB_SMT("SMT : updated my UNA = %s\n",
					addr_to_string(&sm->smt_source),0) ;
					if (!is_equal(&smc->mib.m[MAC0].
					    fddiMACUpstreamNbr,&SMT_Unknown)){
					 
					 smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
					 smc->mib.m[MAC0].fddiMACUpstreamNbr ;
					}

					smc->mib.m[MAC0].fddiMACUpstreamNbr =
						sm->smt_source ;
					smt_srf_event(smc,
						SMT_EVENT_MAC_NEIGHBOR_CHANGE,
						INDEX_MAC,0) ;
					smt_echo_test(smc,0) ;
				}
				smc->sm.smt_tvu = smt_get_time() ;
				st = (struct smt_p_state *)
					sm_to_para(smc,sm,SMT_P_STATE) ;
				if (st) {
					smc->mib.m[MAC0].fddiMACUNDA_Flag =
					(st->st_dupl_addr & SMT_ST_MY_DUPA) ?
					TRUE : FALSE ;
					update_dac(smc,1) ;
				}
			}
			if ((sm->smt_type == SMT_REQUEST) &&
			    is_individual(&sm->smt_source) &&
			    ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||
			     (m_fc(mb) != FC_SMT_NSA))) {
				DB_SMT("SMT : replying to NIF request %s\n",
					addr_to_string(&sm->smt_source),0) ;
				smt_send_nif(smc,&sm->smt_source,
					FC_SMT_INFO,
					sm->smt_tid,
					SMT_REPLY,local) ;
			}
			break ;
		case SMT_REPLY :
			DB_SMT("SMT : received NIF response from %s\n",
				addr_to_string(&sm->smt_source),0) ;
			if (fs & A_INDICATOR) {
				smc->sm.pend[SMT_TID_NIF] = 0 ;
				DB_SMT("SMT : duplicate address\n",0,0) ;
				smc->mib.m[MAC0].fddiMACDupAddressTest =
					DA_FAILED ;
				smc->r.dup_addr_test = DA_FAILED ;
				queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
				smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;
				update_dac(smc,1) ;
				break ;
			}
			if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {
				smc->sm.pend[SMT_TID_NIF] = 0 ;
				
				if (!is_equal(
					&smc->mib.m[MAC0].fddiMACDownstreamNbr,
					&sm->smt_source)) {
					DB_SMT("SMT : updated my DNA\n",0,0) ;
					if (!is_equal(&smc->mib.m[MAC0].
					 fddiMACDownstreamNbr, &SMT_Unknown)){
					 
				smc->mib.m[MAC0].fddiMACOldDownstreamNbr =
					 smc->mib.m[MAC0].fddiMACDownstreamNbr ;
					}

					smc->mib.m[MAC0].fddiMACDownstreamNbr =
						sm->smt_source ;
					smt_srf_event(smc,
						SMT_EVENT_MAC_NEIGHBOR_CHANGE,
						INDEX_MAC,0) ;
					smt_echo_test(smc,1) ;
				}
				smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;
				update_dac(smc,1) ;
				smc->sm.smt_tvd = smt_get_time() ;
				smc->mib.m[MAC0].fddiMACDupAddressTest =
					DA_PASSED ;
				if (smc->r.dup_addr_test != DA_PASSED) {
					smc->r.dup_addr_test = DA_PASSED ;
					queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
				}
			}
			else if (sm->smt_tid ==
				smc->sm.pend[SMT_TID_NIF_TEST]) {
				DB_SMT("SMT : NIF test TID ok\n",0,0) ;
			}
			else {
				DB_SMT("SMT : expected TID %lx, got %lx\n",
				smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ;
			}
			break ;
		default :
			illegal = 2 ;
			break ;
		}
		break ;
	case SMT_SIF_CONFIG :	
		if (sm->smt_type != SMT_REQUEST)
			break ;
		DB_SMT("SMT : replying to SIF Config request from %s\n",
			addr_to_string(&sm->smt_source),0) ;
		smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;
		break ;
	case SMT_SIF_OPER :	
		if (sm->smt_type != SMT_REQUEST)
			break ;
		DB_SMT("SMT : replying to SIF Operation request from %s\n",
			addr_to_string(&sm->smt_source),0) ;
		smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;
		break ;
	case SMT_ECF :		
		switch (sm->smt_type) {
		case SMT_REPLY :
			smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;
			DB_SMT("SMT: received ECF reply from %s\n",
				addr_to_string(&sm->smt_source),0) ;
			if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) {
				DB_SMT("SMT: ECHODATA missing\n",0,0) ;
				break ;
			}
			if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {
				DB_SMT("SMT : ECF test TID ok\n",0,0) ;
			}
			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {
				DB_SMT("SMT : ECF test UNA ok\n",0,0) ;
			}
			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {
				DB_SMT("SMT : ECF test DNA ok\n",0,0) ;
			}
			else {
				DB_SMT("SMT : expected TID %lx, got %lx\n",
					smc->sm.pend[SMT_TID_ECF],
					sm->smt_tid) ;
			}
			break ;
		case SMT_REQUEST :
			smc->mib.priv.fddiPRIVECF_Req_Rx++ ;
			{
			if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {
			DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;
				smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,
					local) ;
				break ;
			}
			DB_SMT("SMT - sending ECF reply to %s\n",
				addr_to_string(&sm->smt_source),0) ;

			
			sm->smt_dest = sm->smt_source ;
			sm->smt_type = SMT_REPLY ;
			dump_smt(smc,sm,"ECF REPLY") ;
			smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;
			smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
			return ;		
			}
		default :
			illegal = 1 ;
			break ;
		}
		break ;
#ifndef	BOOT
	case SMT_RAF :		
#ifdef	ESS
		DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;
		fs = ess_raf_received_pack(smc,mb,sm,fs) ;
#endif

#ifdef	SBA
		DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;
		sba_raf_received_pack(smc,sm,fs) ;
#endif
		break ;
	case SMT_RDF :		
		smc->mib.priv.fddiPRIVRDF_Rx++ ;
		break ;
	case SMT_ESF :		
		if (sm->smt_type == SMT_REQUEST) {
			DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;
			smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
		}
		break ;
	case SMT_PMF_GET :
	case SMT_PMF_SET :
		if (sm->smt_type != SMT_REQUEST)
			break ;
		
		if (sm->smt_class == SMT_PMF_GET)
			smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;
		else
			smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;
		
		if ((sm->smt_class == SMT_PMF_SET) &&
			!is_individual(&sm->smt_dest)) {
			DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;
			break ;
		}
		smt_pmf_received_pack(smc,mb, local) ;
		break ;
	case SMT_SRF :
		dump_smt(smc,sm,"SRF received") ;
		break ;
	default :
		if (sm->smt_type != SMT_REQUEST)
			break ;
		
		DB_SMT("SMT : class = %d, send RDF to %s\n",
			sm->smt_class, addr_to_string(&sm->smt_source)) ;

		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
		break ;
#endif
	}
	if (illegal) {
		DB_SMT("SMT: discarding invalid frame, reason = %d\n",
			illegal,0) ;
	}
	smt_free_mbuf(smc,mb) ;
}
Exemplo n.º 7
0
void smt_event(struct s_smc *smc, int event)
{
	u_long		time ;
#ifndef SMT_REAL_TOKEN_CT
	int		i ;
#endif


	if (smc->sm.please_reconnect) {
		smc->sm.please_reconnect -- ;
		if (smc->sm.please_reconnect == 0) {
			
			queue_event(smc,EVENT_ECM,EC_CONNECT) ;
		}
	}

	if (event == SM_FAST)
		return ;

	
	smt_timer_poll(smc) ;
	smt_start_watchdog(smc) ;
#ifndef	SLIM_SMT
#ifndef BOOT
#ifdef	ESS
	ess_timer_poll(smc) ;
#endif
#endif
#ifdef	SBA
	sba_timer_poll(smc) ;
#endif

	smt_srf_event(smc,0,0,0) ;

#endif	

	time = smt_get_time() ;

	if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
		
		struct fddi_mib_m	*mib ;
		u_long			upper ;
		u_long			lower ;
		int			cond ;
		int			port;
		struct s_phy		*phy ;
		
		sm_lem_evaluate(smc) ;
		smc->sm.smt_last_lem = time ;

		
#ifndef	SLIM_SMT
		mac_update_counter(smc) ;
		mib = smc->mib.m ;
		upper =
		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
		(mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
		lower =
		(mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
		mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;

		cond =
			((!mib->fddiMACFrameErrorThreshold &&
			mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
			(mib->fddiMACFrameErrorRatio >
			mib->fddiMACFrameErrorThreshold)) ;

		if (cond != mib->fddiMACFrameErrorFlag)
			smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
				INDEX_MAC,cond) ;

		upper =
		(mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
		lower =
		upper +
		(mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
		mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;

		cond =
			((!mib->fddiMACNotCopiedThreshold &&
			mib->fddiMACNotCopied_Ct !=
				mib->fddiMACOld_NotCopied_Ct)||
			(mib->fddiMACNotCopiedRatio >
			mib->fddiMACNotCopiedThreshold)) ;

		if (cond != mib->fddiMACNotCopiedFlag)
			smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
				INDEX_MAC,cond) ;

		
		mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
		mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
		mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
		mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
		mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;

		
		for (port = 0; port < NUMPHYS; port ++) {
			phy = &smc->y[port] ;

			if (!phy->mib->fddiPORTHardwarePresent) {
				continue;
			}

			cond = (phy->mib->fddiPORTEBError_Ct -
				phy->mib->fddiPORTOldEBError_Ct > 5) ;

			
			smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
				(int) (INDEX_PORT+ phy->np) ,cond) ;

			
			phy->mib->fddiPORTOldEBError_Ct =
				phy->mib->fddiPORTEBError_Ct ;
		}

#endif	
	}

#ifndef	SLIM_SMT

	if (time - smc->sm.smt_last_notify >= (u_long)
		(smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
		
		if (!smc->sm.pend[SMT_TID_NIF])
			smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
		smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
			smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
		smc->sm.smt_last_notify = time ;
	}

	
	if (smc->sm.smt_tvu &&
	    time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
		DB_SMT("SMT : UNA expired\n",0,0) ;
		smc->sm.smt_tvu = 0 ;

		if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
			&SMT_Unknown)){
			
			smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
				smc->mib.m[MAC0].fddiMACUpstreamNbr ;
		}
		smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
		smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
		
		update_dac(smc,0) ;
		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
			INDEX_MAC,0) ;
	}
	if (smc->sm.smt_tvd &&
	    time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
		DB_SMT("SMT : DNA expired\n",0,0) ;
		smc->sm.smt_tvd = 0 ;
		if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
			&SMT_Unknown)){
			
			smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
				smc->mib.m[MAC0].fddiMACDownstreamNbr ;
		}
		smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
			INDEX_MAC,0) ;
	}

#endif	

#ifndef SMT_REAL_TOKEN_CT
	
	for (i = MAC0; i < NUMMACS; i++ ){
		if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
			smt_emulate_token_ct( smc, i );
		}
	}
#endif

	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
}
Exemplo n.º 8
0
/*ARGSUSED1*/
void smt_event(struct s_smc *smc, int event)
{
	u_long		time ;
#ifndef SMT_REAL_TOKEN_CT
	int		i ;
#endif


	if (smc->sm.please_reconnect) {
		smc->sm.please_reconnect -- ;
		if (smc->sm.please_reconnect == 0) {
			/* Counted down */
			queue_event(smc,EVENT_ECM,EC_CONNECT) ;
		}
	}

	if (event == SM_FAST)
		return ;

	/*
	 * timer for periodic cleanup in driver
	 * reset and start the watchdog (FM2)
	 * ESS timer
	 * SBA timer
	 */
	smt_timer_poll(smc) ;
	smt_start_watchdog(smc) ;
#ifndef	SLIM_SMT
#ifndef BOOT
#ifdef	ESS
	ess_timer_poll(smc) ;
#endif
#endif
#ifdef	SBA
	sba_timer_poll(smc) ;
#endif

	smt_srf_event(smc,0,0,0) ;

#endif	/* no SLIM_SMT */

	time = smt_get_time() ;

	if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
		/*
		 * Use 8 sec. for the time intervall, it simplifies the
		 * LER estimation.
		 */
		struct fddi_mib_m	*mib ;
		u_long			upper ;
		u_long			lower ;
		int			cond ;
		int			port;
		struct s_phy		*phy ;
		/*
		 * calculate LEM bit error rate
		 */
		sm_lem_evaluate(smc) ;
		smc->sm.smt_last_lem = time ;

		/*
		 * check conditions
		 */
#ifndef	SLIM_SMT
		mac_update_counter(smc) ;
		mib = smc->mib.m ;
		upper =
		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
		(mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
		lower =
		(mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
		mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;

		cond =
			((!mib->fddiMACFrameErrorThreshold &&
			mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
			(mib->fddiMACFrameErrorRatio >
			mib->fddiMACFrameErrorThreshold)) ;

		if (cond != mib->fddiMACFrameErrorFlag)
			smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
				INDEX_MAC,cond) ;

		upper =
		(mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
		lower =
		upper +
		(mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
		mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;

		cond =
			((!mib->fddiMACNotCopiedThreshold &&
			mib->fddiMACNotCopied_Ct !=
				mib->fddiMACOld_NotCopied_Ct)||
			(mib->fddiMACNotCopiedRatio >
			mib->fddiMACNotCopiedThreshold)) ;

		if (cond != mib->fddiMACNotCopiedFlag)
			smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
				INDEX_MAC,cond) ;

		/*
		 * set old values
		 */
		mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
		mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
		mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
		mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
		mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;

		/*
		 * Check port EBError Condition
		 */
		for (port = 0; port < NUMPHYS; port ++) {
			phy = &smc->y[port] ;

			if (!phy->mib->fddiPORTHardwarePresent) {
				continue;
			}

			cond = (phy->mib->fddiPORTEBError_Ct -
				phy->mib->fddiPORTOldEBError_Ct > 5) ;

			/* If ratio is more than 5 in 8 seconds
			 * Set the condition.
			 */
			smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
				(int) (INDEX_PORT+ phy->np) ,cond) ;

			/*
			 * set old values
			 */
			phy->mib->fddiPORTOldEBError_Ct =
				phy->mib->fddiPORTEBError_Ct ;
		}

#endif	/* no SLIM_SMT */
	}

#ifndef	SLIM_SMT

	if (time - smc->sm.smt_last_notify >= (u_long)
		(smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
		/*
		 * we can either send an announcement or a request
		 * a request will trigger a reply so that we can update
		 * our dna
		 * note: same tid must be used until reply is received
		 */
		if (!smc->sm.pend[SMT_TID_NIF])
			smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
		smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
			smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
		smc->sm.smt_last_notify = time ;
	}

	/*
	 * check timer
	 */
	if (smc->sm.smt_tvu &&
	    time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
		DB_SMT("SMT : UNA expired\n",0,0) ;
		smc->sm.smt_tvu = 0 ;

		if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
			&SMT_Unknown)){
			/* Do not update unknown address */
			smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
				smc->mib.m[MAC0].fddiMACUpstreamNbr ;
		}
		smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
		smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
		/*
		 * Make sure the fddiMACUNDA_Flag = FALSE is
		 * included in the SRF so we don't generate
		 * a separate SRF for the deassertion of this
		 * condition
		 */
		update_dac(smc,0) ;
		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
			INDEX_MAC,0) ;
	}
	if (smc->sm.smt_tvd &&
	    time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
		DB_SMT("SMT : DNA expired\n",0,0) ;
		smc->sm.smt_tvd = 0 ;
		if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
			&SMT_Unknown)){
			/* Do not update unknown address */
			smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
				smc->mib.m[MAC0].fddiMACDownstreamNbr ;
		}
		smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
			INDEX_MAC,0) ;
	}

#endif	/* no SLIM_SMT */

#ifndef SMT_REAL_TOKEN_CT
	/*
	 * Token counter emulation section. If hardware supports the token
	 * count, the token counter will be updated in mac_update_counter.
	 */
	for (i = MAC0; i < NUMMACS; i++ ){
		if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
			smt_emulate_token_ct( smc, i );
		}
	}
#endif

	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
}