dot3ah.c

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

C
1,260
字号
	}

	/*put the local info TLV data*/
	tLocalInfoTLV->hwVerTpLink.Bits.TpLinkStatus = localNoamPortLnkStat;
	tLocalInfoTLV->hwVerTpLink.Bits.firstPwrUpFlg = locPwrUpFlag;
	SEND_NETWORK_BUF(localInfoTLV,TLV_INFO_LEN);

	tLocalInfoTLV->infoRevision++;
	
	/*if discovery state is ACTIVE_SEND_LOCAL, send local info TLV only*/
	if(oamDiscoveryState == DISC_ACTIVE_SEND_LOCAL)
	{
		SEND_NETWORK_B(TLV_INFO_TYPE_END);
		NETWORK_COMPLETE_SEND(0x0040);		  /*Send the packet*/	
		init_timer(pduTimer, pduTmrPrd*TIMERTIC);
		DOT3AH_DEBUGOUT("Send DISC_ACTIVE_SEND_LOCAL\n\r");
		dot3ahTxInfoPkts++;
		return;
	}

	/*put the remote info TLV data*/	
	SEND_NETWORK_BUF(remoteInfoTLV,TLV_INFO_LEN);

	/*put the specific info TLV data or end info*/
	SEND_NETWORK_B(TLV_INFO_TYPE_END);
	
	/*Send the packet*/
	NETWORK_COMPLETE_SEND(46);

	//DOT3AH_DEBUGOUT("Send DISC_ACTIVE_SEND_RMT\n\r");
	dot3ahTxInfoPkts++;
	init_timer(pduTimer, pduTmrPrd*TIMERTIC);
}

/*
 * Function:
 *   dot3ah_send_spec()
 * Purpose:
 *   Send organization specific OAM.
 * Parameters:
 *   buf -- organization specific TLVs data pointer
 *   len -- the data length
 * Returns:
 *   OK or ERROR.
 * Notes:
 *   None.
 */
STATUS dot3ah_send_spec(void *buf, UINT16 len)
{	
	UINT8 i;

	if((oamDiscoveryState!=DISC_SEND_ANY)&&(oamDiscoveryState!=DISC_SEND_LOCAL_RMT_OK))
		return ERROR;

	if(remoteDTEType == DTE_TYPE_UNKNOWN)
		return ERROR;

	if(oamPduCnt == 0) /*had sent 10 OAMPDUs in a second*/
		return ERROR;

	oamPduCnt -= 1;

	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;

	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*/
	SEND_NETWORK_W(rmtOAMFlagField.flagFieldVal); /*802.3ah OAM flag field*/
	SEND_NETWORK_B(OAM_CODE_ORG_SPEC);            /*802.3ah OAM code field*/

	/*put the OUI*/
	SEND_NETWORK_B(OAMPDU_OUI_MSB);
	SEND_NETWORK_W(OAMPDU_OUI_LSB);

	/*put the OAM specific code*/
	SEND_NETWORK_B(OAM_SPEC_CODE);
	
	/*put the specific info TLV data*/
	SEND_NETWORK_BUF((UINT8 *)buf, len);	
	
	/*put the specific end info*/
	SEND_NETWORK_B(SPEC_TYPE_END);
	
	/*Send the packet*/
	NETWORK_COMPLETE_SEND(len+9); /*9 bytes=subType+flag+code+OUI+specCode+specEnd*/

	DOT3AH_DEBUGOUT("Send spec: ");
	for(i=0;i<len;i++)
	{
		DOT3AH_DEBUGOUT("%02x ",*((UINT8 *)buf+i));
	}
	DOT3AH_DEBUGOUT("\n\r");
	dot3ahTxSpecPkts++;
	return OK;
}

/*
 * Function:
 *   process_info_oampdu()
 * Purpose:
 *   Process the information OAMPDU.
 * Parameters:
 *   None.
 * Returns:
 *   None.
 * Notes:
 *   None.
 */
void process_info_oampdu(void)
{
	UINT8  tempByte;

	dot3ahRxInfoPkts++;
	
	/*get the local info type*/
	tempByte = RECEIVE_NETWORK_B();

	if(tempByte == TLV_INFO_TYPE_END)
	{		
		return;
	}

	/*get int remote DTE local info TLV*/
	if(tempByte != TLV_INFO_TYPE_LOCAL)
	{
		return; /*it's an invalid info OAMPDU*/
	}
	else
	{	
		/*check the info OAMPDU length field*/
		tempByte = RECEIVE_NETWORK_B();
		if(tempByte != TLV_INFO_LEN)
		{
			return; /*length is inlvalid*/
		}
		tRemoteInfoTLV->infoLen = tempByte;
		
		/*get the OAM Version field*/
		tRemoteInfoTLV->oamVersion = RECEIVE_NETWORK_B();

		/*get the info OAMPDU Revision field*/
		tRemoteInfoTLV->infoRevision = RECEIVE_NETWORK_W();

		/*get the info OAMPDU state field*/
		tRemoteInfoTLV->infoState.infoTlvStateVal = RECEIVE_NETWORK_B();

		/*get the info OAM configration field*/
		tRemoteInfoTLV->oamConfig.infoTlvOamCfgVal = RECEIVE_NETWORK_B();

		/*get the info OAMPDU configration field*/
		tRemoteInfoTLV->oampduConfig.infoTlvOamPduCfgVal = RECEIVE_NETWORK_W();

		/*get the info OAMPDU OUI field*/
		tRemoteInfoTLV->ouiHigh = RECEIVE_NETWORK_B();
		tRemoteInfoTLV->ouiLow = RECEIVE_NETWORK_W();
		
		/*get the info OAMPDU vendor specific field*/
		tRemoteInfoTLV->vendorInfoCode = RECEIVE_NETWORK_B();		
		tRemoteInfoTLV->vendorDTEType = RECEIVE_NETWORK_B();
		tRemoteInfoTLV->hwVerTpLink.hwVerTpLinkVal = RECEIVE_NETWORK_B();
		tRemoteInfoTLV->vendorSWVer = RECEIVE_NETWORK_B();

		/*analyze the remote DTE state and config, set corresponding variable*/
		remoteStateValid = 1;
		if((tLocalInfoTLV->oamConfig.infoTlvOamCfgVal & tRemoteInfoTLV->oamConfig.infoTlvOamCfgVal)&0x1E)
		{
			localSatisfied = 1;
		}
		else
		{
			localSatisfied = 0;
		}

		if(rmtOAMFlagField.Bits.localStableEval == DISCOVERY_COMPLETED)
		{
			remoteStable = 1;
		}
		else if(rmtOAMFlagField.Bits.localStableEval != 0x3)
		{
			remoteStable = 0;
		}

		/*get remote DTE information*/
		if(rmtOAMFlagField.Bits.linkFault == 1)			
			remoteFXLink = 0;
		else
			remoteFXLink = 1;
		
		if((tRemoteInfoTLV->ouiHigh==OAMPDU_OUI_MSB) && (tRemoteInfoTLV->ouiLow==OAMPDU_OUI_LSB))
		{
			if(tRemoteInfoTLV->vendorInfoCode == OAM_SPEC_CODE)
			{
				remoteDTEType = tRemoteInfoTLV->vendorDTEType;
				remoteTPLink = tRemoteInfoTLV->hwVerTpLink.Bits.TpLinkStatus;
				remotePwrUpFlg = tLocalInfoTLV->hwVerTpLink.Bits.firstPwrUpFlg;
				remoteHWVer = tRemoteInfoTLV->hwVerTpLink.Bits.vendorHWVer;
				remoteSWVer = tRemoteInfoTLV->vendorSWVer;
			}			
		}
	}

	/*get the remote info type*/
	tempByte = RECEIVE_NETWORK_B();
	if(tempByte == TLV_INFO_TYPE_END)
	{	
		return;
	}
	if(tempByte != TLV_INFO_TYPE_REMOTE)
	{
		return; /*it's an invalid info OAMPDU*/
	}
	else
	{
		/*check the info OAMPDU length field*/
		if(RECEIVE_NETWORK_B() != TLV_INFO_LEN)
			return; /*length is inlvalid*/

		/*get the OAM Version field*/
		RECEIVE_NETWORK_B();

		/*get the info OAMPDU Revision field*/
		RECEIVE_NETWORK_W();

		/*get the info OAMPDU state field*/
		RECEIVE_NETWORK_B();

		/*get the info OAM configration field*/
		RECEIVE_NETWORK_B();

		/*get the info OAMPDU configration field*/
		RECEIVE_NETWORK_W();

		/*get the info OAMPDU OUI field*/
		RECEIVE_NETWORK_B();
		RECEIVE_NETWORK_W();		

		/*get the info OAMPDU vendor specific field*/
		RECEIVE_NETWORK_W();
		RECEIVE_NETWORK_W();
	}	

	/*reset the lost link timer*/
	init_timer(locLstLnkTimer, locLstLnkTmrPrd*TIMERTIC);
	
	/*get the specific info type*/
	tempByte = RECEIVE_NETWORK_B();
	if(tempByte == TLV_INFO_TYPE_END)
	{
		return;
	}
	else
	{
		/*process the specific info here, no definition now*/
	}
}

/*
 * Function:
 *   process_spec_oampdu()
 * Purpose:
 *   Process the organization specific OAMPDU.
 * Parameters:
 *   bufIndex -- the data start pointer in MBUF.
 * Returns:
 *   None.
 * Notes:
 *   None.
 */
void process_spec_oampdu(UINT16 bufIndex)
{
	UINT8  tempByte;
	UINT16 tempWord;
	UINT16 dataLen;
	UINT8  dataEnd;

	dot3ahRxSpecPkts++;
	
	/*get the OUI*/
	tempByte = RECEIVE_NETWORK_B();
	bufIndex += 1;
	tempWord = RECEIVE_NETWORK_W();
	bufIndex += 2;
	/*check the OUI, if not wri OUI, return*/
	if((tempByte!=OAMPDU_OUI_MSB) || (tempWord!=OAMPDU_OUI_LSB))
		return;

	/*check the specific code, if not 0xB3, return*/
	if(RECEIVE_NETWORK_B() != OAM_SPEC_CODE)
		return;
	
	bufIndex += 1;
	
	dataEnd = 0;
	dataLen = 0;
	
	for(;;)
	{
		/*get the specific TLV type*/
		tempByte = RECEIVE_NETWORK_B();
		switch(tempByte)
		{
			case SPEC_TYPE_END:
				dataEnd = 1;
				break;
				
			case SPEC_TYPE_CFG_SET_REQ:				
				/*check the config tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_CFG_SET_REQ_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_CFG_SET_REQ_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_CFG_SET_REQ_LEN + 2);
				break;
				
			case SPEC_TYPE_STAT_GET_REQ:
				/*check the status get request tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_STAT_GET_REQ_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_STAT_GET_REQ_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_STAT_GET_REQ_LEN + 2);				
				break;
				
			case SPEC_TYPE_STAT_GET_RES:
				/*check the status get response tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_STAT_GET_RES_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_STAT_GET_RES_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_STAT_GET_RES_LEN + 2);
				break;
				
			case SPEC_TYPE_RATELMT_SET_REQ:
				/*check the rate limit set request tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_RATELMT_SET_REQ_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_RATELMT_SET_REQ_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_RATELMT_SET_REQ_LEN + 2);
				break;
				
			case SPEC_TYPE_RATELMT_GET_REQ:
				/*check the rate limit get request tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_RATELMT_GET_REQ_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_RATELMT_GET_REQ_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_RATELMT_GET_REQ_LEN + 2);
				break;
				
			case SPEC_TYPE_RATELMT_GET_RES:
				/*check the rate limit get response tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_RATELMT_GET_RES_LEN)
				{
					dataEnd = 1;
					break;
				}
				if((dataLen+SPEC_RATELMT_GET_RES_LEN+2+SPEC_OAM_HEADER_FCS_LEN) > OAMPDU_MAX_SIZE)
				{
					dataEnd = 1;
					break;
				}
				dataLen += (SPEC_RATELMT_GET_RES_LEN + 2);
				break;
				
			case SPEC_TYPE_STATISTIC_GET_REQ:
				/*check the statistics get request tlv length*/
				if(RECEIVE_NETWORK_B() != SPEC_STATISTIC_GET_REQ_LEN)
				{

⌨️ 快捷键说明

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