⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igmp_host.cpp

📁 igmp for switch in vxworks
💻 CPP
字号:
/*******************************************************
文件名: igmp_host.cpp
文件说明:
本文件是IGMP Host子模块文件,负责处理来自Ethernet的IGMP
包,完成IGMP Host功能。

修改记录:


1. 2004-4-7 changzhan   初次建立本文件
*******************************************************/

#include "igmpcon.h"
/*#include "igmp_interface.h"*/
/*
#include <CustomTimer.h>
*/


#if 1
/***************************************************
函数名称:HostProcessIgmpV1Query
函数功能:处理IGMP V1查询包
输入参数:ReceiveIgmpMsg 接收到的IGMP包 
返回值:	 无
***************************************************/
void HostProcessIgmpV1Query (IGMPMsg ReceiveIgmpMsg)
{
	GroupEntity *IgmpGroup;

	if (ReceiveIgmpMsg.unDestinationAddress == 0xe0000001)	/*通用查询*/
	{
		if (ReceiveIgmpMsg.unGroupAddress != 0) /*通用查询组地址必须为0*/
		{
			ulEtherReceiveIgmpBad++;
			if (bIgmpDebug)
			{
				printf ("HostProcessIgmpV1GeneralQuery Receive Bad Pkt!\n");
			}
			return;
		}
		bV1RouterPresentFlag = TRUE;
		StartV1RouterPresentTimer ();
		IgmpGroup = pGroupEntityList;
		while(IgmpGroup)
		{
			/*IgmpGroup->OutVlanTag = ReceiveIgmpMsg.VlanTag;*/       /*edit by aibin 20080404*/
			IgmpGroup = IgmpGroup->pNext;
		}
		AllGroupSendReport (ReceiveIgmpMsg.ucMaxResponseTime);
	}
	else						/*通用查询特定组*/
	{
		if (ReceiveIgmpMsg.unGroupAddress !=
			ReceiveIgmpMsg.unDestinationAddress)/*特定查询组地址必须等于目的IP地址*/
		{
			ulEtherReceiveIgmpBad++;
			if (bIgmpDebug)
			{
				printf
					("HostProcessIgmpV1Group-SpecificQuery Receive Bad Pkt!\n");
			}
			return;
		}
		/*查找组播组是否存在*/
		IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
		if (IgmpGroup != NULL)/*组播组存在*/
		{
			IgmpGroup->eHostStatus = DelayingMember;
			/*IgmpGroup->OutVlanTag = ReceiveIgmpMsg.VlanTag;*/   /*edit by aibin 20080404*/
			StartHostReportDelayTimer (IgmpGroup,
				ReceiveIgmpMsg.ucMaxResponseTime);
		}
	}

}

/***************************************************
函数名称:HostProcessIgmpV2Query
函数功能:处理IGMP V2查询包
输入参数:ReceiveIgmpMsg 接收到的IGMP包 
返回值:	 无
***************************************************/
void HostProcessIgmpV2Query (IGMPMsg ReceiveIgmpMsg)
{
	GroupEntity *IgmpGroup;

	if (ReceiveIgmpMsg.unDestinationAddress == 0xe0000001)	/*通用查询*/
	{
		if (ReceiveIgmpMsg.unGroupAddress != 0)
		{
			ulEtherReceiveIgmpBad++;
			if (bIgmpDebug)
			{
				printf ("HostProcessIgmpV2GeneralQuery Receive Bad Pkt!\n");
			}
			return;
		}
		IgmpGroup = pGroupEntityList;
		while(IgmpGroup)
		{
			/*IgmpGroup->OutVlanTag = ReceiveIgmpMsg.VlanTag;*/  /*edit by aibin 20080404*/
			IgmpGroup = IgmpGroup->pNext;
		}
		AllGroupSendReport (ReceiveIgmpMsg.ucMaxResponseTime);

	}
	else						/*特定组查询*/
	{
		if (ReceiveIgmpMsg.unGroupAddress !=
			ReceiveIgmpMsg.unDestinationAddress)
		{
			ulEtherReceiveIgmpBad++;
			if (bIgmpDebug)
			{
				printf
					("HostProcessIgmpV2Group-SpecificQuery Receive Bad Pkt!\n");
			}
			return;
		}
		IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
		if (IgmpGroup != NULL)
		{
			IgmpGroup->eHostStatus = DelayingMember;
			/*IgmpGroup->OutVlanTag = ReceiveIgmpMsg.VlanTag;*/  /*edit by aibin 20080404*/
			//printf("Store VLAN TAG %d\n",ReceiveIgmpMsg.VlanTag);
			StartHostReportDelayTimer (IgmpGroup,
				ReceiveIgmpMsg.ucMaxResponseTime);
		}
	}

}

/***************************************************
函数名称:HostProcessIgmpV2Query
函数功能:处理IGMP Report包
输入参数:ReceiveIgmpMsg 接收到的IGMP包 
返回值:	 无
***************************************************/
void HostProcessIgmpReport (IGMPMsg ReceiveIgmpMsg)
{
	GroupEntity *IgmpGroup;

	/*Report包目的IP必须等于组播组IP*/
	if (ReceiveIgmpMsg.unGroupAddress != ReceiveIgmpMsg.unDestinationAddress)
	{
		ulEtherReceiveIgmpBad++;
		return;
	}
	
	IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
	if (IgmpGroup == NULL)/*组播组不存在*/
	{
		return;
	}
	if (IgmpGroup->eHostStatus != DelayingMember)
	{
		return;
	}
	/*组播组存在*/
	/*以下处理参见RFC2236 Host状态机*/
	IgmpGroup->eHostStatus = IdleMember;
	//StopHostReportDelayTimer (IgmpGroup);
	/*IgmpGroup->tHostReportDelayTimer = 0;*/             /*收到加入报文不再抑制往上联口测发加入, aibin 20061116*/
	IgmpGroup->bHostLastMemberFlag[ReceiveIgmpMsg.usPort] = FALSE;
}


/***************************************************
函数名称:AllGroupSendReport
函数功能:通知所有存在的组播组发送Report包
输入参数:MaxResponseTime 最大响应时间 
返回值:	 无
***************************************************/
void AllGroupSendReport (UCHAR MaxResponseTime)
{
	GroupEntity *pTemp;

	if (pGroupEntityList == NULL)
	{
		return;
	}
	pTemp = pGroupEntityList;

	if (MaxResponseTime == 0)	/*版本1 */
	{
		MaxResponseTime = 10;
	}

	while (pTemp)
	{
		if (bIgmpDebug)
		{
			if (pTemp->eHostStatus == NonMember)
			{
				printf ("AllGroupSendReport ERROR : NonMember!\n");
			}
		}
		if (pTemp->eHostStatus == DelayingMember)
		{
			/*if (usQueryInterval > MaxResponseTime)	参见RFC2236 3.4节 
			{*/
				StartHostReportDelayTimer (pTemp, MaxResponseTime);
			/*}*/
		}
		if (pTemp->eHostStatus == IdleMember)
		{
			if (bIgmpDebug)
			{
				if (pTemp->tHostReportDelayTimer != 0)
				{
					printf
						("AllSendReport ERR: tHostReportDelayTimer Not Zero ! \n ");
				}
			}
			pTemp->eHostStatus = DelayingMember;
			StartHostReportDelayTimer (pTemp, MaxResponseTime);

		}
		pTemp = pTemp->pNext;
	}

}

/***************************************************
函数名称:HostProcessV1RouterPresentTimeOutEvent
函数功能:处理V1RouterPresent超时事件
输入参数:无
返回值:	 无
***************************************************/
void HostProcessV1RouterPresentTimeOutEvent ()
{
	bV1RouterPresentFlag = FALSE;
	tV1RouterPresentTimer = 0;
}

/***************************************************
函数名称:HostProcessHostReportDelayTimeOutEvent
函数功能:处理HostReportDelay超时事件
输入参数:IgmpGroup 指向组播组的指针
返回值:	 无
***************************************************/
void HostProcessHostReportDelayTimeOutEvent (GroupEntity * IgmpGroup)
{
	int i;
	
	if (!FindIgmpGroupFromList (IgmpGroup))/*组播组不存在*/
	{
		if (bIgmpDebug)
		{
			printf ("HostReportDelayTimeOut ERROR:Group Not Found!\n");
		}
		return;
	}
	for (i = 1; i <= MAX_UPLINK_PORT; i++)
	{
		if (slot_module[i] == HOST_MODULE_PORT)
		{
			IgmpGroup->bHostLastMemberFlag[i] = TRUE;
		}
	}
	IgmpGroup->eHostStatus = IdleMember;
	IgmpGroup->tHostReportDelayTimer = 0;
#if 1  /*RFC2236推荐发两次加入报文确保路由器能收到,但中国电信测试要求只发一次20060412 */
 if (bV1RouterPresentFlag)
	{
		SpecificGroupSendV1Report (IgmpGroup->unGroupAddress);
	}
	else
	{
		SpecificGroupSendV2Report (IgmpGroup->unGroupAddress);
	}
#endif 
}

/***************************************************
函数名称:StartV1RouterPresentTimer
函数功能:启动V1RouterPresent定时器
输入参数:无
返回值:	 无
***************************************************/
void StartV1RouterPresentTimer (void)
{
	TimerEntity *TimeOut;

	if (tV1RouterPresentTimer != 0) /*定时器已经存在*/
	{
                nos_deltimer(tV1RouterPresentTimer); /*mod by aibin */
		/*TimeOut = (TimerEntity *) StopTimer (tV1RouterPresentTimer);*/
		
	}
	else
	{
              TimeOut = (TimerEntity *) malloc (sizeof (TimerEntity));
		/*TimeOut = (TimerEntity *) CustomMalloc (sizeof (TimerEntity));*/
		if (TimeOut == NULL)
		{
			if (bIgmpDebug)
			{
				printf ("Malloc Timer ERROR!\n");
			}
			return;
		}
		memset(TimeOut,0,sizeof (TimerEntity));
		usCurrentTimer++;
		TimeOut->TimerType = V1RouterPresentTimeOutEvent;
		TimeOut->IgmpGroup = NULL;
	}
	/*把原来的定时器替换成nos_timeout定时器,aibin  2005-01-19*/
	tV1RouterPresentTimer =
		nos_timerout ((UINT)usV1RouterPresentTimeout* 1000,(long int)ProcessIgmpTimerEvent, (char *) TimeOut);
	/*	StartTimer ((UINT) usV1RouterPresentTimeout * 1000, */
	/*	(TIMERFUNC) ProcessIgmpTimerEvent, (ULONG) TimeOut, TIMERONESHOT);  */
}


/***************************************************
函数名称:StopV1RouterPresentTimer
函数功能:停止V1RouterPresent定时器
输入参数:无
返回值:	 无
***************************************************/
void StopV1RouterPresentTimer (void)
{
	/*TimerEntity *TimeOut;*/

	if (tV1RouterPresentTimer != 0)
	{
              nos_deltimer(tV1RouterPresentTimer);  /*mod by aibin */
		/*TimeOut = (TimerEntity *) StopTimer (tV1RouterPresentTimer);*/
		/*free (TimeOut); /*CustomFree ((void *) TimeOut);/*释放定时器参数*/
		usCurrentTimer--;
	}
	tV1RouterPresentTimer = 0;
}

/***************************************************
函数名称:StartHostReportDelayTimer
函数功能:启动HostReportDelay定时器
输入参数:IgmpGroup 指向组播组的指针
		 ucMaxResponseTime 最大响应时间
返回值:	 无
***************************************************/
void StartHostReportDelayTimer (GroupEntity * IgmpGroup,UCHAR ucMaxResponseTime)
{
	IgmpGroup->tHostReportDelayTimer = GetRandomTimeByMaxRespTime (ucMaxResponseTime) * TIMER_RATE;
	
	#if 0
	TimerEntity *TimeOut;
	UINT	unInterval;

	if (IgmpGroup->tHostReportDelayTimer == 0) /*定时器不存在*/
	{
		TimeOut = (TimerEntity *) CustomMalloc (sizeof (TimerEntity));
		if (TimeOut == NULL)
		{
			if (bIgmpDebug)
			{
				printf ("Malloc Timer ERROR!\n");
			}
			return;
		}
		usCurrentTimer++;
	}
	else	/*定时器已经存在*/
	{
		TimeOut = (TimerEntity *) StopTimer (IgmpGroup->tHostReportDelayTimer);
	}
	TimeOut->IgmpGroup = IgmpGroup;
	TimeOut->TimerType = HostReportDelayTimeOutEvent;
	unInterval = GetRandomTimeByMaxRespTime (ucMaxResponseTime *	1000);
	/*printf("unInterval = %d\n",unInterval);*/
	IgmpGroup->tHostReportDelayTimer =
		StartTimer (unInterval, (TIMERFUNC) ProcessIgmpTimerEvent, (ULONG) TimeOut, TIMERONESHOT);
	/*taskDelay(2);*/
	#endif
}

/***************************************************
函数名称:StopHostReportDelayTimer
函数功能:停止HostReportDelay定时器
输入参数:unTimerID 定时器ID号
返回值:	 无
***************************************************/
void StopHostReportDelayTimer (GroupEntity * IgmpGroup)
{
	IgmpGroup->tHostReportDelayTimer = 0;
	#if 0
	TimerEntity *TimeOut;

	if (unTimerID != 0)
	{
		TimeOut = (TimerEntity *) StopTimer (unTimerID);
		CustomFree ((void *) TimeOut);/*释放定时器参数*/
		usCurrentTimer--;
	}
	#endif
}

/***************************************************
函数名称:SpecificGroupSendV1Report
函数功能:指定的组播组发送V1 Report包
输入参数:unGroupAddress 组播组地址
返回值:	 无
***************************************************/
void SpecificGroupSendV1Report (UINT unGroupAddress)
{
	SendIgmpPkt (IGMPV1MembershipReport,unGroupAddress, 0, 0);
}


/***************************************************
函数名称:SpecificGroupSendV2Report
函数功能:指定的组播组发送V2 Report包
输入参数:unGroupAddress 组播组地址
返回值:	 无
***************************************************/
void SpecificGroupSendV2Report (UINT unGroupAddress)
{
	USHORT slot;
	
	SendIgmpPkt (IGMPV2MembershipReport,unGroupAddress, 0, 0);
	
/*	if (fsourcecon)
	{
		slot = CheckUpLinksrc(unGroupAddress);
		if (!slot)
		{
			return;
		}
		SendIgmpPkt (IGMPV2MembershipReport,unGroupAddress, slot, 0);
	}
	else
	{
		SendIgmpPkt (IGMPV2MembershipReport,unGroupAddress, 0, 0);
	}
	*/
}


/***************************************************
函数名称:SpecificGroupSendLeaveGroup
函数功能:指定的组播组发送Leave包
输入参数:unGroupAddress 组播组地址
返回值:	 无
***************************************************/
void SpecificGroupSendLeaveGroup (UINT unGroupAddress)
{
	GroupEntity *ptmp;
	int i;

	ptmp = FindIgmpGroupByAddress(unGroupAddress);
	if (NULL == ptmp)
	return;

	if(!IfPreJoinNodeExist(unGroupAddress)) /*如果不是预加入的组就发离开报文 2006.8.8*/
	{
		for (i = MIN_UPLINK_PORT; i <= MAX_UPLINK_PORT; i++)
		{
			if (ptmp->bHostLastMemberFlag[i] == TRUE)
			{
				SendIgmpPkt (IGMPLeaveGroup,unGroupAddress, i, 0);
			}
		}	
	}
}
#endif

⌨️ 快捷键说明

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