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 ; }
/* 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) ; }
/* * 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] ) ; }
/* * 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 */ } }
/* 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) ; }
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) ; }
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)) ; }
/*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)) ; }