📄 igmp_router.cpp
字号:
/*******************************************************
文件名: igmp_router.cpp
文件说明:
本文件是IGMP Router子模块文件,负责处理来自ATM的IGMP
包,完成IGMP Router功能。
修改记录:
1. 2004-4-7 changzhan 初次建立本文件
*******************************************************/
/*
#include "igmp.h"
#include "igmp_interface.h"
#include <ipuplink.h>
#include <CustomMemory.h>
#include <CustomTimer.h>
#include "Igmp_control.h"
*/
#include "igmpcon.h"
#define ROUTER_VID 4088
#define HOST_VID 4088
#define ReservedVlan 4089
#define DefaultVlan 4088
/***************************************************
函数名称:RouterProcessIgmpV2Query
函数功能:处理IGMP V1查询包
输入参数:ReceiveIgmpMsg 接收到的IGMP包
返回值: 无
***************************************************/
struct ethernet_information gEtherInfo1; /*aibin */
void RouterProcessIgmpV1Query (IGMPMsg ReceiveIgmpMsg)
{
if (!bEnableQueryElection)
{
return;
}
}
/***************************************************
函数名称:RouterProcessIgmpV2Query
函数功能:处理IGMP V2查询包
输入参数:ReceiveIgmpMsg 接收到的IGMP包
返回值: 无
***************************************************/
void RouterProcessIgmpV2Query (IGMPMsg ReceiveIgmpMsg)
{
GroupEntity *pTemp;
int i; /*,Flag = 0 */
if (!bEnableQueryElection)
{
return;
}
pTemp = pGroupEntityList;
while (pTemp)
{
for (i = 1; i <= MAX_UPLINK_PORT; i++)
{
if (pTemp->eGroupPortStatus[i] == CheckingMembership)
{
/*Flag = 1; */
return;
}
}
pTemp = pTemp->pNext;
}
/*if(Flag == 1) 有成员正在离开,忽略查询消息
{
return;
} 2004.11.9 */
if (gEtherInfo.ipAddr > ReceiveIgmpMsg.unSourceAddress)
{
bQuerierFlag = FALSE;
StartOtherQuerierPresentTimer ();
/*if (tGeneralQueryTimer != 0)
{
StopGeneralQueryTimer ();
} */
if (tStartupQueryTimer != 0)
{
StopStartupQueryTimer ();
}
}
}
/***************************************************
函数名称:RouterProcessIgmpV1Report
函数功能:处理IGMP V1 Report包
输入参数:ReceiveIgmpMsg 接收到的IGMP包
返回值: 无
***************************************************/
void RouterProcessIgmpV1Report (IGMPMsg ReceiveIgmpMsg)
{
GroupEntity *IgmpGroup;
if ((ReceiveIgmpMsg.unDestinationAddress != ReceiveIgmpMsg.unGroupAddress))
{ /*数据包非法则丢弃 */
ulATMReceiveIgmpBad++;
if (bIgmpDebug)
{
printf ("RouterProcessIgmpV1Report Receive Bad Pkt!\n");
}
return;
}
IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
if (IgmpGroup == NULL) /*组播组不存在 */
{
if ((usCurrentUser >= usMaxUser) || (usCurrentGroup > MaxGroup))
{ /*达到容量限制 */
return;
}
IgmpGroup = AddNewIgmpGroup (ReceiveIgmpMsg.unGroupAddress);
IgmpGroup->OutVlanTag = GetGroupVlan (ReceiveIgmpMsg.unGroupAddress);
if (IgmpGroup == NULL) /*添加组播组失败 */
{
printf ("AddNewIgmpGroup FAIL!\n");
return;
}
semTake (semIgmpDelete, WAIT_FOREVER);
AddPortToSpecificGroup (ReceiveIgmpMsg.unGroupAddress,
ReceiveIgmpMsg.usPort);
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] = V1MembersPresent;
IgmpGroup->bGroupV1HostPresentFlag = TRUE;
if (!IfPreJoinNodeExist (ReceiveIgmpMsg.unGroupAddress)) /*如果不是预加入的组就发加入报文 2006.8.8 */
SpecificGroupSendV1Report (ReceiveIgmpMsg.unGroupAddress);
StartHostReportDelayTimer (IgmpGroup, usUnsolicitedReportInterval);
StartGroupV1HostPresentTimer (IgmpGroup);
StartGroupPortV1HostTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
AddPortToSearchGroup (IgmpGroup, ReceiveIgmpMsg.usPort);
usCurrentUser++;
semGive (semIgmpDelete);
}
else /*组播组已经存在 */
{
if (!FindPortInSpecificGroup (IgmpGroup, ReceiveIgmpMsg.usPort)) /*端口不存在 */
{
if (usCurrentUser >= usMaxUser)
{ /*达到容量限制 */
return;
}
semTake (semIgmpDelete, WAIT_FOREVER);
AddPortToSpecificGroup (ReceiveIgmpMsg.unGroupAddress,
ReceiveIgmpMsg.usPort);
IgmpGroup->bGroupV1HostPresentFlag = TRUE;
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] =
V1MembersPresent;
IgmpGroup->usGroupUserNumber++; /*组成员数加1 */
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
StartGroupV1HostPresentTimer (IgmpGroup);
StartGroupPortV1HostTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
AddPortToSearchGroup (IgmpGroup, ReceiveIgmpMsg.usPort);
AddPortToGroup (ReceiveIgmpMsg.unGroupAddress,
ReceiveIgmpMsg.usPort);
usCurrentUser++;
semGive (semIgmpDelete);
}
else /*端口已经存在 */
{
IgmpGroup->bGroupV1HostPresentFlag = TRUE;
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] =
V1MembersPresent;
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
StartGroupV1HostPresentTimer (IgmpGroup);
StartGroupPortV1HostTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
}
}
}
/***************************************************
函数名称:RouterProcessIgmpV2Report
函数功能:处理IGMP V2 Report包
输入参数:ReceiveIgmpMsg 接收到的IGMP包
返回值: 无
***************************************************/
void RouterProcessIgmpV2Report (IGMPMsg ReceiveIgmpMsg)
{
GroupEntity *IgmpGroup;
/*检查上联带宽是否超过最大值 */
if (CheckUpBandwidth (ReceiveIgmpMsg.unGroupAddress) == -1)
{
return;
}
if (ReceiveIgmpMsg.ucIGMPType == IGMPV3MembershipReport)
{
if (ReceiveIgmpMsg.unDestinationAddress != 0xe0000016)
{
ulATMReceiveIgmpBad++;
if (bIgmpDebug)
{
printf ("RouterProcessIgmpV3Report Receive Bad Pkt!\n");
}
return;
}
}
else
{
if (ReceiveIgmpMsg.unDestinationAddress !=
ReceiveIgmpMsg.unGroupAddress)
{ /*Report包的目的IP和组地址必须一致 */
ulATMReceiveIgmpBad++;
if (bIgmpDebug)
{
printf ("RouterProcessIgmpV2Report Receive Bad Pkt!\n");
}
return;
}
}
if ( /*(ReceiveIgmpMsg.unGroupAddress <= 0xe00000ff) || */
(ReceiveIgmpMsg.unGroupAddress > 0xefffffff))
{ /*Report包的目的IP应该在224.0.1.0到239.255.255.255之间 */
/*IANA预留224.0.0.1到224.0.0.255的组播地址,为路由协议以及其他低级拓扑查找及维护协议使用
224.0.0.1 所有主机
224.0.0.2 所有路由器
224.0.0.3 不分配
224.0.0.4 DVMRP路由器
224.0.0.5 OSPF路由器
224.0.0.6 OSPF指定路由器
224.0.0.7 ST路由器
224.0.0.8 ST主机
224.0.0.9 RIP2路由器
224.0.0.10 IGRP路由器
224.0.0.11 活动代理
224.0.0.12 DHCP服务器、中继代理
224.0.0.13 所有PIM路由器
224.0.0.14 PSVP封装
224.0.0.15 所有CBT路由器
224.0.0.16 指定SBM
224.0.0.17 所有SBM
224.0.0.18 VRRP
224.0.0.19~224.0.0.255 不分配
224.0.1.0 VMTP管理组
224.0.1.1 网络时间协议
224.0.1.2 SGI Dogfight
224.0.1.3 Rwhod
224.0.1.4 VNP
224.0.1.5 人工界限Artificial Horizons
224.0.1.6 名称维护服务器
224.0.1.7 声音新闻组AudioNews
224.0.1.8 SUN NIS+信息服务
224.0.1.9 MTP组播传输协议
224.0.1.10 IETF-1-LOW-AUDIO
224.0.1.11 IETF-1-AUDIO
224.0.1.12 IETF-1-VIDEO
224.0.1.13 IETF-2-LOW-AUDIO
224.0.1.14 IETF-2-AUDIO
224.0.1.15 IETF-2-VIDEO
224.0.1.16 MUSIC-SERVICE
224.0.1.17 SEANET-TELEMETRY
224.0.1.18 SEANET-IMAGE
224.0.1.19 MLOADD
224.0.1.20 任何私人实验
224.0.1.21 MOSPF上的DVMRP
224.0.1.32 Mtrace
224.0.1.33 RSAP封装1
224.0.1.34 RSAP封装2
224.0.1.39 Cisco RP公告
224.0.1.40 Cisco RP发现
224.0.1.80~224.0.1.255 不分配
*/
ulATMReceiveIgmpBad++;
if (bIgmpDebug)
{
printf ("RouterProcessIgmpV2Report Receive Reserved IP!\n");
}
return;
}
IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
if (IgmpGroup == NULL) /*组播组不存在 */
{
if ((usCurrentUser >= usMaxUser) || (usCurrentGroup > MaxGroup))
{ /*达到容量限制 */
return;
}
/*printf("组播组不存在,新建组播组\n"); */
IgmpGroup = AddNewIgmpGroup (ReceiveIgmpMsg.unGroupAddress);
/*IgmpGroup->OutVlanTag = GetGroupVlan(ReceiveIgmpMsg.unGroupAddress); eidt by aibin 20080404 */
if (IgmpGroup == NULL)
{
printf ("AddNewIgmpGroup FAIL!\n");
return;
}
semTake (semIgmpDelete, WAIT_FOREVER);
AddPortToSpecificGroup (ReceiveIgmpMsg.unGroupAddress, ReceiveIgmpMsg.usPort); /*通知底层 */
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] = MembersPresent;
/*启动定时器 */
if (!IfPreJoinNodeExist (ReceiveIgmpMsg.unGroupAddress)) /*如果不是预加入的组就发加入报文 2006.8.8 */
SpecificGroupSendV2Report (ReceiveIgmpMsg.unGroupAddress);
/*StartHostReportDelayTimer (IgmpGroup, usUnsolicitedReportInterval); */
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
AddPortToSearchGroup (IgmpGroup, ReceiveIgmpMsg.usPort);
usCurrentUser++;
semGive (semIgmpDelete);
/*printf("User++\n"); */
}
else /*组播组已经存在 */
{
if (!FindPortInSpecificGroup (IgmpGroup, ReceiveIgmpMsg.usPort)) /*端口不存在 */
{
if (usCurrentUser >= usMaxUser)
{ /*达到容量限制 */
return;
}
/*printf("组播组已经存在,添加端口\n"); */
semTake (semIgmpDelete, WAIT_FOREVER);
AddPortToSpecificGroup (ReceiveIgmpMsg.unGroupAddress,
ReceiveIgmpMsg.usPort);
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] = MembersPresent;
IgmpGroup->usGroupUserNumber++;
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
AddPortToSearchGroup (IgmpGroup, ReceiveIgmpMsg.usPort);
/*通知底层 */
AddPortToGroup (ReceiveIgmpMsg.unGroupAddress,
ReceiveIgmpMsg.usPort);
usCurrentUser++;
semGive (semIgmpDelete);
/*printf("User++\n"); */
}
else /*端口已经存在 */
{
/*printf("端口已经存在,刷新定时器\n"); */
if (IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] ==
CheckingMembership)
{
StopGroupPortLastMemberQueryTimer (IgmpGroup,
ReceiveIgmpMsg.usPort);
IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] =
MembersPresent;
}
StartGroupPortV2MembershipTimer (IgmpGroup, ReceiveIgmpMsg.usPort);
}
testReceieveJoin++;
}
}
/***************************************************
函数名称:RouterProcessIgmpLeave
函数功能:处理IGMP Leave包
输入参数:ReceiveIgmpMsg 接收到的IGMP包
返回值: 无
***************************************************/
void RouterProcessIgmpLeave (IGMPMsg ReceiveIgmpMsg)
{
GroupEntity *IgmpGroup;
if ((ReceiveIgmpMsg.unDestinationAddress != 0xe0000002) && (ReceiveIgmpMsg.unDestinationAddress != ReceiveIgmpMsg.unGroupAddress)) /*数据包非法 */
{ /*RFC2236规定离开包的地址应该是224.0.0.2,但为了提高兼容性,目的IP和组播组地址一致也可以。 */
ulATMReceiveIgmpBad++;
if (bIgmpDebug)
{
printf ("RouterProcessIgmpLeave Receive Bad Pkt!\n");
}
return;
}
if (!bQuerierFlag) /*非查询者状态下忽略离开报文 */
{
ulATMReceiveIgmpBad++;
return;
}
IgmpGroup = FindIgmpGroupByAddress (ReceiveIgmpMsg.unGroupAddress);
if (IgmpGroup == NULL) /*没有找到该组 */
{
//printf ("RouterProcessIgmpLeave:No such a group!\n");
return;
}
if (!FindPortInSpecificGroup (IgmpGroup, ReceiveIgmpMsg.usPort))
{ /*该组中没有这个成员端口 */
//printf ("RouterProcessIgmpLeave:No such a port!\n");
return;
}
if (IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] ==
CheckingMembership)
{
//printf ("RouterProcessIgmpLeave:port == Checking!\n");
return;
}
if (IgmpGroup->bGroupV1HostPresentFlag) /*该组有V1成员 */
{
if (IgmpGroup->eGroupPortStatus[ReceiveIgmpMsg.usPort] !=
MembersPresent)
{
return;
}
}
DeletePortFromSpecificGroup (IgmpGroup, ReceiveIgmpMsg.usPort,
ReceiveIgmpMsg.user);
testReceiveLeave++;
/*move */
}
/***************************************************
函数名称:AddPortToSpecificGroup
函数功能:将端口加入指定组播组
输入参数:unGroupAddress 组播组地址
usPort 指定的端口
返回值: 无
***************************************************/
void AddPortToSpecificGroup (UINT unGroupAddress, USHORT usPort)
{
/*printf("AddPortToGroup:0x%x,0x%x\n",usPort,unGroupAddress); */
AddPortToGroup (unGroupAddress, usPort); /*由底层提供的接口函数 */
}
/***************************************************
函数名称:DeletePortFromSpecificGroup
函数功能:将端口从指定组播组中删除
输入参数:IgmpGroup 指向组播组的指针
usPort 指定的端口
返回值: 无
***************************************************/
void DeletePortFromSpecificGroup (GroupEntity * IgmpGroup, USHORT usPort,
int user)
{
int leavedelaytime;
if (semIgmpDelete == NULL)
{
return;
}
/*printf("Port %d 离开\n",usPort); */
if (IgmpGroup->eGroupPortStatus[usPort] != MembersPresent)
{
return;
}
semTake (semIgmpDelete, WAIT_FOREVER); /*信号量保护 */
leavedelaytime = GetLeaveDelay (IgmpGroup->unGroupAddress);
if (bEnableInstantLeave && !leavedelaytime) /*允许端口开速离开 */
{
/*printf("DelPortFromGroup:0x%x,%d\n",IgmpGroup->unGroupAddress,usPort); */
DelPortFromGroup1 (IgmpGroup->unGroupAddress, usPort); /*由底层提供的接口函数 */
//StopGroupPortV2MembershipTimer (IgmpGroup-> tGroupPortV2MembershipTimer[usPort]);
DelPortFromSearchGroup (IgmpGroup, usPort);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -