📄 smt.c
字号:
/****************************************************************************** * * (C)Copyright 1998,1999 SysKonnect, * a business unit of Schneider & Koch & Co. Datensysteme GmbH. * * See the file "skfddi.c" for further information. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/#include "h/types.h"#include "h/fddi.h"#include "h/smc.h"#include "h/smt_p.h"#define KERNEL#include "h/smtstate.h"#ifndef lintstatic const char ID_sccs[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ;#endifextern const u_char canonical[256] ;/* * FC in SMbuf */#define m_fc(mb) ((mb)->sm_data[0])#define SMT_TID_MAGIC 0x1f0a7b3c#ifdef DEBUGstatic const char *const smt_type_name[] = { "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??", "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??", "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??", "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"} ;static const char *const smt_class_name[] = { "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF", "SRF","PMF_GET","PMF_SET","ESF"} ;#endif#define LAST_CLASS (SMT_PMF_SET)static const struct fddi_addr SMT_Unknown = { { 0,0,0x1f,0,0,0 }} ;/* * external variables */extern const struct fddi_addr fddi_broadcast ;/* * external functions */int pcm_status_twisted(struct s_smc *smc);/* * function prototypes */#ifdef LITTLE_ENDIANstatic int smt_swap_short(u_short s);#endifstatic int mac_index(struct s_smc *smc, int mac);static int phy_index(struct s_smc *smc, int phy);static int mac_con_resource_index(struct s_smc *smc, int mac);static int phy_con_resource_index(struct s_smc *smc, int phy);static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, int local);static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, int fc, u_long tid, int type, int local);static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, u_long tid, int type, int len);static void smt_echo_test(struct s_smc *smc, int dna);static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, u_long tid, int local);static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, u_long tid, int local);#ifdef LITTLE_ENDIANstatic void smt_string_swap(void);#endifstatic void smt_add_frame_len(SMbuf *mb, int len);static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);static void smt_fill_manufacturer(struct s_smc *smc, struct smp_p_manufacturer *man);static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, int len);void smt_clear_una_dna(struct s_smc *smc);static void smt_clear_old_una_dna(struct s_smc *smc);#ifdef CONCENTRATORstatic int entity_to_index(void);#endifstatic void update_dac(struct s_smc *smc, int report);static int div_ratio(u_long upper, u_long lower);#ifdef USE_CAN_ADDRvoid hwm_conv_can(struct s_smc *smc, char *data, int len);#else#define hwm_conv_can(smc,data,len)#endifstatic inline int is_my_addr(const struct s_smc *smc, const struct fddi_addr *addr){ return(*(short *)(&addr->a[0]) == *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) && *(short *)(&addr->a[2]) == *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2]) && *(short *)(&addr->a[4]) == *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;}static inline int is_broadcast(const struct fddi_addr *addr){ return(*(u_short *)(&addr->a[0]) == 0xffff && *(u_short *)(&addr->a[2]) == 0xffff && *(u_short *)(&addr->a[4]) == 0xffff ) ;}static inline int is_individual(const struct fddi_addr *addr){ return(!(addr->a[0] & GROUP_ADDR)) ;}static inline int is_equal(const struct fddi_addr *addr1, const struct fddi_addr *addr2){ return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;}/* * list of mandatory paras in frames */static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;/* * init SMT agent */void smt_agent_init(struct s_smc *smc){ int i ; /* * get MAC address */ smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ; /* * get OUI address from driver (bia == built-in-address) */ smc->mib.fddiSMTStationId.sid_oem[0] = 0 ; smc->mib.fddiSMTStationId.sid_oem[1] = 0 ; driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ; for (i = 0 ; i < 6 ; i ++) { smc->mib.fddiSMTStationId.sid_node.a[i] = canonical[smc->mib.fddiSMTStationId.sid_node.a[i]] ; } smc->mib.fddiSMTManufacturerData[0] = smc->mib.fddiSMTStationId.sid_node.a[0] ; smc->mib.fddiSMTManufacturerData[1] = smc->mib.fddiSMTStationId.sid_node.a[1] ; smc->mib.fddiSMTManufacturerData[2] = smc->mib.fddiSMTStationId.sid_node.a[2] ; smc->sm.smt_tid = 0 ; smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ; smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;#ifndef SLIM_SMT smt_clear_una_dna(smc) ; smt_clear_old_una_dna(smc) ;#endif for (i = 0 ; i < SMT_MAX_TEST ; i++) smc->sm.pend[i] = 0 ; smc->sm.please_reconnect = 0 ; smc->sm.uniq_ticks = 0 ;}/* * SMT task * forever * delay 30 seconds * send NIF * check tvu & tvd * end */void smt_agent_task(struct s_smc *smc){ smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, EV_TOKEN(EVENT_SMT,SM_TIMER)) ; DB_SMT("SMT agent task\n",0,0) ;}void smt_please_reconnect(struct s_smc *smc, int reconn_time)/* struct s_smc *smc; Pointer to SMT context *//* int reconn_time; Wait for reconnect time in seconds */{ /* * The please reconnect variable is used as a timer. * It is decremented each time smt_event is called. * This happens every second or when smt_force_irq is called. * Note: smt_force_irq () is called on some packet receives and * when a multicast address is changed. Since nothing * is received during the disconnect and the multicast * address changes can be viewed as not very often and * the timer runs out close to its given value * (reconn_time). */ smc->sm.please_reconnect = reconn_time ;}#ifndef SMT_REAL_TOKEN_CTvoid smt_emulate_token_ct(struct s_smc *smc, int mac_index){ u_long count; u_long time; time = smt_get_time(); count = ((time - smc->sm.last_tok_time[mac_index]) * 100)/TICKS_PER_SECOND; /* * Only when ring is up we will have a token count. The * flag is unfortunatly a single instance value. This * doesn't matter now, because we currently have only * one MAC instance. */ if (smc->hw.mac_ring_is_up){ smc->mib.m[mac_index].fddiMACToken_Ct += count; } /* Remember current time */ smc->sm.last_tok_time[mac_index] = time;}#endif/*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)) ;}static int div_ratio(u_long upper, u_long lower){ if ((upper<<16L) < upper) upper = 0xffff0000L ; else upper <<= 16L ; if (!lower) return(0) ; return((int)(upper/lower)) ;}#ifndef SLIM_SMT/* * receive packet handler */void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)/* int fs; frame status */{ 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) ; /* check destination address */ if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) { smt_free_mbuf(smc,mb) ; return ; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -