dot3ah.c

来自「在freescale 的ne64上开发的源代码」· C语言 代码 · 共 1,260 行 · 第 1/3 页

C
1,260
字号
#include <string.h>
#include <stdio.h>
#include <stdlib.h> /*atoi*/
#include "System.h"
#include "debug.h"
#include "ethernet.h"
#include "dot3ah.h"
#include "timers.h"
#include "mBuf.h"
#include "ne64debug.h" 

/*variables need other place support*/
extern UINT8 localNoamPortLnkStat;   /*1-link up*/
extern UINT8 localOamPortLnkFault;   /*1-link fault*/
extern UINT8 localDTEType;           /*local device type*/
extern MBUF* pCurrentMBuf;
extern UINT8 localHWVersion;         /*local hardware version*/
extern UINT8 locPwrUpFlag;

#if 0 
extern UINT8 remoteFXLink;           /*1-link up*/
extern UINT8 remoteHWVer;            /*remote hardware version*/
extern UINT8 remoteSWVer;            /*remote software version*/
extern UINT8 localSWVersion;         /*local software version*/
#else
UINT8 remoteFXLink;                  /*1-link up*/
UINT8 remoteHWVer;                   /*remote hardware version*/
UINT8 remoteSWVer;                   /*remote software version*/
UINT8 localSWVersion=2;              /*local software version*/
#endif
UINT8 localOAMEnable;                /*remote control enable 1-enable, 0-disable*/
UINT8 localOAMMode;                  /*1-active, 0-passive*/
UINT8 localOAMPort;                  /*8-FX or FX2 port, 10-TP or FX1 port*/
UINT8 localPdu;
UINT8 localSatisfied;
UINT8 localStable;
UINT8 localUnidirectional;
UINT8 remoteStable;
UINT8 remoteStateValid;
UINT8 oamDiscoveryState;
UINT8 oamPduCnt;
UINT8 otherSlowProtocolDetected;
UINT8 oamPduCntDefault;
UINT8 dot3ahOAMInited = 0;
UINT8 oamPacketFirst;
UINT8 remoteTPLink;                 /*1-link up*/
UINT8 remotePwrUpFlg;
UINT8 remoteDTEExist;               /*remote device exist flag, 1-exist*/
UINT8 pduTimer;                     /*second decreace*/
UINT8 locLstLnkTimer;               /*second decreace*/
UINT32 pduTmrPrd;
UINT32 locLstLnkTmrPrd;
UINT8 remoteDTEType;          

UINT16 dot3ahTxInfoPkts;
UINT16 dot3ahTxSpecPkts;
UINT16 dot3ahRxPkts;
UINT16 dot3ahRxSlowPkts;
UINT16 dot3ahRxInfoPkts;
UINT16 dot3ahRxSpecPkts;

UNION_OAM_FLAG_FIELD localOAMFlagField;
UNION_OAM_FLAG_FIELD rmtOAMFlagField;

const UINT8 dot3ah_addr[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02};
UINT8 rmtDTEAddr[6];

UINT8 localInfoTLV[16];
UINT8 remoteInfoTLV[16];
tINFO_TLV *tLocalInfoTLV = (tINFO_TLV *)localInfoTLV;
tINFO_TLV *tRemoteInfoTLV = (tINFO_TLV *)remoteInfoTLV;

extern void hwLfpRecover(void);

/*
 * Function:
 *   dot3ah_init()
 * Purpose:
 *   Init the dot3ah used variables.
 * Parameters:
 *   oamMode -- DTE_OAM_ACTIVE or DTE_OAM_PASSIVE
 *   oamPort -- The tx or rx OAM packet port, 10 or 8
 * Returns:
 *   None.
 */
void dot3ah_init(void)
{
	if(dot3ahOAMInited)
		return;

	/*init variables*/
	localOAMEnable = 1;
	localOAMMode = DTE_OAM_PASSIVE;	
	localPdu = LOCAL_PDU_LF_INFO;
	localSatisfied = 0;
	localStable = 0;
	localUnidirectional = 0;
	remoteDTEExist = 0;
	remoteStable = 0;
	remoteStateValid = 0;
	oamDiscoveryState = DISC_FAULT;	
	otherSlowProtocolDetected = 0;
	oamPacketFirst = 1;
	remoteDTEType = DTE_TYPE_UNKNOWN;
	
	pduTmrPrd = PDU_TIME;
	locLstLnkTmrPrd = LOCAL_LOST_LINK_TIME;
	oamPduCntDefault = OAMPDU_COUNT_PER_SECOND;
	oamPduCnt = oamPduCntDefault;

	dot3ahTxInfoPkts = 0;
	dot3ahTxSpecPkts = 0;
	dot3ahRxPkts = 0;
	dot3ahRxSlowPkts = 0;
	dot3ahRxInfoPkts = 0;
	dot3ahRxSpecPkts = 0;
	
	/*init flag field*/
	localOAMFlagField.flagFieldVal = 0;
	localOAMFlagField.Bits.criticEvent = 0;
	localOAMFlagField.Bits.dyingGasp = 0;
	localOAMFlagField.Bits.linkFault = 0;

	/*init local information TLV*/
	tLocalInfoTLV->infoType = TLV_INFO_TYPE_LOCAL;
	tLocalInfoTLV->infoLen = TLV_INFO_LEN;
	tLocalInfoTLV->oamVersion = OAM_VERSION;
	tLocalInfoTLV->infoRevision = 0;
	tLocalInfoTLV->infoState.infoTlvStateVal = 0;
	tLocalInfoTLV->infoState.Bits.parAction = PAR_ACTION_FWD;
	tLocalInfoTLV->infoState.Bits.muxAction = MUX_ACTION_FWD;
	tLocalInfoTLV->oamConfig.infoTlvOamCfgVal = 0;
	tLocalInfoTLV->oamConfig.Bits.oamMode = localOAMMode;
	tLocalInfoTLV->oamConfig.Bits.unidirectSupport = 0;
	tLocalInfoTLV->oamConfig.Bits.loopSupport = 0;
	tLocalInfoTLV->oamConfig.Bits.linkEvents = 1;
	tLocalInfoTLV->oamConfig.Bits.varRetrieval = 0;
	tLocalInfoTLV->oampduConfig.infoTlvOamPduCfgVal = OAMPDU_MAX_SIZE;
	tLocalInfoTLV->ouiHigh = OAMPDU_OUI_MSB;
	tLocalInfoTLV->ouiLow = OAMPDU_OUI_LSB;
	tLocalInfoTLV->vendorInfoCode = OAM_SPEC_CODE; /*fixed vendor info code*/
	tLocalInfoTLV->vendorDTEType = localDTEType;
	tLocalInfoTLV->hwVerTpLink.hwVerTpLinkVal= 0;
	tLocalInfoTLV->hwVerTpLink.Bits.TpLinkStatus = localNoamPortLnkStat;
	tLocalInfoTLV->hwVerTpLink.Bits.firstPwrUpFlg = locPwrUpFlag;
	tLocalInfoTLV->hwVerTpLink.Bits.vendorHWVer = localHWVersion;
	tLocalInfoTLV->vendorSWVer = localSWVersion;

	tRemoteInfoTLV->infoType = TLV_INFO_TYPE_REMOTE;

	/*Set slow protocol destination MAC, ports=10 and 8*/
	dot3ahOAMMacAddrSet((0x1<<9)|(0x1<<localOAMPort)); 
	
	/*init timer*/
	pduTimer = get_timer();
	init_timer(pduTimer, pduTmrPrd*TIMERTIC);
	locLstLnkTimer = get_timer();	
	init_timer(locLstLnkTimer, locLstLnkTmrPrd*TIMERTIC);
	
	dot3ahOAMInited = 1;
}

/*
 * Function:
 *   dot3ah_discovery()
 * Purpose:
 *   Excute the dot3ah discovery state exchange.
 * Parameters:
 *   None.
 * Returns:
 *   None.
 * Notes:
 *   This function shouled be call at the main loop.
 */
void dot3ah_discovery(void)
{
	if(dot3ahOAMInited == 0)
		return;

	if(check_timer(locLstLnkTimer) == 0)
	{
		init_timer(locLstLnkTimer, locLstLnkTmrPrd*TIMERTIC);
		localSatisfied = 0;
		localStable = 0;	
		remoteStable = 0;
		remoteStateValid = 0;
		oamDiscoveryState = DISC_FAULT;		
	}

	if(localOAMEnable == OAM_DISABLE)
	{
		oamPacketFirst = 1;
		pduTmrPrd = PDU_TIME;
		locLstLnkTmrPrd = LOCAL_LOST_LINK_TIME;
		oamPduCntDefault = OAMPDU_COUNT_PER_SECOND;
		localSatisfied = 0;
		localStable = 0;	
		remoteStable = 0;
		remoteStateValid = 0;
		oamDiscoveryState = DISC_FAULT;
		remoteDTEExist = 0;
		return;
	}

	if(localOamPortLnkFault == 1)
	{
		localSatisfied = 0;
		localStable = 0;	
		remoteStable = 0;
		remoteStateValid = 0;
		oamDiscoveryState = DISC_FAULT;
	}
	
	switch(oamDiscoveryState)
	{
		case DISC_FAULT:
			if(localOamPortLnkFault == 1)
			{
				localPdu = LOCAL_PDU_LF_INFO;
			}
			else
			{
				if(localOAMMode == DTE_OAM_ACTIVE)
				{
					oamDiscoveryState = DISC_ACTIVE_SEND_LOCAL;		
					localPdu = LOCAL_PDU_INFO;
				}
				else
				{
					oamDiscoveryState = DISC_PASSIVE_WAIT;
					localPdu = LOCAL_PDU_RX_INFO;
				}
			}
			localStable = 0;
			localOAMFlagField.Bits.localStableEval = DISCOVERY_NOT_COMPLETED;
			break;
			
		case DISC_PASSIVE_WAIT:
			if(remoteStateValid == 1)
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 0;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_NOT_COMPLETED;
			}			
			break;
			
		case DISC_ACTIVE_SEND_LOCAL:
			if(remoteStateValid == 1)
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 0;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_NOT_COMPLETED;
			}
			break;
			
		case DISC_SEND_LOCAL_RMT:
			if(localSatisfied == 1)
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT_OK;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 1;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_COMPLETED;
			}
			break;
			
		case DISC_SEND_LOCAL_RMT_OK:
			if((localSatisfied==1) && (remoteStable==1))
			{
				oamDiscoveryState = DISC_SEND_ANY;
				localPdu = LOCAL_PDU_ANY;			
			}
			if(localSatisfied == 0)
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 0;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_NOT_COMPLETED;
			}
			break;
			
		case DISC_SEND_ANY:
			if((localSatisfied==1) && (remoteStable==0))
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT_OK;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 1;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_COMPLETED;
			}
			if(localSatisfied == 0)
			{
				oamDiscoveryState = DISC_SEND_LOCAL_RMT;
				localPdu = LOCAL_PDU_INFO;	
				localStable = 0;
				localOAMFlagField.Bits.localStableEval = DISCOVERY_NOT_COMPLETED;
			}
			break;
		default:
			break;
	}

	if(oamDiscoveryState == DISC_SEND_ANY)
	{
		if(remoteDTEExist == 0)
		{
			if((tRemoteInfoTLV->ouiHigh==OAMPDU_OUI_MSB) && (tRemoteInfoTLV->ouiLow==OAMPDU_OUI_LSB))
			{
			#if 0
				pduTmrPrd = MAX_PDU_TIME;
				locLstLnkTmrPrd = MAX_LOCAL_LOST_LINK_TIME;
				oamPduCntDefault = MAX_OAMPDU_COUNT_PER_SECOND;
			#endif
			}
			DOT3AH_DEBUGOUT("Remote device discovered\n\r");
		}		
		remoteDTEExist = 1;
	}
	else
	{	
		if(remoteDTEExist == 1)
		{
			oamPacketFirst = 1;
			pduTmrPrd = PDU_TIME;
			locLstLnkTmrPrd = LOCAL_LOST_LINK_TIME;
			oamPduCntDefault = OAMPDU_COUNT_PER_SECOND;

			//DOT3AH_DEBUGOUT("Remote device lost\n\r");
		}		
		remoteDTEExist = 0;
	}
}

/*
 * Function:
 *   dot3ah_send_info()
 * Purpose:
 *   Excute the dot3ah discovery state exchange.
 * Parameters:
 *   None.
 * Returns:
 *   None.
 * Notes:
 *   This function shouled be call at the main loop.
 */
void dot3ah_send_info(void)
{
	UINT8 i;

	if((dot3ahOAMInited==0) ||(localOAMEnable==OAM_DISABLE))
		return;

	if(check_timer(pduTimer) != 0)
		return;

	/*check if the OAM sublayer RX_INFO only*/
	if(localPdu == LOCAL_PDU_RX_INFO)
	{	
		init_timer(pduTimer, pduTmrPrd*TIMERTIC);
		oamPduCnt = oamPduCntDefault;
		return;
	}

	/*check if the OAM sublayer is LF_INFO and don't support unidirection*/
	if((localUnidirectional==0) && (localPdu==LOCAL_PDU_LF_INFO))
	{
		init_timer(pduTimer, pduTmrPrd*TIMERTIC);
		oamPduCnt = oamPduCntDefault;
		return;
	}
	
	/*check if had sent an OAMPDU in one second,if true, return*/
	if(oamPduCnt == 0)
	{
		init_timer(pduTimer, pduTmrPrd*TIMERTIC);
		oamPduCnt = oamPduCntDefault;
		return;
	}

	oamPduCnt = oamPduCntDefault;

	NETWORK_SEND_INITIALIZE(OAM_BUFFER);
	
	/*Add Ethernet addresses information*/	
	for( i=0; i<6; i++)	
	{
		send_frame.destination[i] = dot3ah_addr[i];
		send_frame.source[i] = localmachine.localHW[i];
	}
	
	send_frame.protocol = PROTOCOL_SLOW;

	/*Add egress port information*/	
	send_frame.sendFrameType = PORT_DIRECT_FRAME;
#if 0
	if(localOAMMode == DTE_OAM_ACTIVE)
		send_frame.port = localOAMPort;        /*the port 8 is fixed fiber port*/
	else
		send_frame.port = received_frame.port; /*In passive mode*/
#else
	send_frame.port = localOAMPort;
#endif
	#pragma MESSAGE DISABLE C1825		/*Warning: indirection*/
	NETWORK_ADD_DATALINK(&send_frame);
	#pragma MESSAGE DEFAULT C1825		/*Warning: indirection*/       
	
	/*Put OAMPDU Data*/
	SEND_NETWORK_B(SLOW_SUBTYPE_OAM);             /*802.3ah OAM subType*/
	localOAMFlagField.Bits.linkFault = localOamPortLnkFault;
	SEND_NETWORK_W(localOAMFlagField.flagFieldVal); /*802.3ah OAM flag field*/
	SEND_NETWORK_B(OAM_CODE_INFO);                /*802.3ah OAM code field*/

	/*If the OAM sublayer if at LF_INFO state, with on info TLVs*/
	if(localPdu == LOCAL_PDU_LF_INFO)
	{
		SEND_NETWORK_B(TLV_INFO_TYPE_END);
		NETWORK_COMPLETE_SEND(0x0040);		  /*Send the packet*/	
		init_timer(pduTimer, pduTmrPrd*TIMERTIC);
		dot3ahTxInfoPkts++;
		return;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?