📄 igmpcon_main.c
字号:
/************************************************************
Copyright (C), 1988-2002, Fiberhome Tech. Co., Ltd.
文件名: igmpcon_main.c
作者: aibin
日期: 2006-12-19
文件描述: 可控组播主函数,负责接收和处理
可控组播私有协议报文
版本: // 版本信息
***********************************************************/
#include "igmpcon.h"
#define OK 0
#define MaxRecord 200 /*最大日志条数 */
#define MaxGroupStat 255 /*最大组统计条数 */
#define SAVE_CHECK 124 /*存储读取标志检查 */
#define MODULE_IGMPCON 1 /*可控组播模块号 */
#define defalut_igmp_port 1 /*iptv默认端口 */
MSG_Q_ID ConMsgQId = 0;
int ConTaskId;
#ifdef TEST
BOOL bConDebug = FALSE;
#else
BOOL bConDebug = FALSE;
#endif
BOOL bConDebugSnmp = FALSE;
BOOL gEnableCrossVlan = FALSE; /*TRUE 表示跨VLAN ,可有多个组播VLAN, FALSE表示不跨VLAN,只能和单播共用一个VLAN */
SEM_ID semConinfo = 0;
SEM_ID semConauth = 0;
SEM_ID semConLog = 0;
SEM_ID semConStat = 0;
SEM_ID semBandwidth = 0;
UINT tConRecordTmer; /*日志查询时间 */
UINT tConQueryTimer; /*控制查询时间 */
UINT tStartUpQuery = 0; /*启动时的查询 */
short gConOld = 300;
UINT MaxUpBandwidth; /*上传带宽上限 */
UINT CurrentUpBandwidth; /*当前总共上传带宽 */
USHORT Totaluser; /*总用户数 */
USHORT Totalgroup; /*总组播组数 */
USHORT Totalauthgroup; /*配置的认证组个数 */
USHORT sendpktcount[MAX_DOWN_SLOT + 1]; /*发送指定槽位线卡控制包计数 */
UCHAR previewtime = 10; /*预览持续时间 */
UCHAR previewinterval = 20; /*预览间隔 */
UCHAR previewresettime = 24; /*预览复位时间 */
UCHAR previewcount = 4; /*预览次数 */
UCHAR previewTotalTime = 254; /*总预览时间,min */
struct Group_auth *authlist = NULL; /*认证表 */
struct Group_info *infolist = NULL; /*当前信息表 */
struct Port_Record *recordlist = NULL; /*日志表 */
struct Group_Stat *groupstatlist = NULL; /*组用户统计表 */
struct Port_stat portstatlist[MAX_DOWN_SLOT + 1][MaxOnu + 1][MaxOnuPort + 1]; /*端口信息统计 */
struct Profile_Data profile[MaxTemp + 1];
struct igmp_onu onulist[MAX_DOWN_SLOT + 1][MaxOnu + 1];
USHORT groupstatcount; /*组统计个数 */
USHORT recordcount; /*日志的计数 */
UCHAR RecordHolding; /*日志轮询时间 */
UCHAR RecordIgnore; /*日志忽略时间 */
UCHAR aSlotType[MAX_DOWN_SLOT + 1]; /*线卡的类型 */
UINT semtakeerror;
BOOL bUpLinkPortEnable = TRUE; /*上联口使能,为0不能级联 */
int gPortCfgResponse = 0; /*端口信息查询响应 */
int gIGMPMODE = MODE_PROXY;
/*************************************************
Function: ProcessInfoMsg
Description: process an infor message
Input: msg
Output: 无
Return: 无
Others: // 其它说明
*************************************************/
extern int auto_upload_igmplog_flag;
int ProcessInfoMsg (ConMsg msg)
{
if (msg.onu < 1 || msg.onuPort < 1 || msg.cmd > 1 || msg.state > leaveforce
|| msg.preview < 1)
{
return ERROR;
}
/*防止线卡传来预览位为0的消息 */
if (msg.preview == 0)
{
msg.preview = MEMBER_NORMAL;
}
/*加入的情况 */
if (msg.cmd == 1)
{
if (processJoinMsg (msg) != OK)
{
return ERROR;
}
}
/*离开的情况 */
else
{
if (processLeaveMsg (msg) != OK)
{
return ERROR;
}
}
/*记录日志 */
AddRecord (msg);
/*加入统计 ,只在离开时统计 */
if (msg.cmd == 0)
{
AddStatistic (msg);
}
/*在日志自动上传使能时,如果日志达到最大数时自动上传 */
if (auto_upload_igmplog_flag && recordcount >= MaxRecord)
{
upload_igmp_log ();
}
return OK;
}
int typedebug = 0;
/*************************************************
Function: processJoinMsg
Description: process a join message
Input: msg
Output: 无
Return: 正确返回0,错误返回-1
Others: // 其它说明
*************************************************/
int processJoinMsg (ConMsg msg)
{
int prestat;
int find, i, seek;
int port;
GroupInfo *ptmp;
groupMember *pMember;
GroupAuth *authgroup;
/*if it's failed join, return ok */
if (msg.state != 0)
{
return OK;
}
/*find such port in online group list, if exist,flush the oldtimer and return error, else continue */
ptmp = (GroupInfo *) GetCurGroup (msg.group);
if (ptmp && ptmp->member)
{
pMember = ptmp->member;
while (pMember)
{
if (pMember->slot == msg.slot && pMember->onu == msg.onu &&
pMember->onuPort == msg.onuPort)
{
pMember->old = 0;
return ERROR;
}
pMember = pMember->pNext;
}
}
/*check the port whether have right join the group */
/*exceed the group limit of gsw? */
if (NULL == ptmp && Totalgroup == MaxGroup)
{
msg.state = failmaxgroup;
SendForceLeaveMsg (msg.slot, msg.onu, msg.onuPort, 0, msg.group);
AddRecord (msg);
return ERROR;
}
authgroup = (GroupAuth *) GetAuthGroup (msg.group);
/*exceed the port bandwidth? */
if (portstatlist[msg.slot][msg.onu][msg.onuPort].bandwidth)
{
if (authgroup && authgroup->bandwidth)
{
if (GetCurPortBd (msg.slot, msg.onu,
msg.onuPort) + authgroup->bandwidth >
portstatlist[msg.slot][msg.onu][msg.onuPort].bandwidth)
{
/*printf ("currb =%d, gband=%d, portband=%d\r\n", GetCurPortBd(msg.slot, msg.onu, msg.onuPort), authgroup->bandwidth, portstatlist[msg.slot][msg.onu][msg.onuPort].bandwidth ); */
msg.state = failupbd;
SendForceLeaveMsg (msg.slot, msg.onu, msg.onuPort, 0,
msg.group);
AddRecord (msg);
return ERROR;
}
}
/*if (authgroup && authgroup->bandwidth
&& (portstatlist[msg.slot][msg.onu][msg.onuPort].curbd +
authgroup->bandwidth >
portstatlist[msg.slot][msg.onu][msg.onuPort].bandwidth))
{
printf ("currb =%d, gband=%d, portband=%d\r\n", portstatlist[msg.slot][msg.onu][msg.onuPort].curbd,authgroup->bandwidth, portstatlist[msg.slot][msg.onu][msg.onuPort].bandwidth );
msg.state = failupbd;
SendForceLeaveMsg (msg.slot, msg.onu, msg.onuPort, 0, msg.group);
AddRecord (msg);
return ERROR;
} */
}
/*exceed the group bandwidth? */
if (NULL == ptmp && MaxUpBandwidth)
{
if (authgroup && authgroup->bandwidth &&
(CurrentUpBandwidth + authgroup->bandwidth > MaxUpBandwidth))
{
msg.state = failupbd;
SendForceLeaveMsg (msg.slot, msg.onu, msg.onuPort, 0, msg.group);
AddRecord (msg);
return ERROR;
}
}
/*****************************add such port to group********************************************/
/*在线组不存在 */
if (NULL == ptmp)
{
ptmp = (GroupInfo *) malloc (sizeof (GroupInfo));
if (NULL == ptmp)
{
if (bConDebug)
{
printf ("malloc GroupInfo failed!\r\n");
}
return ERROR;
}
memset (ptmp, 0, sizeof (GroupInfo));
ptmp->groupaddress = msg.group;
ptmp->member = NULL;
ptmp->pNext = NULL;
ptmp->pPrv = NULL;
ptmp->totaluser = 1;
if (NULL == authgroup)
{
ptmp->auth = FALSE;
}
else
{
ptmp->auth = TRUE;
}
pMember = (groupMember *) malloc (sizeof (groupMember));
if (NULL == pMember)
{
if (bConDebug)
{
printf ("malloc pMember failed!\r\n");
}
return ERROR;
}
memset (pMember, 0, sizeof (groupMember));
pMember->slot = msg.slot;
pMember->onu = msg.onu;
pMember->onuPort = msg.onuPort;
pMember->state = msg.preview;
pMember->pNext = NULL;
pMember->pPrv = NULL;
pMember->onlinetime = 0;
pMember->old = 0;
ptmp->member = pMember;
ptmp->pNext = infolist;
if (NULL == infolist)
{
infolist = ptmp;
}
else
{
infolist->pPrv = ptmp;
infolist = ptmp;
}
Totalgroup++;
if (authgroup)
{
CurrentUpBandwidth += authgroup->bandwidth;
}
}
/*在线组已经存在 */
else
{
pMember = (groupMember *) malloc (sizeof (groupMember));
if (NULL == pMember)
{
if (bConDebug)
{
printf ("malloc pMember failed!\r\n");
}
return ERROR;
}
memset (pMember, 0, sizeof (groupMember));
pMember->slot = msg.slot;
pMember->onu = msg.onu;
pMember->onuPort = msg.onuPort;
pMember->state = msg.preview;
pMember->pNext = NULL;
pMember->pPrv = NULL;
pMember->onlinetime = 0;
pMember->old = 0;
pMember->pNext = ptmp->member;
ptmp->member->pPrv = pMember;
ptmp->member = pMember;
ptmp->totaluser++;
}
if (authgroup)
{
portstatlist[msg.slot][msg.onu][msg.onuPort].curbd +=
authgroup->bandwidth;
}
pMember = infolist->member;
return OK;
}
void free1 (groupMember * member)
{
if (member != NULL)
free (member);
return;
}
void free2 (groupMember * member)
{
if (member != NULL)
free (member);
return;
}
void free3 (groupMember * member)
{
if (member != NULL)
free (member);
return;
}
void free4 (groupMember * member)
{
if (member != NULL)
free (member);
return;
}
/*************************************************
Function: processLeaveMsg
Description: process a leave message
Input: msg
Output: 无
Return: 正确返回0,错误返回-1
Others: // 其它说明
*************************************************/
int processLeaveMsg (ConMsg msg)
{
int prestat;
int find = 0, i, seek;
int port;
GroupInfo *ptmp, *groupdel;
groupMember *pMember = NULL, *memdel, *pMember1;
GroupAuth *authgroup;
/*find such port in online group list, if dosn't exist, return ERROR, else break */
ptmp = (GroupInfo *) GetCurGroup (msg.group);
if (ptmp && ptmp->member)
{
pMember = ptmp->member;
while (pMember)
{
if (pMember->slot == msg.slot && pMember->onu == msg.onu &&
pMember->onuPort == msg.onuPort)
{
find = 1;
break;
}
pMember = pMember->pNext;
}
}
if (!find)
{
return ERROR;
}
pMember1 = infolist->member;
if (typedebug)
printf ("\r\ndelete find %x(%d:%d)\r\n", pMember, pMember->slot,
pMember->onu);
while (typedebug && pMember1)
{
printf ("---%x<-%x->%x(%d:%d)", pMember1->pPrv, pMember1,
pMember1->pNext, pMember1->slot, pMember1->onu);
pMember1 = pMember1->pNext;
}
/*del port from online group */
memdel = pMember;
authgroup = (GroupAuth *) GetAuthGroup (msg.group);
if (authgroup)
portstatlist[msg.slot][msg.onu][msg.onuPort].curbd -=
authgroup->bandwidth;
/*case single port */
if (pMember->pPrv == NULL && NULL == pMember->pNext)
{
if (authgroup)
{
authgroup->active = FALSE;
}
taskLock ();
delGroupFromOnlineList (ptmp);
taskUnlock ();
}
/*case first */
else if (pMember->pPrv == NULL && NULL != pMember->pNext)
{
ptmp->member = pMember->pNext;
ptmp->member->pPrv = NULL;
free2 (memdel);
ptmp->totaluser--;
}
/*case last */
else if (pMember->pPrv != NULL && NULL == pMember->pNext)
{
/* printf ("lastr\n"); */
pMember->pPrv->pNext = NULL;
free3 (memdel);
ptmp->totaluser--;
}
/*case middle */
else
{
/* printf ("middler\n"); */
pMember->pPrv->pNext = pMember->pNext;
pMember->pNext->pPrv = pMember->pPrv;
free4 (memdel);
ptmp->totaluser--;
}
return OK;
}
/*************************************************
Function: delGroupFromOnlineList
Description: del group node from online group list
Input: onlinegroup
Output: n/a
Return: n/a
Others: // 其它说明
*************************************************/
void delGroupFromOnlineList (GroupInfo * onlinegroup)
{
GroupAuth *authgroup;
authgroup = (GroupAuth *) GetAuthGroup (onlinegroup->groupaddress);
if (onlinegroup->member)
{
free1 (onlinegroup->member);
}
Totalgroup--;
if (authgroup)
{
if (CurrentUpBandwidth >= authgroup->bandwidth)
CurrentUpBandwidth -= authgroup->bandwidth;
else
CurrentUpBandwidth = 0;
}
/*case single port */
if (onlinegroup->pPrv == NULL && NULL == onlinegroup->pNext)
{
free (onlinegroup);
infolist = NULL;
}
/*case first */
else if (onlinegroup->pPrv == NULL && NULL != onlinegroup->pNext)
{
infolist = onlinegroup->pNext;
infolist->pPrv = NULL;
free (onlinegroup);
}
/*case last */
else if (onlinegroup->pPrv != NULL && NULL == onlinegroup->pNext)
{
onlinegroup->pPrv->pNext = NULL;
free (onlinegroup);
}
/*case middle */
else
{
onlinegroup->pPrv->pNext = onlinegroup->pNext;
onlinegroup->pNext->pPrv = onlinegroup->pPrv;
free (onlinegroup);
}
}
/*************************************************
Function: ProcessSlotChangeMsg
Description: process a slotchange message
Input: msg
Output: 无
Return: 无
Others: // 其它说明
*************************************************/
void ProcessSlotChangeMsg (ConMsg msg)
{
int i;
GroupInfo *ptmp;
groupMember *pMember;
int sem;
ptmp = infolist;
if (bConDebug)
{
if (msg.cmd == 0)
printf ("\r\n processslotchagemsg: slot %d down\r\n", msg.slot);
else
printf ("\r\n processslotchagemsg: slot %d up\r\n", msg.slot);
}
/*线卡拔出 */
if (msg.cmd == 0)
{
/*将该线卡上所有端口的信息清除 */
while (ptmp)
{
pMember = ptmp->member;
while (pMember)
{
if (pMember->slot == msg.slot)
{
SendIgmpPktbyCmd (23, ptmp->groupaddress, 0x11111, msg.slot,
1);
pMember->old = 1;
}
pMember = pMember->pNext;
}
ptmp = ptmp->pNext;
}
}
/*线卡被插上的情况 */
else
{
SendCfg2Slot (msg.slot);
}
return;
}
/*************************************************
Function: sendInfoMsgbyCmd
Description: send an info msg by cmd
Input:
Output: 无
Return: success return 0, else return -1
Others: // 其它说明
*************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -