📄 igmp_host.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 + -