/* * Copyright c Realsil Semiconductor Corporation, 2009 * All rights reserved. * * Program : igmp snooping function * Abstract : * Author :qinjunjie * Email:qinjunjie1980@hotmail.com * */ #if defined(CONFIG_APOLLO_ROMEDRIVER) || defined(CONFIG_XDSL_ROMEDRIVER) #ifdef __KERNEL__ #ifdef __linux__ #ifdef CONFIG_DEFAULTS_KERNEL_3_18 #else #include <linux/config.h> #endif #include <linux/jiffies.h> #include <linux/timer.h> #include <linux/proc_fs.h> #include <linux/skbuff.h> #ifdef CONFIG_PROC_FS #include <linux/seq_file.h> #endif #endif #else //model #include <stdio.h> #include <string.h> #include <mem.h> #include <stdlib.h> #endif #include <common/type.h> #include <rtk_rg_igmpsnooping.h> #include <rtk_rg_fwdEngine.h> #if defined(CONFIG_XDSL_NEW_HWNAT_DRIVER) #include <rtk_rg_xdsl_extAPI.h> #endif //static int IGMPQueryVersion = 3; //Default is using IGMP V3 to Query. //static int IGMPQuery3Length = 0; //Default is using IGMP V3 to Query. // - delete #if 0 static unsigned char igmpQueryBuf[64]={ 0 } ; #else static unsigned char *igmpQueryBuf; #endif /*igmpv3 general query, 50*/ static unsigned char igmpQueryBufV3[64]={ 0x01,0x00,0x5e,0x00,0x00,0x01, /*destination mac*/ 0x00,0x00,0x00,0x00,0x00,0x00, /*offset:6*/ 0x08,0x00, /*offset:12*/ 0x46,0x00,0x00,0x24, /*offset:14*/ //0x46,0x00,0x00,0x28, /*offset:14*/ 0x00,0x00,0x40,0x00, /*offset:18*/ 0x01,0x02,0x00,0x00, /*offset:22*/ 0x00,0x00,0x00,0x00, /*offset:26,source ip*/ 0xe0,0x00,0x00,0x01, /*offset:30,destination ip*/ 0x94,0x04,0x00,0x00, /*offset:34,router alert option*/ 0x11,0x64,0x00,0x00, /*offset:38,max response time*/ 0x00,0x00,0x00,0x00, /*offset:42,queried multicast ip address*/ 0x0a,0x3c,0x00,0x00, /*offset:46*/ 0x00,0x00,0x00,0x00, /*offset:50*/ 0x00,0x00,0x00,0x00, /*offset:54*/ 0x00,0x00,0x00,0x00, /*offset:58*/ 0x00,0x00 /*offset:62*/ //0x00,0x00,0x00,0x00 /*offset:62*/ }; #if 1 /* max source is about 243, skb no considerate CRC */ #define IGMPV3_QUERY_SOURCE_MAX_NO ((1024 - 52)>>2) #define IGMPV3_QUERY_SOURCE_MIN_NO ((64 - 52)>>2) #define IGMPV3_QUERY_MAX_SIZE ((IGMPV3_QUERY_SOURCE_MAX_NO<<2) + 52) #else /* max source is about 242*/ #define IGMPV3_QUERY_SOURCE_MAX_NO ((1024 - 50 - 4)>>2) #define IGMPV3_QUERY_SOURCE_MIN_NO ((1024 - 50)>>2) #define IGMPV3_QUERY_MAX_SIZE ((IGMPV3_QUERY_SOURCE_MAX_NO<<2) + 50 + 4) #endif /*igmpv2 general query, 42*/ static unsigned char igmpQueryBufV2[64]={ 0x01,0x00,0x5e,0x00,0x00,0x01, /*destination mac*/ 0x00,0x00,0x00,0x00,0x00,0x00, /*offset:6*/ 0x08,0x00, /*offset:12*/ 0x45,0x00,0x00,0x1c, /*offset:14*/ 0x00,0x00,0x40,0x00, /*offset:18*/ 0x01,0x02,0x00,0x00, /*offset:22*/ 0x00,0x00,0x00,0x00, /*offset:26*/ 0xe0,0x00,0x00,0x01, /*offset:30*/ 0x11,0x64,0x0c,0xfa, /*offset:34,max response time*/ 0x00,0x00,0x00,0x00, /*offset:38*/ 0x00,0x00,0x00,0x00, /*offset:42*/ 0x00,0x00,0x00,0x00, /*offset:46*/ 0x00,0x00,0x00,0x00, /*offset:50*/ 0x00,0x00,0x00,0x00, /*offset:54*/ 0x00,0x00,0x00,0x00, /*offset:58*/ 0x00,0x00 /*offset:62*/ }; static unsigned char mldQueryBuf[86]={ 0x33,0x33,0x00,0x00,0x00,0x01, /*destination mac*/ 0x00,0x00,0x00,0x00,0x00,0x00, /*source mac*/ /*offset:6*/ 0x86,0xdd, /*ether type*/ /*offset:12*/ 0x60,0x00,0x00,0x00, /*version(1 byte)-traffic cliass(1 byte)- flow label(2 bytes)*/ /*offset:14*/ 0x00,0x20,0x00,0x01, /*payload length(2 bytes)-next header(1 byte)-hop limit(value:1 1byte)*//*offset:18*/ 0xfe,0x80,0x00,0x00, /*source address*/ /*offset:22*/ 0x00,0x00,0x00,0x00, /*be zero*/ /*offset:26*/ 0x00,0x00,0x00, /*upper 3 bytes mac address |0x02*/ /*offset:30*/ 0xff,0xfe, /*fixed*/ 0x00,0x00,0x00, /*lowert 3 bytes mac address*/ /*offset:35*/ 0xff,0x02,0x00,0x00, /*destination address is fixed as FF02::1*/ /*offset:38*/ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0x3a,0x00, /*icmp type(1 byte)-length(1 byte)*/ /*offset:54*/ 0x05,0x02,0x00,0x00, /*router alert option*/ 0x01,0x00, /*padN*/ 0x82,0x00, /*type(query:0x82)-code(0)*/ /*offset:62*/ 0x00,0x00, /*checksum*/ /*offset:64*/ 0x00,0x0a, /*maximum reponse code*/ 0x00,0x00, /*reserved*/ 0x00,0x00,0x00,0x00, /*multicast address,fixed as 0*/ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 }; static unsigned char ipv6PseudoHdrBuf[40]={ 0xfe,0x80,0x00,0x00, /*source address*/ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xff, 0xfe,0x00,0x00,0x00, 0xff,0x02,0x00,0x00, /*destination address*/ 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x18, /*upper layer packet length*/ 0x00,0x00,0x00,0x3a /*zero padding(3 bytes)-next header(1 byte)*/ }; struct rtl_multicastModule rtl_mCastModuleArray[MAX_MCAST_MODULE_NUM]; //#if 0 #if defined(__linux__) && defined(__KERNEL__) struct timer_list igmpSysTimer; /*igmp timer*/ struct timer_list mCastQuerytimer; /*igmp query timer*/ struct timer_list mCastForceReporttimer; /*igmp mld force response timer*/ #endif #if 0 #define NMAC(addr) \ ((unsigned char *)addr)[0], \ ((unsigned char *)addr)[1], \ ((unsigned char *)addr)[2], \ ((unsigned char *)addr)[3], \ ((unsigned char *)addr)[4], \ ((unsigned char *)addr)[5] #define SF_MACH "%02X:%02X:%02X:%02X:%02X:%02X" #define SF_IP4D "%d.%d.%d.%d" #define SF_IP4H "%X:%X:%X:%X" #define SF_IP6D IP4D" "IP4D" "IP4D" "IP4D #define SF_IP6H IP4H" "IP4H" "IP4H" "IP4H #endif #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] #define NIP4QUAD(addr) \ NIPQUAD((addr[0])) //NIPQUAD((addr)) #define NIP6QUAD(addr) \ NIPQUAD((addr[0])), \ NIPQUAD((addr[1])), \ NIPQUAD((addr[2])), \ NIPQUAD((addr[3])) #define NMACQUAD(addr) \ ((unsigned char *)addr)[0], \ ((unsigned char *)addr)[1], \ ((unsigned char *)addr)[2], \ ((unsigned char *)addr)[3], \ ((unsigned char *)addr)[4], \ ((unsigned char *)addr)[5] #define MACH "%02X:%02X:%02X:%02X:%02X:%02X" #define IP4D "%d.%d.%d.%d" #define IP4H "%X:%X:%X:%X" #define IP6D IP4D" "IP4D" "IP4D" "IP4D #define IP6H IP4H" "IP4H" "IP4H" "IP4H /*global system resources declaration*/ static uint32 rtl_totalMaxGroupCnt; /*maximum total group entry count, default is 100*/ static uint32 rtl_totalMaxClientCnt; /*maximum total group entry count, default is 100*/ static uint32 rtl_totalMaxSourceCnt; /*maximum total group entry count, default is 300*/ void *rtl_groupMemory=NULL; void *rtl_clientMemory=NULL; void *rtl_sourceMemory=NULL; void *rtl_mcastFlowMemory=NULL; //static int igmpsnoopenabled=1; //static int mldSnoopEnabled=1; static uint32 igmpSnoopingCounterVer_Port[RTK_RG_MAX_MAC_PORT][IGMP_MLD_VER_MAX]; #ifdef CONFIG_MASTER_WLAN0_ENABLE static uint32 igmpSnoopingCounterVer_MBSSID[MAX_WLAN_DEVICE_NUM][IGMP_MLD_VER_MAX]; #endif static uint8 igmpSnoopingCounterVer_1=0; ////: add static uint8 igmpSnoopingCounterVer_2=0; static uint8 igmpSnoopingCounterVer_3=0; static uint8 MLDCounterVer_1=0; static uint8 MLDCounterVer_2=0; static struct rtl_groupEntry *rtl_groupEntryPool=NULL; static struct rtl_clientEntry *rtl_clientEntryPool=NULL; static struct rtl_sourceEntry *rtl_sourceEntryPool=NULL; #ifdef CONFIG_RECORD_MCAST_FLOW static struct rtl_mcastFlowEntry *rtl_mcastFlowEntryPool=NULL; #endif struct rtl_mCastTimerParameters rtl_mCastTimerParas; /*IGMP snooping parameters */ static uint32 rtl_hashTableSize=0; static uint32 rtl_hashMask=0; static uint32 system_expire_type; /*the system up time*/ static uint32 rtl_startTime; static uint32 rtl_sysUpSeconds; static unsigned long int last_query_jiffies; /*record the system jiffie of last query send*/ static rtl_multicastEventContext_t reportEventContext; static rtl_multicastEventContext_t timerEventContext; #if defined (CONFIG_RG_HARDWARE_MULTICAST) static rtl_multicastEventContext_t linkEventContext; int rtl_handle_igmpgroup_change(rtl_multicastEventContext_t* param); #ifdef CONFIG_RG_SIMPLE_IGMP_v3 int rtl_handle_igmpgroup_change_v3(rtl_multicastEventContext_t* param); #endif struct list_head rtl_multicast_index_mapping_listhead; struct list_head hwMappingEntryFreeListHead; rtl_multicast_index_mapping_t hwMappingEntry[DEFAULT_MAX_HW_MAPPING_COUNT]; #endif /*******************************internal function declaration*****************************/ /************************** resource managment **************************/ static struct rtl_groupEntry* rtl_initGroupEntryPool(uint32 poolSize); static struct rtl_groupEntry* rtl_allocateGroupEntry(void); static void rtl_freeGroupEntry(struct rtl_groupEntry* groupEntryPtr) ; static struct rtl_clientEntry* rtl_initClientEntryPool(uint32 poolSize); static struct rtl_clientEntry* rtl_allocateClientEntry(void); static void rtl_freeClientEntry(struct rtl_clientEntry* clientEntryPtr) ; static struct rtl_sourceEntry* rtl_initSourceEntryPool(uint32 poolSize); static struct rtl_sourceEntry* rtl_allocateSourceEntry(void); static void rtl_freeSourceEntry(struct rtl_sourceEntry* sourceEntryPtr) ; #ifdef CONFIG_RECORD_MCAST_FLOW static struct rtl_mcastFlowEntry* rtl_initMcastFlowEntryPool(uint32 poolSize); static struct rtl_mcastFlowEntry* rtl_allocateMcastFlowEntry(void); static void rtl_freeMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry) ; #endif /**********************************Structure Maintenance*************************/ static struct rtl_groupEntry* rtl_searchGroupEntry(uint32 moduleIndex, uint32 ipVersion,uint32 *multicastAddr, uint16 vlanId); static void rtl_linkGroupEntry(struct rtl_groupEntry* entryNode , struct rtl_groupEntry ** hashTable); static void rtl_unlinkGroupEntry(struct rtl_groupEntry* entryNode, struct rtl_groupEntry ** hashTable); static void rtl_clearGroupEntry(struct rtl_groupEntry* groupEntryPtr); static struct rtl_clientEntry* rtl_searchClientEntry(uint32 ipVersion,struct rtl_groupEntry* groupEntry, uint32 portNum, uint32 *clientAddr); static void rtl_linkClientEntry(struct rtl_groupEntry *groupEntry, struct rtl_clientEntry* clientEntry); static void rtl_unlinkClientEntry(struct rtl_groupEntry *groupEntry, struct rtl_clientEntry* clientEntry); static void rtl_clearClientEntry(struct rtl_clientEntry* clientEntryPtr); static void rtl_deleteClientEntry(struct rtl_groupEntry * groupEntry, struct rtl_clientEntry * clientEntry); static struct rtl_sourceEntry* rtl_searchSourceEntry(uint32 ipVersion, uint32 *sourceAddr, struct rtl_clientEntry *clientEntry); static void rtl_linkSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* entryNode); static void rtl_unlinkSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* entryNode); static void rtl_clearSourceEntry(struct rtl_sourceEntry* sourceEntryPtr); static void rtl_deleteSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* sourceEntry); #ifdef CONFIG_RECORD_MCAST_FLOW static struct rtl_mcastFlowEntry* rtl_searchMcastFlowEntry(uint32 moduleIndex, uint32 ipVersion, uint32 *serverAddr,uint32 *groupAddr); static void rtl_linkMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry , struct rtl_mcastFlowEntry ** hashTable); static void rtl_unlinkMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry, struct rtl_mcastFlowEntry ** hashTable); static void rtl_clearMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry); static void rtl_deleteMcastFlowEntry( struct rtl_mcastFlowEntry* mcastFlowEntry, struct rtl_mcastFlowEntry ** hashTable); #endif //static int32 rtl_checkMCastAddrMapping(uint32 ipVersion, uint32 *ipAddr, uint8* macAddr); #ifdef CONFIG_RG_MLD_SNOOPING //static int32 rtl_compareIpv6Addr(uint32* ipv6Addr1, uint32* ipv6Addr2); static uint16 rtl_ipv6L3Checksum(uint8 *pktBuf, uint32 pktLen, union pseudoHeader *ipv6PseudoHdr); #endif //static int32 rtl_compareMacAddr(uint8* macAddr1, uint8* macAddr2); static uint16 rtl_checksum(uint8 *packetBuf, uint32 packetLen); // Mason Yu. type error //static uint8 rtl_getClientFwdPortMask(struct rtl_clientEntry * clientEntry, uint32 sysTime); static uint32 rtl_getClientFwdPortMask(struct rtl_clientEntry * clientEntry, uint32 sysTime); static void rtl_checkSourceTimer(struct rtl_clientEntry * clientEntry , struct rtl_sourceEntry * sourceEntry); #if 0 static uint32 rtl_getGroupSourceFwdPortMask(struct rtl_groupEntry * groupEntry, uint32 * sourceAddr, uint32 sysTime); static uint32 rtl_getClientSourceFwdPortMask(uint32 ipVersion, struct rtl_clientEntry * clientEntry, uint32 * sourceAddr, uint32 sysTime); #endif static void rtl_checkGroupEntryTimer(struct rtl_groupEntry * groupEntry, struct rtl_groupEntry ** hashTable); static void rtl_checkClientEntryTimer(struct rtl_groupEntry * groupEntry, struct rtl_clientEntry * clientEntry); static uint32 rtl_getMulticastRouterPortMask(uint32 moduleIndex, uint32 ipVersion, uint32 sysTime); /*hash table operation*/ static int32 rtl_initHashTable(uint32 moduleIndex, uint32 hashTableSize); /************************************Pkt Process**********************************/ /*MAC frame analyze function*/ static void rtl_parseMacFrame(uint32 moduleIndex, uint8* MacFrame, rtk_rg_pktHdr_t *pPktHdr, uint32 verifyCheckSum, struct rtl_macFrameInfo* macInfo); /*Process Query Packet*/ static void rtl_snoopQuerier(uint32 moduleIndex, uint32 ipVersion, uint32 portNum); static uint32 rtl_processQueries(uint32 moduleIndex, rtk_rg_pktHdr_t *pPktHdr, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint8* pktBuf, uint32 pktLen); /*Process Report Packet*/ static uint32 rtl_processJoin(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); // process join report packet static uint32 rtl_processLeave(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process leave/done report packet static int32 rtl_processIsInclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process MODE_IS_INCLUDE report packet static int32 rtl_processIsExclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process MODE_IS_EXCLUDE report packet static int32 rtl_processToInclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process CHANGE_TO_INCLUDE_MODE report packet static int32 rtl_processToExclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process CHANGE_TO_EXCLUDE_MODE report packet static int32 rtl_processAllow(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); //process ALLOW_NEW_SOURCES report packet static int32 rtl_processBlock(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf);//process BLOCK_OLD_SOURCES report packet static uint32 rtl_processIgmpv3Mldv2Reports(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf); /*******************different protocol process function**********************************/ static uint32 rtl_processIgmpMld(uint32 moduleIndex, rtk_rg_pktHdr_t *pPktHdr, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8* pktBuf, uint32 pktLen); static uint32 rtl_processDvmrp(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen); static uint32 rtl_processMospf(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen); static uint32 rtl_processPim(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen); #ifdef CONFIG_RECORD_MCAST_FLOW static int32 rtl_recordMcastFlow(uint32 moduleIndex,uint32 ipVersion, uint32 *sourceIpAddr, uint32 *groupAddr, struct rtl_multicastFwdInfo * multicastFwdInfo); static void rtl_invalidateMCastFlow(uint32 moduleIndex,uint32 ipVersion, uint32 *groupAddr); static void rtl_doMcastFlowRecycle(uint32 moduleIndex,uint32 ipVersion); #endif #if defined(__linux__) && defined(__KERNEL__) void rtl_multicastSysTimerExpired(uint32 expireDada); void rtl_multicastSysTimerInit(void); static void rtl_multicastSysTimerDestroy(void); #endif static void rtl_deleteGroupEntry( struct rtl_groupEntry* groupEntry,struct rtl_groupEntry ** hashTable); /************************************************ Implementation ************************************************/ /************************** Initialize **************************/ static unsigned long lastjiffies=0; static uint32 lastTimer=0; //start for 0 sec uint32 rtk_rg_getTimeSec(void) { int32 jiffiesDiff; if(jiffies > lastjiffies) jiffiesDiff =jiffies-lastjiffies; else jiffiesDiff =(0xffffffff-(lastjiffies-jiffies)); lastjiffies=jiffies; lastTimer +=(jiffiesDiff/CONFIG_HZ); return lastTimer; } static unsigned short rtl_ipv4Checksum(unsigned char *pktBuf, unsigned int pktLen) { /*note: the first bytes of packetBuf should be two bytes aligned*/ unsigned int checksum=0; unsigned int count=pktLen; unsigned short *ptr= (unsigned short *)pktBuf; while(count>1) { checksum+= ntohs(*ptr); ptr++; count -= 2; } if(count>0) { checksum+= *(pktBuf+pktLen-1)<<8; /*the last odd byte is treated as bit 15~8 of unsigned short*/ } /* Roll over carry bits */ checksum = (checksum >> 16) + (checksum & 0xffff); checksum += (checksum >> 16); /* Return checksum */ return ((unsigned short) ~ checksum); } #if 0 static unsigned char* rtl_generateIgmpQuery(char *src_mac,char *src_ip) #else static unsigned char* rtl_generateIgmpQuery(char *src_mac, char *src_ip, int igmp_ver, char* grp, int no_src, struct rtl_sourceEntry *src_ent, char * src_list, const int q3_len) #endif { unsigned short checkSum=0; //unsigned char xmac[] ={ 0x00, 0x00, 0x00, 0x00, 0x09, 0x09 }; //unsigned char xip[] ={ 0xc0, 0xa8, 0x09, 0x09 }; //unsigned char xgip[] ={ 0xea, 0xea, 0xea, 0xea }; //234.234.234.234 /* unsigned char s1[] ={0x9, 0x8, 0x7, 0x6}; //9.8.7.6 unsigned char s2[] ={0x5, 0x4, 0x3, 0x2}; //5.4.3.2 unsigned char *s[] ={s1,s2}; */ //unsigned char s[][]= { {0x9, 0x8, 0x7, 0x6}, {0x5, 0x4, 0x3, 0x2} }; //5.4.3.2 //unsigned char *s[]= { {0x9, 0x8, 0x7, 0x6}, {0x5, 0x4, 0x3, 0x2} }; //5.4.3.2 //unsigned char s[2][4]={ {0x9, 0x8, 0x7, 0x6}, {0x5, 0x4, 0x3, 0x2} }; //5.4.3.2 //unsigned char s[]={ 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2 }; //9.8.7.6, 5.4.3.2, //src_mac = { 0x00, 0x00, 0x00, 0x00, 0x09, 0x09 }; compile error //src_mac = (unsigned char *) { 0x00, 0x00, 0x00, 0x00, 0x09, 0x09 }; excess elements in scalar initializer //src_mac = xmac; //src_mac = (unsigned char []) { 0x00, 0x00, 0x00, 0x00, 0x09, 0x09 }; #if 0 if (IGMPQueryVersion == 3) memcpy(igmpQueryBuf,igmpQueryBufV3,64); else memcpy(igmpQueryBuf,igmpQueryBufV2,64); #else //IGMPQuery3Length = 0x0; //if (IGMPQueryVersion == 3) if (igmp_ver==IGMP_V3) { #if 0 /* src_mac = "000000000909"; src_ip = "c0a80909"; grp = "eaeaeaea"; //234.234.234.234 no_src= 0; src_list= NULL; src_mac = "\0\0\0\0\0\0\0\0\0\9\0\9"; src_ip = "\c\0\a\8\0\9\0\9"; grp = "\e\a\e\a\e\a\e\a"; //234.234.234.234 no_src= 0; src_list= NULL; */ /* src_mac = (unsigned char*) { 0x00, 0x00, 0x00, 0x00, 0x09, 0x09 }; src_ip = (unsigned char*) { 0xc0, 0xa8, 0x09, 0x09 }; grp = (unsigned char*) { 0xea, 0xea, 0xea, 0xea };//234.234.234.234 no_src= 0; src_list= NULL; */ //src_mac = xmac; //src_ip = xip; grp = xgip;//234.234.234.234 no_src= 0; src_list= NULL; /* src_mac = "\0\0\0\0\011\011"; src_ip = "\c\0\a\8\0\9\0\9"; grp = "\e\a\e\a\e\a\e\a"; //234.234.234.234 no_src= 0; src_list= NULL; */ #else /* src_mac = "000000000808"; src_ip = "c0a80808"; grp = "eaeaeaea"; no_src=1; //src_list= "c0a0404"; src_list= {"c0a0404"}; */ /* grp = xgip;//234.234.234.234 no_src= 2; src_list= s; */ #endif memcpy(igmpQueryBuf, igmpQueryBufV3, 64); if (grp != NULL) { memcpy(&igmpQueryBuf[42],grp,4); /*set group IP address*/ if (no_src>=0) { unsigned int i; #if 0 /*if (no_src==0) { igmpQueryBuf[17]=0x24; } else*/ if (no_src<=3) { //igmpQueryBuf[17] = 0x24+ (no_src<<2); } else //(no_src>=3) { no_src=3; igmpQueryBuf[17]=0x30; WARN("Error: overflow, 3 source only"); } #else #if 0 if (no_src >= 3) //(64 - 50) div 4 = 3, no considerate CRC { no_src=3; WARN("Error: overflow, accept 3 sources only"); } IGMPQuery3Length = (no_src<<2); #endif //i = 0x24 + q3_len; //20 + 4 + 12 = 36 =0x24 i = 36 + (no_src<<2); //20 + 4 + 12 = 36 =0x24 igmpQueryBuf[16]= i >> 8; igmpQueryBuf[17]= i & 0xff; #endif igmpQueryBuf[48]= no_src >> 8; igmpQueryBuf[49]= no_src & 0xff; if (src_ent!=NULL) { i = 0; do { if (src_ent->setOpFlag) { memcpy(&igmpQueryBuf[50 + (i<<2)], src_ent->sourceAddr, 4); src_ent->setOpFlag=0; i++; } src_ent = src_ent->next; } while (src_ent!=NULL); //} while (src_ent!=NULL && i<no_src); } else { for (i=0;i<no_src;i++) { /* if (src_list[no_src]!=NULL) { memcpy(&igmpQueryBuf[50], &src_list[no_src], 4); //50~53, 54~57, 58~61, 62~65 } else { WARN("Error: NULL string"); } */ //memcpy(&igmpQueryBuf[50 + (i<<2)], &s[(i<<2)], 4); //50~53, 54~57, 58~61, 62~65 memcpy(&igmpQueryBuf[50 + (i<<2)], &src_list[(i<<2)], 4); //50~53, 54~57, 58~61, 62~65 } } } //no_src > 0 } } else //igmp_ver is IGMP_V1 or IGMP_V2 { memcpy(igmpQueryBuf,igmpQueryBufV2,64); if (grp != NULL) { memcpy(&igmpQueryBuf[38],grp,4); /*set group IP address*/ } } #endif memcpy(&igmpQueryBuf[6],src_mac,6); /*set source mac address*/ memcpy(&igmpQueryBuf[26],src_ip,4); /*set source IP address*/ igmpQueryBuf[24]=0; igmpQueryBuf[25]=0; //if (IGMPQueryVersion == 3) if (igmp_ver==IGMP_V3) checkSum=rtl_ipv4Checksum(&igmpQueryBuf[14],24); else checkSum=rtl_ipv4Checksum(&igmpQueryBuf[14],20); igmpQueryBuf[24]=(checkSum&0xff00)>>8; igmpQueryBuf[25]=(checkSum&0x00ff); //if (IGMPQueryVersion == 3) if (igmp_ver==IGMP_V3) { igmpQueryBuf[40]=0; igmpQueryBuf[41]=0; //checkSum=rtl_ipv4Checksum(&igmpQueryBuf[38],12); //checkSum=rtl_ipv4Checksum(&igmpQueryBuf[38],12 + IGMPQuery3Length); //checkSum=rtl_ipv4Checksum(&igmpQueryBuf[38],12 + q3_len); checkSum=rtl_ipv4Checksum(&igmpQueryBuf[38],12 + (no_src<<2)); igmpQueryBuf[40]=(checkSum&0xff00)>>8; igmpQueryBuf[41]=(checkSum&0x00ff); } else { igmpQueryBuf[36]=0; igmpQueryBuf[37]=0; checkSum=rtl_ipv4Checksum(&igmpQueryBuf[34],8); igmpQueryBuf[36]=(checkSum&0xff00)>>8; igmpQueryBuf[37]=(checkSum&0x00ff); } return igmpQueryBuf; } #ifdef __KERNEL__ /* arg: 0, gen query after accessing report 1, gen query as Timer expired */ #if 0 static void rtl_igmpQueryTimerExpired(unsigned long arg) #else static void rtl_igmpQueryTimerExpired(unsigned long arg, int igmp_ver, char *grp, int no_src, struct rtl_sourceEntry *src_ent, char *src_list) //static void rtl_igmpQueryTimerExpired(unsigned long arg, int igmp_ver, char *grp, struct rtl_clientEntry *clt_ent, int no_src, char *src_list) #endif { struct sk_buff *skb; int i,rg_fwdengine_ret_code=0; int q3_len = 0; //int tmp_intf_vlan_id; rg_kernel.tracefilterShow =0; //disable tracefilter show skb=(struct sk_buff *)_rtk_rg_getAlloc(1024); //call fwdEngineInput, the alloc counter will be added. so don't need to add again if ((skb)&&(rg_db.systemGlobal.fwdStatistic)) { #if RTK_RG_SKB_PREALLOCATE rg_db.systemGlobal.statistic.perPortCnt_skb_pre_alloc_for_uc[rg_db.pktHdr->ingressPort]--; #else rg_db.systemGlobal.statistic.perPortCnt_skb_alloc[rg_db.pktHdr->ingressPort]--; #endif } if (skb==NULL) { WARNING("Error: skb null"); return; } /**send packet***/ #if 0 if (rg_db.systemGlobal.lanIntfTotalNum<=0) { DEBUG("No any LAN Interfaces for sending igmp-query"); }else{ DEBUG("It has LAN %d Interface(s) for sending igmp-query", rg_db.systemGlobal.lanIntfTotalNum); } #endif DEBUG("lanIntfTotalNum=%d\n",rg_db.systemGlobal.lanIntfTotalNum); //tmp_intf_vlan_id = rg_kernel.rxInfoFromIGMPMLD.rx_cvlan_tag; for (i=0;i<rg_db.systemGlobal.lanIntfTotalNum;i++) { #if 0 unsigned char *igmpBuf=NULL; bzero((void*)skb->data,64); igmpBuf=rtl_generateIgmpQuery(rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->gmac.octet,(char *)&rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->ip_addr, NULL, 0, NULL); if (igmpBuf==NULL) { return; } memcpy(skb->data,igmpBuf,64); #else //if (IGMPQueryVersion==3) if (igmp_ver==IGMP_V3) { if (no_src > IGMPV3_QUERY_SOURCE_MAX_NO) { q3_len = IGMPV3_QUERY_MAX_SIZE; no_src = IGMPV3_QUERY_SOURCE_MAX_NO; } #if 0 else if (no_src <= IGMPV3_QUERY_SOURCE_MIN_NO) // <= 3 { q3_len = 64; } #endif else // >= 4 { q3_len = (no_src<<2) + 50;//14+24+12 //q3_len = (no_src<<2) + 12; } bzero((void*)skb->data, q3_len); } else //igmp query 1 or 2 { q3_len=0; bzero((void*)skb->data, 64); } igmpQueryBuf = skb->data; rtl_generateIgmpQuery(rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->gmac.octet,(char *)&rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->ip_addr, igmp_ver, grp, no_src, src_ent, src_list, q3_len); #endif skb->len = 0; //if (IGMPQueryVersion==3) if (igmp_ver==IGMP_V3) { //skb_put(skb, 50); //0 serverip //skb_put(skb, 50 + IGMPQuery3Length); //N serverip skb_put(skb, q3_len); //N serverip }else skb_put(skb, 42); rg_db.pktHdr=&rg_db.systemGlobal.pktHeader_2; rg_kernel.rxInfoFromIGMPMLD.rx_cvlan_tag=rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->intf_vlan_id; if (_rtk_rg_get_initState()==RTK_RG_INIT_FINISHED) { rg_db.pktHdr->IGMPQueryVer = igmp_ver; //IGMP_V1, IGMP_V2, IGMP_V3, rg_fwdengine_ret_code = rtk_rg_fwdEngineInput(NULL,skb,(void*)&rg_kernel.rxInfoFromIGMPMLD); //Processing packets if (rg_fwdengine_ret_code == RG_FWDENGINE_RET_TO_PS) { //FIXME:iPhone 5 change wireless connection from master to slave will send strange unicast ARP request for LAN gateway IP, and forwarded by protocol stack IGMP("IGMP_TX_O[%x]: To Protocol-Stack...FREE SKB!!\n",(unsigned int)skb&0xffff); //dump_packet(skb->data,skb->len,"dump_back_to_PS"); } else if (rg_fwdengine_ret_code == RG_FWDENGINE_RET_DROP) { IGMP("IGMP_TX_O[%x]: Drop...FREE SKB!!\n",(unsigned int)skb&0xffff); } else { IGMP("IGMP_TX_O[%x]: strange return value %d....\n",(unsigned int)skb&0xffff,rg_fwdengine_ret_code); } } rg_db.pktHdr=&rg_db.systemGlobal.pktHeader_1; } //rg_kernel.rxInfoFromIGMPMLD.rx_cvlan_tag = tmp_intf_vlan_id; _rtk_rg_dev_kfree_skb_any(skb); } static unsigned short rtl_ipv6Checksum(unsigned char *pktBuf, unsigned int pktLen, unsigned char *ipv6PseudoHdrBuf) { unsigned int checksum=0; unsigned int count=pktLen; unsigned short *ptr; /*compute ipv6 pseudo-header checksum*/ ptr= (unsigned short *) (ipv6PseudoHdrBuf); for(count=0; count<20; count++) /*the pseudo header is 40 bytes long*/ { checksum+= ntohs(*ptr); ptr++; } /*compute the checksum of mld buffer*/ count=pktLen; ptr=(unsigned short *) (pktBuf); while(count>1) { checksum+= ntohs(*ptr); ptr++; count -= 2; } if(count>0) { checksum+= *(pktBuf+pktLen-1)<<8; /*the last odd byte is treated as bit 15~8 of unsigned short*/ } /* Roll over carry bits */ checksum = (checksum >> 16) + (checksum & 0xffff); checksum += (checksum >> 16); /* Return checksum */ return ((uint16) ~ checksum); } static unsigned char* rtl_generateMldQuery(char *src_mac) { unsigned short checkSum=0; memcpy(&mldQueryBuf[6],src_mac,6); /*set source mac address*/ memcpy(&mldQueryBuf[30],src_mac,3); /*set mld query packet source ip address*/ mldQueryBuf[30]=mldQueryBuf[30]|0x02; memcpy(&mldQueryBuf[35],&src_mac[3],3); memcpy(ipv6PseudoHdrBuf,&mldQueryBuf[22],16); /*set pseudo-header source ip*/ mldQueryBuf[64]=0;/*reset checksum*/ mldQueryBuf[65]=0; checkSum=rtl_ipv6Checksum(&mldQueryBuf[62],24,ipv6PseudoHdrBuf); mldQueryBuf[64]=(checkSum&0xff00)>>8; mldQueryBuf[65]=(checkSum&0x00ff); return mldQueryBuf; } void rtl_mldQueryTimerExpired(unsigned long arg) { struct sk_buff *skb; unsigned char *mldBuf=NULL; int i,rg_fwdengine_ret_code; skb=(struct sk_buff *)_rtk_rg_getAlloc(1024); //call fwdEngineInput, the alloc counter will be added. so don't need to add again if((skb)&&(rg_db.systemGlobal.fwdStatistic)) { #if RTK_RG_SKB_PREALLOCATE rg_db.systemGlobal.statistic.perPortCnt_skb_pre_alloc_for_uc[rg_db.pktHdr->ingressPort]--; #else rg_db.systemGlobal.statistic.perPortCnt_skb_alloc[rg_db.pktHdr->ingressPort]--; #endif } if(skb==NULL) return; /**send packet***/ for(i=0;i<rg_db.systemGlobal.lanIntfTotalNum;i++) { bzero((void*)skb->data,86); mldBuf=rtl_generateMldQuery(rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->gmac.octet); if(mldBuf==NULL) return; memcpy(skb->data,mldBuf,86); skb->len = 0; skb_put(skb, 86); rg_kernel.rxInfoFromIGMPMLD.rx_cvlan_tag=rg_db.systemGlobal.lanIntfGroup[i].p_intfInfo->p_lanIntfConf->intf_vlan_id; if(_rtk_rg_get_initState()==RTK_RG_INIT_FINISHED) { rg_fwdengine_ret_code = rtk_rg_fwdEngineInput(NULL,skb,(void*)&rg_kernel.rxInfoFromIGMPMLD); //Processing packets if(rg_fwdengine_ret_code == RG_FWDENGINE_RET_TO_PS) { //FIXME:iPhone 5 change wireless connection from master to slave will send strange unicast ARP request for LAN gateway IP, and forwarded by protocol stack IGMP("MLD_TX_O[%x]: To Protocol-Stack...FREE SKB!!\n",(unsigned int)skb&0xffff); //dump_packet(skb->data,skb->len,"dump_back_to_PS"); } else if (rg_fwdengine_ret_code == RG_FWDENGINE_RET_DROP) { IGMP("MLD_TX_O[%x]: Drop...FREE SKB!!\n",(unsigned int)skb&0xffff); } else { IGMP("MLD_TX_O[%x]: strange return value %d....\n",(unsigned int)skb&0xffff,rg_fwdengine_ret_code); } } } _rtk_rg_dev_kfree_skb_any(skb); } #endif static unsigned int mCastQueryTimerCnt=0; void rtl_mCastQueryTimerExpired(unsigned long arg) { //printk("[Timer rtl_mCastQueryTimerExpired]\n"); //struct net_bridge *br = (struct net_bridge*) arg; //extern unsigned int debug_enable; #if 0 //fix iterative send IGMPv2 query, IGMPv3 query to send both at the same time. #ifdef __KERNEL__ mod_timer(&mCastQuerytimer, jiffies+rg_db.systemGlobal.mcast_query_sec*CONFIG_HZ); if(mCastQueryTimerCnt%2==0) { //If previous send igmpV3, and we have v2 client, send v2 query once! if(IGMPQueryVersion==3 && igmpSnoopingCounterVer_2>0) IGMPQueryVersion=2; else //otherwise, just send v3 query IGMPQueryVersion=3; if(rg_db.systemGlobal.multicastProtocol!=RG_MC_MLD_ONLY) rtl_igmpQueryTimerExpired(arg); } else { #if defined (CONFIG_RG_MLD_SNOOPING) if(rg_db.systemGlobal.multicastProtocol!=RG_MC_IGMP_ONLY) rtl_mldQueryTimerExpired(arg); #endif } mCastQueryTimerCnt++; #endif #else #ifdef __KERNEL__ IGMP("QueryTimerExpired\n"); if (rg_db.systemGlobal.mcast_query_sec!=0) { mod_timer(&mCastQuerytimer, jiffies+rg_db.systemGlobal.mcast_query_sec*CONFIG_HZ); } last_query_jiffies = jiffies; if (rg_db.systemGlobal.multicastProtocol!=RG_MC_MLD_ONLY){//send IGMP query if (igmpSnoopingCounterVer_3>0){ #if 0 IGMPQueryVersion=3; rtl_igmpQueryTimerExpired(arg); #else rtl_igmpQueryTimerExpired(arg, IGMP_V3, NULL, 0, NULL, NULL); #endif IGMP("System send Query(IGMPv3), last_query_jiffies=%lu",last_query_jiffies); } if (igmpSnoopingCounterVer_2>0){ #if 0 IGMPQueryVersion=2; rtl_igmpQueryTimerExpired(arg); #else rtl_igmpQueryTimerExpired(arg, IGMP_V2, NULL, 0, NULL, NULL); #endif IGMP("System send Query(IGMPv2), last_query_jiffies=%lu",last_query_jiffies); } if (igmpSnoopingCounterVer_1>0){ ////++ #if 0 IGMPQueryVersion=1; rtl_igmpQueryTimerExpired(arg); #else rtl_igmpQueryTimerExpired(arg, IGMP_V1, NULL, 0, NULL, NULL); #endif IGMP("System send Query(IGMPv1), last_query_jiffies=%lu",last_query_jiffies); } } if (rg_db.systemGlobal.multicastProtocol!=RG_MC_IGMP_ONLY){//send MLD query if (MLDCounterVer_1>0 || MLDCounterVer_2>0){//we just consider MLDv1 and MLv2 as one type now. rtl_mldQueryTimerExpired(arg); IGMP("System send Query(MLDQuery), last_query_jiffies=%lu",last_query_jiffies); } } //if forceReportResponseTime enabled(!=0), the report must received in this peroid of time, or the client should be delete. if(rg_db.systemGlobal.forceReportResponseTime!=0){ #ifdef __KERNEL__ if(timer_pending(&mCastForceReporttimer)) del_timer(&mCastForceReporttimer); init_timer(&mCastForceReporttimer); mCastForceReporttimer.data = SYS_EXPIRED_USER_FORCE; mCastForceReporttimer.expires = jiffies+rg_db.systemGlobal.forceReportResponseTime*CONFIG_HZ; mCastForceReporttimer.function = (void*)rtl_multicastSysTimerExpired; mod_timer(&mCastForceReporttimer, jiffies+rg_db.systemGlobal.forceReportResponseTime*CONFIG_HZ); IGMP("Trigger a force report timer in %d sec (current jiffies is %d)",rg_db.systemGlobal.forceReportResponseTime,jiffies); #endif } mCastQueryTimerCnt++; #endif #endif return; } // struct list_head hwMappingEntry=NULL; //indexed by HASH(IVL or SVL) // struct list_head hwMappingEntryFreeListHead=NULL; // rtl_multicast_index_mapping_t hwMappingEntry[DEFAULT_MAX_HW_MAPPING_COUNT]; rtl_multicast_index_mapping_t * _rtk_hwMappingEntry_malloc(void) { rtl_multicast_index_mapping_t *mapping_entry; rtl_multicast_index_mapping_t *mapping_entry_tmp; if(list_empty(&hwMappingEntryFreeListHead)) { WARNING("all free IGMP hw mapping list are allocated..."); return (NULL); } //IGMP("get a free Entry for hardware mapping entry \n"); //Get one from free list list_for_each_entry_safe(mapping_entry,mapping_entry_tmp,&hwMappingEntryFreeListHead,entry) //just return the first entry right behind of head { list_del_init(&mapping_entry->entry); break; } memset(mapping_entry,0,sizeof(rtl_multicast_index_mapping_t)); list_add(&mapping_entry->entry, &rtl_multicast_index_mapping_listhead); //kmalloc //INIT_LIST_HEAD(&mapping_entry->entry); return mapping_entry; } int _rtk_hwMappingEntry_free(rtl_multicast_index_mapping_t* mapping_entry) { list_del_init(&mapping_entry->entry); list_add(&mapping_entry->entry, &hwMappingEntryFreeListHead); //IGMP("free hardware mapping entry !!\n"); return (RT_ERR_RG_OK); } //rtl_multicast_index_mapping_t hwMappingEntry[DEFAULT_MAX_HW_MAPPING_COUNT]; int _rtk_hwMappingEntry_flashInit(void) { int i; INIT_LIST_HEAD(&rtl_multicast_index_mapping_listhead); INIT_LIST_HEAD(&hwMappingEntryFreeListHead); for(i=0 ; i<DEFAULT_MAX_HW_MAPPING_COUNT;i++ ) { memset(&hwMappingEntry[i],0,sizeof(rtl_multicast_index_mapping_t)); INIT_LIST_HEAD(&hwMappingEntry[i].entry); list_add_tail(&hwMappingEntry[i].entry, &hwMappingEntryFreeListHead); } //IGMP("flash hardware mapping entry !!\n"); return (RT_ERR_RG_OK); } int32 rtl_initMulticastSnooping(struct rtl_mCastSnoopingGlobalConfig mCastSnoopingGlobalConfig) { int i,j; uint32 maxHashTableSize=MAX_HASH_TABLE_SIZE; #ifdef __KERNEL__ spin_lock_init(&rg_kernel.igmpsnoopingLock); #endif #ifdef CONFIG_RG_HARDWARE_MULTICAST _rtk_hwMappingEntry_flashInit(); #endif for (i=0; i<MAX_MCAST_MODULE_NUM; i++) { memset(&(rtl_mCastModuleArray[i]), 0, sizeof(struct rtl_multicastModule)); for (j=0; j<6; j++) { rtl_mCastModuleArray[i].rtl_gatewayMac[j]=0; } rtl_mCastModuleArray[i].rtl_gatewayIpv4Addr=0; rtl_mCastModuleArray[i].rtl_ipv4HashTable=NULL; #ifdef CONFIG_RG_MLD_SNOOPING for (j=0; j<4; j++) { rtl_mCastModuleArray[i].rtl_gatewayIpv6Addr[j]=0; } rtl_mCastModuleArray[i].rtl_ipv6HashTable=NULL; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_mCastModuleArray[i].flowHashTable=NULL; #endif rtl_mCastModuleArray[i].enableSnooping=FALSE; rtl_mCastModuleArray[i].enableFastLeave=FALSE; } /*set multicast snooping parameters, use default value*/ if(mCastSnoopingGlobalConfig.groupMemberAgingTime==0) { rtl_mCastTimerParas.groupMemberAgingTime= DEFAULT_GROUP_MEMBER_INTERVAL; } else { rtl_mCastTimerParas.groupMemberAgingTime= mCastSnoopingGlobalConfig.groupMemberAgingTime; } if(mCastSnoopingGlobalConfig.lastMemberAgingTime==0) { rtl_mCastTimerParas.lastMemberAgingTime= 0; } else { rtl_mCastTimerParas.lastMemberAgingTime= mCastSnoopingGlobalConfig.lastMemberAgingTime; } if(mCastSnoopingGlobalConfig.querierPresentInterval==0) { rtl_mCastTimerParas.querierPresentInterval= DEFAULT_QUERIER_PRESENT_TIMEOUT; } else { rtl_mCastTimerParas.querierPresentInterval=mCastSnoopingGlobalConfig.querierPresentInterval; } if(mCastSnoopingGlobalConfig.dvmrpRouterAgingTime==0) { rtl_mCastTimerParas.dvmrpRouterAgingTime=DEFAULT_DVMRP_AGING_TIME; } else { rtl_mCastTimerParas.dvmrpRouterAgingTime=mCastSnoopingGlobalConfig.dvmrpRouterAgingTime; } if(mCastSnoopingGlobalConfig.mospfRouterAgingTime==0) { rtl_mCastTimerParas.mospfRouterAgingTime=DEFAULT_MOSPF_AGING_TIME; } else { rtl_mCastTimerParas.mospfRouterAgingTime=mCastSnoopingGlobalConfig.mospfRouterAgingTime; } if(mCastSnoopingGlobalConfig.pimRouterAgingTime==0) { rtl_mCastTimerParas.pimRouterAgingTime=DEFAULT_PIM_AGING_TIME; } else { rtl_mCastTimerParas.pimRouterAgingTime=mCastSnoopingGlobalConfig.pimRouterAgingTime; } /* set hash table size and hash mask*/ if(mCastSnoopingGlobalConfig.hashTableSize==0) { rtl_hashTableSize=DEFAULT_HASH_TABLE_SIZE; /*default hash table size*/ } else { for(i=0;i<11;i++) { if(mCastSnoopingGlobalConfig.hashTableSize>=maxHashTableSize) { rtl_hashTableSize=maxHashTableSize; break; } maxHashTableSize=maxHashTableSize>>1; } } rtl_hashMask=rtl_hashTableSize-1; rtl_groupMemory=NULL; rtl_clientMemory=NULL; rtl_sourceMemory=NULL; rtl_mcastFlowMemory=NULL; /*initialize group entry pool*/ if(mCastSnoopingGlobalConfig.maxGroupNum==0) { rtl_totalMaxGroupCnt=DEFAULT_MAX_GROUP_COUNT; } else { rtl_totalMaxGroupCnt=mCastSnoopingGlobalConfig.maxGroupNum; } rtl_groupEntryPool=rtl_initGroupEntryPool(rtl_totalMaxGroupCnt); if(rtl_groupEntryPool==NULL) { return FAIL; } /*initialize client entry pool*/ if(mCastSnoopingGlobalConfig.maxClientNum==0) { rtl_totalMaxClientCnt=DEFAULT_MAX_CLIENT_COUNT; } else { rtl_totalMaxClientCnt=mCastSnoopingGlobalConfig.maxClientNum; } rtl_clientEntryPool=rtl_initClientEntryPool(rtl_totalMaxClientCnt); if(rtl_clientEntryPool==NULL) { return FAIL; } #ifdef CONFIG_RECORD_MCAST_FLOW rtl_mcastFlowEntryPool=rtl_initMcastFlowEntryPool(DEFAULT_MAX_FLOW_COUNT); if(rtl_mcastFlowEntryPool==NULL) { return FAIL; } #endif /*initialize source entry pool*/ if(mCastSnoopingGlobalConfig.maxSourceNum==0) { rtl_totalMaxSourceCnt=DEFAULT_MAX_SOURCE_COUNT; } else { rtl_totalMaxSourceCnt=mCastSnoopingGlobalConfig.maxSourceNum; } rtl_sourceEntryPool=rtl_initSourceEntryPool(rtl_totalMaxSourceCnt); if(rtl_sourceEntryPool==NULL) { rtl_totalMaxSourceCnt=0; return FAIL; } //#if 0 #if defined(__linux__) && defined(__KERNEL__) rtl_multicastSysTimerInit(); if(rg_db.systemGlobal.mcast_query_sec!=0) { init_timer(&mCastQuerytimer); //if(rg_db.systemGlobal.mcast_query_sec==0) rg_db.systemGlobal.mcast_query_sec=RTK_RG_DEFAULT_MCAST_QUERY_INTERVAL; mCastQuerytimer.expires=jiffies+rg_db.systemGlobal.mcast_query_sec*CONFIG_HZ; mCastQuerytimer.function=(void*)rtl_mCastQueryTimerExpired; } #endif return SUCCESS; } int32 rtl_flushAllIgmpRecord(int forceFlush) { /* maintain current time */ uint32 i=0; struct rtl_groupEntry* groupEntryPtr=NULL; struct rtl_groupEntry* nextEntry=NULL; uint32 moduleIndex; for(moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM; moduleIndex++) { if(rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { /*maintain ipv4 group entry timer */ //if ( !igmpsnoopenabled) if(forceFlush || (rg_db.systemGlobal.initParam.igmpSnoopingEnable==0) || (rg_db.systemGlobal.multicastProtocol==RG_MC_MLD_ONLY)) { for(i=0; i<rtl_hashTableSize; i++) { /*scan the hash table*/ if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable!=NULL) { timerEventContext.ipVersion=IP_VERSION4; groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[i]; while(groupEntryPtr) /*traverse each group list*/ { nextEntry=groupEntryPtr->next; timerEventContext.vlanId=groupEntryPtr->vlanId; timerEventContext.groupAddr[0]=groupEntryPtr->groupAddr[0]; timerEventContext.groupAddr[1]=0; timerEventContext.groupAddr[2]=0; timerEventContext.groupAddr[3]=0; rtl_deleteGroupEntry(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); groupEntryPtr=nextEntry; } } } } #ifdef CONFIG_RG_MLD_SNOOPING /*maintain ipv6 group entry timer */ //if ( !mldSnoopEnabled) if(forceFlush || (rg_db.systemGlobal.initParam.igmpSnoopingEnable==0) || (rg_db.systemGlobal.multicastProtocol==RG_MC_IGMP_ONLY)) { for(i=0; i<rtl_hashTableSize; i++) { /*scan the hash table*/ if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable!=NULL) { timerEventContext.ipVersion=IP_VERSION6; groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[i]; while(groupEntryPtr) /*traverse each group list*/ { nextEntry=groupEntryPtr->next; timerEventContext.vlanId=groupEntryPtr->vlanId; timerEventContext.groupAddr[0]=groupEntryPtr->groupAddr[0]; timerEventContext.groupAddr[1]=groupEntryPtr->groupAddr[1]; timerEventContext.groupAddr[2]=groupEntryPtr->groupAddr[2]; timerEventContext.groupAddr[3]=groupEntryPtr->groupAddr[3]; rtl_deleteGroupEntry(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); groupEntryPtr=nextEntry; } } } } #endif } } _rtk_hwMappingEntry_flashInit(); for (i=IGMP_V1; i<IGMP_MLD_VER_MAX; i++) { int j; for (j=0; j<RTK_RG_MAX_MAC_PORT; j++) { igmpSnoopingCounterVer_Port[j][i] = 0; } #ifdef CONFIG_MASTER_WLAN0_ENABLE for (j=0; j<MAX_WLAN_DEVICE_NUM; j++) { igmpSnoopingCounterVer_MBSSID[j][i]=0; } #endif } igmpSnoopingCounterVer_1=0; igmpSnoopingCounterVer_2=0; igmpSnoopingCounterVer_3=0; MLDCounterVer_1=0; MLDCounterVer_2=0; return SUCCESS; } static inline uint32 rtl_igmpHashAlgorithm(uint32 ipVersion,uint32 *groupAddr) { uint32 hashIndex=0; if (ipVersion==IP_VERSION4) { /*to do:change hash algorithm*/ hashIndex=rtl_hashMask&groupAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { hashIndex=rtl_hashMask&groupAddr[3]; } #endif return hashIndex; } int32 rtl_exitMulticastSnooping(void) { uint32 moduleIndex; for(moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM; moduleIndex++) { rtl_unregisterIgmpSnoopingModule(moduleIndex); } rtl_hashTableSize=0; rtl_hashMask=0; memset(&rtl_mCastTimerParas,0,sizeof(struct rtl_mCastTimerParameters)); if(rtl_groupMemory!=NULL) { rtk_rg_free(rtl_groupMemory); } rtl_totalMaxGroupCnt=0; rtl_groupMemory=NULL; rtl_groupEntryPool=NULL; if(rtl_clientMemory!=NULL) { rtk_rg_free(rtl_clientMemory); } rtl_totalMaxClientCnt=0; rtl_clientMemory=NULL; rtl_clientEntryPool=NULL; if(rtl_sourceMemory!=NULL) { rtk_rg_free(rtl_sourceMemory); } rtl_totalMaxSourceCnt=0; rtl_sourceMemory=NULL; rtl_sourceEntryPool=NULL; //#if 0 #if defined(__linux__) && defined(__KERNEL__) rtl_multicastSysTimerDestroy(); #endif return SUCCESS; } /*group entry memory management*/ static struct rtl_groupEntry* rtl_initGroupEntryPool(uint32 poolSize) { uint32 idx=0; struct rtl_groupEntry *poolHead=NULL; struct rtl_groupEntry *entryPtr=NULL; rg_lock(&rg_kernel.igmpsnoopingLock); /* Lock resource */ if (poolSize == 0) { goto out; } /* Allocate memory */ poolHead = (struct rtl_groupEntry *)rtk_rg_malloc(sizeof(struct rtl_groupEntry) * poolSize); rtl_groupMemory=(void *)poolHead; if (poolHead != NULL) { memset(poolHead, 0, (poolSize * sizeof(struct rtl_groupEntry))); entryPtr = poolHead; /* link the whole group entry pool */ for (idx = 0 ; idx < poolSize ; idx++, entryPtr++) { if(idx==0) { entryPtr->previous=NULL; if(idx == (poolSize - 1)) //poolSize is 1 { entryPtr->next=NULL; } else { entryPtr->next = entryPtr + 1; } } else { entryPtr->previous=entryPtr-1; if (idx == (poolSize - 1)) { entryPtr->next = NULL; } else { entryPtr->next = entryPtr + 1; } } } } out: rg_unlock(&rg_kernel.igmpsnoopingLock); /* UnLock resource */ return poolHead; } // allocate a group entry from the group entry pool static struct rtl_groupEntry* rtl_allocateGroupEntry(void) { struct rtl_groupEntry *ret = NULL; rg_lock(&rg_kernel.igmpsnoopingLock); if (rtl_groupEntryPool!=NULL) { ret = rtl_groupEntryPool; if(rtl_groupEntryPool->next!=NULL) { rtl_groupEntryPool->next->previous=NULL; } rtl_groupEntryPool = rtl_groupEntryPool->next; memset(ret, 0, sizeof(struct rtl_groupEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); return ret; } // free a group entry and link it back to the group entry pool, default is link to the pool head static void rtl_freeGroupEntry(struct rtl_groupEntry* groupEntryPtr) { if (!groupEntryPtr) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); groupEntryPtr->next = rtl_groupEntryPool; if(rtl_groupEntryPool!=NULL) { rtl_groupEntryPool->previous=groupEntryPtr; } rtl_groupEntryPool=groupEntryPtr; rg_unlock(&rg_kernel.igmpsnoopingLock); } /*client entry memory management*/ static struct rtl_clientEntry* rtl_initClientEntryPool(uint32 poolSize) { uint32 idx=0; struct rtl_clientEntry *poolHead=NULL; struct rtl_clientEntry *entryPtr=NULL; rg_lock(&rg_kernel.igmpsnoopingLock); /* Lock resource */ if (poolSize == 0) { goto out; } /* Allocate memory */ poolHead = (struct rtl_clientEntry *)rtk_rg_malloc(sizeof(struct rtl_clientEntry) * poolSize); rtl_clientMemory=(void *)poolHead; if (poolHead != NULL) { memset(poolHead, 0, (poolSize * sizeof(struct rtl_clientEntry))); entryPtr = poolHead; /* link the whole group entry pool */ for (idx = 0 ; idx < poolSize ; idx++, entryPtr++) { if(idx==0) { entryPtr->previous=NULL; if(idx == (poolSize - 1)) { entryPtr->next=NULL; } else { entryPtr->next = entryPtr + 1; } } else { entryPtr->previous=entryPtr-1; if (idx == (poolSize - 1)) { entryPtr->next = NULL; } else { entryPtr->next = entryPtr + 1; } } } } out: rg_unlock(&rg_kernel.igmpsnoopingLock); /* UnLock resource */ return poolHead; } // allocate a client entry from the client entry pool static struct rtl_clientEntry* rtl_allocateClientEntry(void) { struct rtl_clientEntry *ret = NULL; rg_lock(&rg_kernel.igmpsnoopingLock); if (rtl_clientEntryPool!=NULL) { ret = rtl_clientEntryPool; if(rtl_clientEntryPool->next!=NULL) { rtl_clientEntryPool->next->previous=NULL; } rtl_clientEntryPool = rtl_clientEntryPool->next; memset(ret, 0, sizeof(struct rtl_clientEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); return ret; } // free a client entry and link it back to the client entry pool, default is link to the pool head static void rtl_freeClientEntry(struct rtl_clientEntry* clientEntryPtr) { if (!clientEntryPtr) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); clientEntryPtr->next = rtl_clientEntryPool; if(rtl_clientEntryPool!=NULL) { rtl_clientEntryPool->previous=clientEntryPtr; } rtl_clientEntryPool=clientEntryPtr; rg_unlock(&rg_kernel.igmpsnoopingLock); } /*source entry memory management*/ static struct rtl_sourceEntry* rtl_initSourceEntryPool(uint32 poolSize) { uint32 idx=0; struct rtl_sourceEntry *poolHead=NULL; struct rtl_sourceEntry *entryPtr=NULL; rg_lock(&rg_kernel.igmpsnoopingLock); /* Lock resource */ if (poolSize == 0) { goto out; } /* Allocate memory */ poolHead = (struct rtl_sourceEntry *)rtk_rg_malloc(sizeof(struct rtl_sourceEntry) * poolSize); rtl_sourceMemory=(void *)poolHead; if (poolHead != NULL) { memset(poolHead, 0, (poolSize * sizeof(struct rtl_sourceEntry))); entryPtr = poolHead; /* link the whole source entry pool */ for (idx = 0 ; idx < poolSize ; idx++, entryPtr++) { if(idx==0) { entryPtr->previous=NULL; if(idx == (poolSize - 1)) { entryPtr->next=NULL; } else { entryPtr->next = entryPtr + 1; } } else { entryPtr->previous=entryPtr-1; if (idx == (poolSize - 1)) { entryPtr->next = NULL; } else { entryPtr->next = entryPtr + 1; } } } } out: rg_unlock(&rg_kernel.igmpsnoopingLock); /* UnLock resource */ return poolHead; } // allocate a source entry from the source entry pool static struct rtl_sourceEntry* rtl_allocateSourceEntry(void) { struct rtl_sourceEntry *ret = NULL; rg_lock(&rg_kernel.igmpsnoopingLock); if (rtl_sourceEntryPool!=NULL) { ret = rtl_sourceEntryPool; if(rtl_sourceEntryPool->next!=NULL) { rtl_sourceEntryPool->next->previous=NULL; } rtl_sourceEntryPool = rtl_sourceEntryPool->next; memset(ret, 0, sizeof(struct rtl_sourceEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); return ret; } // free a source entry and link it back to the source entry pool, default is link to the pool head static void rtl_freeSourceEntry(struct rtl_sourceEntry* sourceEntryPtr) { if (!sourceEntryPtr) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); sourceEntryPtr->next = rtl_sourceEntryPool; if(rtl_sourceEntryPool!=NULL) { rtl_sourceEntryPool->previous=sourceEntryPtr; } rtl_sourceEntryPool=sourceEntryPtr; rg_unlock(&rg_kernel.igmpsnoopingLock); } #ifdef CONFIG_RECORD_MCAST_FLOW /*multicast flow entry memory management*/ static struct rtl_mcastFlowEntry* rtl_initMcastFlowEntryPool(uint32 poolSize) { uint32 idx=0; struct rtl_mcastFlowEntry *poolHead=NULL; struct rtl_mcastFlowEntry *entryPtr=NULL; rg_lock(&rg_kernel.igmpsnoopingLock); /* Lock resource */ if (poolSize == 0) { goto out; } /* Allocate memory */ poolHead = (struct rtl_mcastFlowEntry *)rtk_rg_malloc(sizeof(struct rtl_mcastFlowEntry) * poolSize); rtl_mcastFlowMemory=(void *)poolHead; if (poolHead != NULL) { memset(poolHead, 0, (poolSize * sizeof(struct rtl_mcastFlowEntry))); entryPtr = poolHead; /* link the whole group entry pool */ for (idx = 0 ; idx < poolSize ; idx++, entryPtr++) { if(idx==0) { entryPtr->previous=NULL; if(idx == (poolSize - 1)) { entryPtr->next=NULL; } else { entryPtr->next = entryPtr + 1; } } else { entryPtr->previous=entryPtr-1; if (idx == (poolSize - 1)) { entryPtr->next = NULL; } else { entryPtr->next = entryPtr + 1; } } } } out: rg_unlock(&rg_kernel.igmpsnoopingLock); /* UnLock resource */ return poolHead; } // allocate a multicast flow entry from the multicast flow pool static struct rtl_mcastFlowEntry* rtl_allocateMcastFlowEntry(void) { struct rtl_mcastFlowEntry *ret = NULL; rg_lock(&rg_kernel.igmpsnoopingLock); if (rtl_mcastFlowEntryPool!=NULL) { ret = rtl_mcastFlowEntryPool; if(rtl_mcastFlowEntryPool->next!=NULL) { rtl_mcastFlowEntryPool->next->previous=NULL; } rtl_mcastFlowEntryPool = rtl_mcastFlowEntryPool->next; memset(ret, 0, sizeof(struct rtl_mcastFlowEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); return ret; } // free a multicast flow entry and link it back to the multicast flow entry pool, default is link to the pool head static void rtl_freeMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry) { if (NULL==mcastFlowEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); mcastFlowEntry->next = rtl_mcastFlowEntryPool; if(rtl_mcastFlowEntryPool!=NULL) { rtl_mcastFlowEntryPool->previous=mcastFlowEntry; } rtl_mcastFlowEntryPool=mcastFlowEntry; rg_unlock(&rg_kernel.igmpsnoopingLock); } #endif /********************************************* Group list operation *********************************************/ /* find a group address in a group list */ struct rtl_groupEntry* rtl_searchGroupEntry(uint32 moduleIndex, uint32 ipVersion,uint32 *multicastAddr, uint16 vlanId) { struct rtl_groupEntry* groupPtr = NULL; int32 hashIndex=0; hashIndex=rtl_igmpHashAlgorithm(ipVersion, multicastAddr); if (ipVersion==IP_VERSION4) { groupPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[hashIndex]; } #ifdef CONFIG_RG_MLD_SNOOPING else { groupPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[hashIndex]; } #endif while (groupPtr!=NULL) { if (ipVersion==IP_VERSION4) { if (multicastAddr[0]==groupPtr->groupAddr[0]) { /* if(rg_db.vlan[groupPtr->vlanId].fidMode!=VLAN_FID_SVL && groupPtr->vlanId!=vlanId) goto NEXT; return groupPtr;*/ //#if RTK_RG_MULTICAST_MODE_MACFID 1 if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (((rg_db.vlan[groupPtr->vlanId].fidMode==VLAN_FID_IVL)&&(groupPtr->vlanId!=vlanId)) ||((rg_db.vlan[groupPtr->vlanId].fidMode==VLAN_FID_SVL)&&(rg_db.vlan[groupPtr->vlanId].fid!=LAN_FID))) { goto NEXT; } } return groupPtr; #if 0 else //default path4 { /*if ((rg_db.vlan[groupPtr->vlanId].fidMode==VLAN_FID_IVL && groupPtr->vlanId!=vlanId)) || (rg_db.vlan[groupPtr->vlanId].fidMode==VLAN_FID_SVL && groupPtr->vlanId!=rg_db.vlan[groupPtr->vlanId].fid)) goto NEXT;*/ return groupPtr; } #endif } } #ifdef CONFIG_RG_MLD_SNOOPING else { if( (multicastAddr[0]==groupPtr->groupAddr[0])&& (multicastAddr[1]==groupPtr->groupAddr[1])&& (multicastAddr[2]==groupPtr->groupAddr[2])&& (multicastAddr[3]==groupPtr->groupAddr[3]) ) { if(rg_db.vlan[groupPtr->vlanId].fidMode!=VLAN_FID_SVL && groupPtr->vlanId!=vlanId) goto NEXT; return groupPtr; } } #endif NEXT: groupPtr = groupPtr->next; } return NULL; } /* link group Entry in the front of a group list */ static void rtl_linkGroupEntry(struct rtl_groupEntry* groupEntry , struct rtl_groupEntry ** hashTable) { uint32 hashIndex=0; if(NULL==groupEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock);//Lock resource hashIndex=rtl_igmpHashAlgorithm(groupEntry->ipVersion, groupEntry->groupAddr); if(hashTable[hashIndex]!=NULL) { hashTable[hashIndex]->previous=groupEntry; } groupEntry->next = hashTable[hashIndex]; hashTable[hashIndex]=groupEntry; hashTable[hashIndex]->previous=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } /* unlink a group entry from group list */ static void rtl_unlinkGroupEntry(struct rtl_groupEntry* groupEntry, struct rtl_groupEntry ** hashTable) { uint32 hashIndex=0; if(NULL==groupEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ hashIndex=rtl_igmpHashAlgorithm(groupEntry->ipVersion, groupEntry->groupAddr); /* unlink entry node*/ if(groupEntry==hashTable[hashIndex]) /*unlink group list head*/ { hashTable[hashIndex]=groupEntry->next; if(hashTable[hashIndex]!=NULL) { hashTable[hashIndex]->previous=NULL; } } else { if(groupEntry->previous!=NULL) { groupEntry->previous->next=groupEntry->next; } if(groupEntry->next!=NULL) { groupEntry->next->previous=groupEntry->previous; } } groupEntry->previous=NULL; groupEntry->next=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } /* clear the content of group entry */ static void rtl_clearGroupEntry(struct rtl_groupEntry* groupEntry) { rg_lock(&rg_kernel.igmpsnoopingLock); if (NULL!=groupEntry) { memset(groupEntry, 0, sizeof(struct rtl_groupEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); } /********************************************* Client list operation *********************************************/ static struct rtl_clientEntry* rtl_searchClientEntry(uint32 ipVersion, struct rtl_groupEntry* groupEntry, uint32 portNum, uint32 *clientAddr) { struct rtl_clientEntry* clientPtr = groupEntry->clientList; if(clientAddr==NULL) { return NULL; } while (clientPtr!=NULL) { if(ipVersion==IP_VERSION4) { if((clientPtr->clientAddr[0]==clientAddr[0])) { if(portNum<MAX_SUPPORT_PORT_NUMBER) { /*update port number,in case of client change port*/ clientPtr->portNum=portNum; } return clientPtr; } } #ifdef CONFIG_RG_MLD_SNOOPING else { if( ((clientPtr->clientAddr[0]==clientAddr[0]) &&(clientPtr->clientAddr[1]==clientAddr[1]) &&(clientPtr->clientAddr[2]==clientAddr[2]) &&(clientPtr->clientAddr[3]==clientAddr[3]))) { if(portNum<MAX_SUPPORT_PORT_NUMBER) { /*update port number,in case of client change port*/ clientPtr->portNum=portNum; } return clientPtr; } } #endif clientPtr = clientPtr->next; } return NULL; } /* link client Entry in the front of group client list */ static void rtl_linkClientEntry(struct rtl_groupEntry *groupEntry, struct rtl_clientEntry* clientEntry ) { if(NULL==clientEntry) { return; } if(NULL==groupEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock);//Lock resource #ifdef CONFIG_RG_SIMPLE_IGMP_v3 if ((groupEntry->groupAddr[0] != 0xEFFFFFFA) && //239.255.255.250 ((groupEntry->groupAddr[0] & 0xFFFFFF00) != 0xE0000000) &&//224.0.0/24 ((groupEntry->groupAddr[0] & 0xFFFFFF00) != 0xE0000100))//224.0.1/24 #endif { switch(clientEntry->igmpVersion) { case IGMP_V1: ////++ igmpSnoopingCounterVer_1++; break; case IGMP_V2: igmpSnoopingCounterVer_2++; break; case IGMP_V3: igmpSnoopingCounterVer_3++; break; case MLD_V1: MLDCounterVer_1++; break; case MLD_V2: MLDCounterVer_2++; break; default: break; } #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum > RTK_RG_MAC_PORT_CPU) { igmpSnoopingCounterVer_Port[RTK_RG_MAC_PORT_CPU][clientEntry->igmpVersion - IGMP_V1]++; igmpSnoopingCounterVer_MBSSID[clientEntry->wlan_dev_idx][clientEntry->igmpVersion - IGMP_V1]++; IGMP("Add igmpSnoopingCounterVer_Port[%d][%d]", RTK_RG_MAC_PORT_CPU, clientEntry->igmpVersion - IGMP_V1); IGMP("Add igmpSnoopingCounterVer_MBSSID[%d][%d]", clientEntry->wlan_dev_idx, clientEntry->igmpVersion - IGMP_V1); } else #endif { igmpSnoopingCounterVer_Port[clientEntry->portNum][clientEntry->igmpVersion - IGMP_V1]++; IGMP("Add gmpSnoopingCounterVer_Port[%d][%d]", clientEntry->portNum, clientEntry->igmpVersion - IGMP_V1); } } if(groupEntry->clientList!=NULL) { groupEntry->clientList->previous=clientEntry; } clientEntry->next = groupEntry->clientList; groupEntry->clientList=clientEntry; groupEntry->clientList->previous=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } /* unlink a client entry from group client list */ static void rtl_unlinkClientEntry(struct rtl_groupEntry *groupEntry, struct rtl_clientEntry* clientEntry) { if(NULL==clientEntry) { return; } if(NULL==groupEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ /* unlink entry node*/ if(clientEntry==groupEntry->clientList) /*unlink group list head*/ { groupEntry->clientList=groupEntry->clientList->next; if(groupEntry->clientList!=NULL) { groupEntry->clientList->previous=NULL; } } else { if(clientEntry->previous!=NULL) { clientEntry->previous->next=clientEntry->next; } if(clientEntry->next!=NULL) { clientEntry->next->previous=clientEntry->previous; } } clientEntry->previous=NULL; clientEntry->next=NULL; #ifdef CONFIG_RG_SIMPLE_IGMP_v3 if ((groupEntry->groupAddr[0] != 0xEFFFFFFA) && //239.255.255.250 ((groupEntry->groupAddr[0] & 0xFFFFFF00) != 0xE0000000) &&//224.0.0/24 ((groupEntry->groupAddr[0] & 0xFFFFFF00) != 0xE0000100))//224.0.1/24 #endif { switch(clientEntry->igmpVersion) { case IGMP_V1: ////++ igmpSnoopingCounterVer_1--; break; case IGMP_V2: igmpSnoopingCounterVer_2--; break; case IGMP_V3: igmpSnoopingCounterVer_3--; break; case MLD_V1: MLDCounterVer_1--; break; case MLD_V2: MLDCounterVer_2--; break; default: break; } #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum > RTK_RG_MAC_PORT_CPU) { igmpSnoopingCounterVer_Port[RTK_RG_MAC_PORT_CPU][clientEntry->igmpVersion - IGMP_V1]--; igmpSnoopingCounterVer_MBSSID[clientEntry->wlan_dev_idx][clientEntry->igmpVersion - IGMP_V1]--; } else #endif { igmpSnoopingCounterVer_Port[clientEntry->portNum][clientEntry->igmpVersion - IGMP_V1]--; } } rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } /* clear the content of client entry */ static void rtl_clearClientEntry(struct rtl_clientEntry* clientEntry) { rg_lock(&rg_kernel.igmpsnoopingLock); if (NULL!=clientEntry) { memset(clientEntry, 0, sizeof(struct rtl_clientEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); } /********************************************* source list operation *********************************************/ static struct rtl_sourceEntry* rtl_searchSourceEntry(uint32 ipVersion, uint32 *sourceAddr, struct rtl_clientEntry *clientEntry) { struct rtl_sourceEntry *sourcePtr=clientEntry->sourceList; while(sourcePtr!=NULL) { if(ipVersion==IP_VERSION4) { //DEBUG("check GIP.Clt.SrcIP=(" IP4D ") vs SIP=(" IP4D ")", NIP4QUAD(sourcePtr->sourceAddr), NIP4QUAD(sourceAddr)); if(sourceAddr[0]==sourcePtr->sourceAddr[0]) { //DEBUG("the SIP in GIP.Clt.SrcIP-List"); DEBUG("SIP("IP4D") in GIP(x).Clt("IP4D").SrcIP-List", NIP4QUAD(sourceAddr), NIP4QUAD(clientEntry->clientAddr)); return sourcePtr; } DEBUG("SIP(" IP4D ") is diff from GIP.Clt.SrcIP(" IP4D "), check next", NIP4QUAD(sourceAddr), NIP4QUAD(sourcePtr->sourceAddr)); } #ifdef CONFIG_RG_MLD_SNOOPING else { /*DEBUG("check GIP.Clt.SrcIP=%x.%x.%x.%x vs SIP6=%x.%x.%x.%x", sourcePtr->sourceAddr[0], sourcePtr->sourceAddr[0], sourcePtr->sourceAddr[2], sourcePtr->sourceAddr[3], sourceAddr[0], sourceAddr[0], sourceAddr[2], sourceAddr[3]);*/ if( (sourceAddr[0]==sourcePtr->sourceAddr[0])&& (sourceAddr[1]==sourcePtr->sourceAddr[1])&& (sourceAddr[2]==sourcePtr->sourceAddr[2])&& (sourceAddr[3]==sourcePtr->sourceAddr[3]) ) { //DEBUG("the SIP6 in GIP.Clt.SrcIP6-List"); DEBUG("SIP6("IP6H") in GIP6(x).Clt("IP6H").SrcIP6-List", NIP6QUAD(sourceAddr), NIP6QUAD(clientEntry->clientAddr)); return sourcePtr; } DEBUG("SIP6(" IP6H ") is diff from GIP6.Clt.SrcIP6(" IP6H "), check next", NIP6QUAD(sourceAddr), NIP6QUAD(sourcePtr->sourceAddr)); } #endif sourcePtr=sourcePtr->next; } //DEBUG("Not find GIP.Clt.SrcIP-list"); if(ipVersion==IP_VERSION4) { DEBUG("SIP("IP4D") not in GIP(x).Clt("IP4D").SrcIP-List", NIP4QUAD(sourceAddr), NIP4QUAD(clientEntry->clientAddr)); } else { DEBUG("SIP6("IP6H") not in GIP6(x).Clt("IP6H").SrcIP6-List", NIP6QUAD(sourceAddr), NIP6QUAD(clientEntry->clientAddr)); } return NULL; } #if 0 static int32 rtl_searchSourceAddr(uint32 ipVersion, uint32 *sourceAddr, uint32 *sourceArray, uint32 elementCount) { uint32 i=0; uint32 *srcPtr=sourceArray; for(i=0; i<elementCount; i++) { if(ipVersion==IP_VERSION4) { if(sourceAddr[0]==srcPtr[0]) { return TRUE; } srcPtr++; } #ifdef CONFIG_RG_MLD_SNOOPING if(ipVersion==IP_VERSION6) { if( (sourceAddr[0]==srcPtr[0])&&\ (sourceAddr[1]==srcPtr[1])&&\ (sourceAddr[2]==srcPtr[2])&&\ (sourceAddr[3]==srcPtr[3])) { return TRUE; } srcPtr=srcPtr+4; } #endif } return FALSE; } #endif static void rtl_linkSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* entryNode) { if(NULL==entryNode) { return; } if(NULL==clientEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ if(clientEntry->sourceList!=NULL) { clientEntry->sourceList->previous=entryNode; } entryNode->next=clientEntry->sourceList; clientEntry->sourceList=entryNode; clientEntry->sourceList->previous=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ DEBUG("Add src"); } static void rtl_unlinkSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* sourceEntry) { if(NULL==sourceEntry) { return; } if(NULL==clientEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ /* unlink entry node*/ if(sourceEntry==clientEntry->sourceList) /*unlink group list head*/ { clientEntry->sourceList=sourceEntry->next; if(clientEntry->sourceList!=NULL) { clientEntry->sourceList ->previous=NULL; } } else { if(sourceEntry->previous!=NULL) { sourceEntry->previous->next=sourceEntry->next; } if(sourceEntry->next!=NULL) { sourceEntry->next->previous=sourceEntry->previous; } } sourceEntry->previous=NULL; sourceEntry->next=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } static void rtl_clearSourceEntry(struct rtl_sourceEntry* sourceEntryPtr) { rg_lock(&rg_kernel.igmpsnoopingLock); if (NULL!=sourceEntryPtr) { memset(sourceEntryPtr, 0, sizeof(struct rtl_sourceEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); } /********************************************* multicast flow list operation *********************************************/ #ifdef CONFIG_RECORD_MCAST_FLOW static struct rtl_mcastFlowEntry* rtl_searchMcastFlowEntry(uint32 moduleIndex, uint32 ipVersion, uint32 *serverAddr,uint32 *groupAddr) { struct rtl_mcastFlowEntry* mcastFlowPtr = NULL; uint32 hashIndex=0; if(NULL==serverAddr) { return NULL; } if(NULL==groupAddr) { return NULL; } hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddr); mcastFlowPtr=rtl_mCastModuleArray[moduleIndex].flowHashTable[hashIndex]; while (mcastFlowPtr!=NULL) { if(mcastFlowPtr->ipVersion!=ipVersion) { goto nextFlow; } if(ipVersion==IP_VERSION4) { if( (serverAddr[0]==mcastFlowPtr->serverAddr[0]) && (groupAddr[0]==mcastFlowPtr->groupAddr[0]) ) { mcastFlowPtr->refreshTime=rtl_sysUpSeconds; return mcastFlowPtr; } } #ifdef CONFIG_RG_MLD_SNOOPING else { if( (serverAddr[0]==mcastFlowPtr->serverAddr[0]) &&(serverAddr[0]==mcastFlowPtr->serverAddr[0]) &&(serverAddr[0]==mcastFlowPtr->serverAddr[0]) &&(serverAddr[0]==mcastFlowPtr->serverAddr[0]) &&(groupAddr[0]==mcastFlowPtr->groupAddr[0]) &&(groupAddr[1]==mcastFlowPtr->groupAddr[1]) &&(groupAddr[2]==mcastFlowPtr->groupAddr[2]) &&(groupAddr[3]==mcastFlowPtr->groupAddr[3])) { mcastFlowPtr->refreshTime=rtl_sysUpSeconds; return mcastFlowPtr; } } nextFlow: #endif mcastFlowPtr = mcastFlowPtr->next; } return NULL; } /* link multicast flow entry in the front of a forwarding flow list */ static void rtl_linkMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry , struct rtl_mcastFlowEntry ** hashTable) { uint32 hashIndex=0; if(NULL==mcastFlowEntry) { return; } if(NULL==hashTable) { return; } rg_lock(&rg_kernel.igmpsnoopingLock);//Lock resource hashIndex=rtl_igmpHashAlgorithm(mcastFlowEntry->ipVersion, mcastFlowEntry->groupAddr); if(hashTable[hashIndex]!=NULL) { hashTable[hashIndex]->previous=mcastFlowEntry; } mcastFlowEntry->next = hashTable[hashIndex]; hashTable[hashIndex]=mcastFlowEntry; hashTable[hashIndex]->previous=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource return; } /* unlink a multicast flow entry*/ static void rtl_unlinkMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry, struct rtl_mcastFlowEntry ** hashTable) { uint32 hashIndex=0; if(NULL==mcastFlowEntry) { return; } rg_lock(&rg_kernel.igmpsnoopingLock); /* lock resource*/ hashIndex=rtl_igmpHashAlgorithm(mcastFlowEntry->ipVersion, mcastFlowEntry->groupAddr); /* unlink entry node*/ if(mcastFlowEntry==hashTable[hashIndex]) /*unlink flow list head*/ { hashTable[hashIndex]=mcastFlowEntry->next; if(hashTable[hashIndex]!=NULL) { hashTable[hashIndex]->previous=NULL; } } else { if(mcastFlowEntry->previous!=NULL) { mcastFlowEntry->previous->next=mcastFlowEntry->next; } if(mcastFlowEntry->next!=NULL) { mcastFlowEntry->next->previous=mcastFlowEntry->previous; } } mcastFlowEntry->previous=NULL; mcastFlowEntry->next=NULL; rg_unlock(&rg_kernel.igmpsnoopingLock);//UnLock resource } /* clear the content of multicast flow entry */ static void rtl_clearMcastFlowEntry(struct rtl_mcastFlowEntry* mcastFlowEntry) { rg_lock(&rg_kernel.igmpsnoopingLock); if (NULL!=mcastFlowEntry) { memset(mcastFlowEntry, 0, sizeof(struct rtl_mcastFlowEntry)); } rg_unlock(&rg_kernel.igmpsnoopingLock); } static void rtl_deleteMcastFlowEntry( struct rtl_mcastFlowEntry* mcastFlowEntry, struct rtl_mcastFlowEntry ** hashTable) { #if defined(CONFIG_XDSL_NEW_HWNAT_DRIVER) DEBUG("!!!!!!!!!!! rtl_deleteMcastFlowEntry sip=%x dip=%x ver=%d", mcastFlowEntry->serverAddr[0],mcastFlowEntry->groupAddr[0],mcastFlowEntry->ipVersion==IP_VERSION4); if(mcastFlowEntry->ipVersion==IP_VERSION4 && mcastFlowEntry->serverAddr[0] && mcastFlowEntry->groupAddr[0]) { //delete Multicast hw table rtk_rg_table_v4multicast_t mcEntry; bzero(&mcEntry,sizeof(mcEntry)); mcEntry.sip = mcastFlowEntry->serverAddr[0]; mcEntry.dip = mcastFlowEntry->groupAddr[0]; RTK_MULTICAST_ADD(&mcEntry); DEBUG("!!!!!!!!!!! rtl_deleteMcastFlowEntry "); } #endif if(mcastFlowEntry!=NULL) { rtl_unlinkMcastFlowEntry(mcastFlowEntry, hashTable); rtl_clearMcastFlowEntry(mcastFlowEntry); rtl_freeMcastFlowEntry(mcastFlowEntry); } return; } #endif /*****source entry/client entry/group entry/flow entry operation*****/ static void rtl_deleteSourceEntry(struct rtl_clientEntry *clientEntry, struct rtl_sourceEntry* sourceEntry) { DEBUG("del a GIP.Clt.Src"); if (clientEntry==NULL) { return; } if (sourceEntry!=NULL) { rtl_unlinkSourceEntry(clientEntry,sourceEntry); rtl_clearSourceEntry(sourceEntry); rtl_freeSourceEntry(sourceEntry); } } static void rtl_deleteSourceList(struct rtl_clientEntry* clientEntry) { struct rtl_sourceEntry *sourceEntry=NULL; struct rtl_sourceEntry *nextSourceEntry=NULL; DEBUG("del GIP.Clt.SrcList"); sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { nextSourceEntry=sourceEntry->next; rtl_deleteSourceEntry(clientEntry,sourceEntry); sourceEntry=nextSourceEntry; } } static void rtl_deleteClientEntry(struct rtl_groupEntry* groupEntry,struct rtl_clientEntry *clientEntry) { DEBUG("del a GIP.Clt"); if (NULL==clientEntry) { return; } if (NULL==groupEntry) { return; } //DEBUG("Client not NULL"); rtl_deleteSourceList(clientEntry); rtl_unlinkClientEntry(groupEntry,clientEntry); rtl_clearClientEntry(clientEntry); rtl_freeClientEntry(clientEntry); return; } static void rtl_deleteClientList(struct rtl_groupEntry* groupEntry) { struct rtl_clientEntry *clientEntry=NULL; struct rtl_clientEntry *nextClientEntry=NULL; DEBUG("del GIP.CltList"); if (NULL==groupEntry) { return; } clientEntry=groupEntry->clientList; while (clientEntry!=NULL) { nextClientEntry=clientEntry->next; rtl_deleteClientEntry(groupEntry,clientEntry); clientEntry=nextClientEntry; } } static void rtl_deleteGroupEntry( struct rtl_groupEntry* groupEntry,struct rtl_groupEntry ** hashTable) { DEBUG("del a GIP"); if (groupEntry!=NULL) { timerEventContext.vlanId=groupEntry->vlanId; rtl_deleteClientList(groupEntry); #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(timerEventContext.moduleIndex, timerEventContext.ipVersion, timerEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) #ifdef CONFIG_PROC_FS rtl_mCastModuleArray[timerEventContext.moduleIndex].expireEventCnt++; #endif //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &timerEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&timerEventContext); #else rtl_handle_igmpgroup_change_v3(&timerEventContext); #endif #endif rtl_unlinkGroupEntry(groupEntry, hashTable); rtl_clearGroupEntry(groupEntry); rtl_freeGroupEntry(groupEntry); } } //static int32 rtl_checkMCastAddrMapping(uint32 ipVersion, uint32 *ipAddr, uint8* macAddr) int32 rtl_checkMCastAddrMapping(uint32 ipVersion, uint32 *ipAddr, uint8* macAddr) { if(ipVersion==IP_VERSION4) { if(macAddr[0]!=0x01) { return FALSE; } if((macAddr[3]&0x7f)!=(uint8)((ipAddr[0]&0x007f0000)>>16)) { return FALSE; } if(macAddr[4]!=(uint8)((ipAddr[0]&0x0000ff00)>>8)) { return FALSE; } if(macAddr[5]!=(uint8)(ipAddr[0]&0x000000ff)) { return FALSE; } return TRUE; } #ifdef CONFIG_RG_MLD_SNOOPING else { if(macAddr[0]!=0x33) { return FALSE; } if(macAddr[1]!=0x33) { return FALSE; } if(macAddr[2]!=(uint8)((ipAddr[3]&0xff000000)>>24)) { return FALSE; } if(macAddr[3]!=(uint8)((ipAddr[3]&0x00ff0000)>>16)) { return FALSE; } if(macAddr[4]!=(uint8)((ipAddr[3]&0x0000ff00)>>8)) { return FALSE; } if(macAddr[5]!=(uint8)(ipAddr[3]&0x000000ff)) { return FALSE; } return TRUE; } #endif return FALSE; } #ifdef CONFIG_RG_MLD_SNOOPING //static int32 rtl_compareIpv6Addr(uint32* ipv6Addr1, uint32* ipv6Addr2) int32 rtl_compareIpv6Addr(uint32* ipv6Addr1, uint32* ipv6Addr2) { int i; for(i=0; i<4; i++) { if(ipv6Addr1[i]!=ipv6Addr2[i]) { return FALSE; } } return TRUE; } #endif //static int32 rtl_compareMacAddr(uint8* macAddr1, uint8* macAddr2) int32 rtl_compareMacAddr(uint8* macAddr1, uint8* macAddr2) { int i; for(i=0; i<6; i++) { if(macAddr1[i]!=macAddr2[i]) { return FALSE; } } return TRUE; } static uint16 rtl_checksum(uint8 *packetBuf, uint32 packetLen) { /*note: the first bytes of packetBuf should be two bytes aligned*/ uint32 checksum=0; uint32 count=packetLen; uint16 *ptr= (uint16 *) (packetBuf); while(count>1) { checksum+= ntohs(*ptr); ptr++; count -= 2; } if(count>0) { checksum+= *(packetBuf+packetLen-1)<<8; /*the last odd byte is treated as bit 15~8 of unsigned short*/ } /* Roll over carry bits */ checksum = (checksum >> 16) + (checksum & 0xffff); checksum += (checksum >> 16); /* Return checksum */ return ((uint16) ~ checksum); } #ifdef CONFIG_RG_MLD_SNOOPING static uint16 rtl_ipv6L3Checksum(uint8 *pktBuf, uint32 pktLen, union pseudoHeader *ipv6PseudoHdr) { uint32 checksum=0; uint32 count=pktLen; uint16 *ptr; /*compute ipv6 pseudo-header checksum*/ ptr= (uint16 *) (ipv6PseudoHdr); for(count=0; count<20; count++) /*the pseudo header is 40 bytes long*/ { checksum+= ntohs(*ptr); ptr++; } /*compute the checksum of mld buffer*/ count=pktLen; ptr=(uint16 *) (pktBuf); while(count>1) { checksum+= ntohs(*ptr); ptr++; count -= 2; } if(count>0) { checksum+= *(pktBuf+pktLen-1)<<8; /*the last odd byte is treated as bit 15~8 of unsigned short*/ } /* Roll over carry bits */ checksum = (checksum >> 16) + (checksum & 0xffff); checksum += (checksum >> 16); /* Return checksum */ return ((uint16) ~ checksum); } #endif // Mason Yu. type error //static uint8 rtl_getClientFwdPortMask(struct rtl_clientEntry * clientEntry, uint32 sysTime) static uint32 rtl_getClientFwdPortMask(struct rtl_clientEntry * clientEntry, uint32 sysTime) { // Mason Yu. type error //uint8 portMask=(1<<clientEntry->portNum); //uint8 fwdPortMask=0; uint32 portMask=(1<<clientEntry->portNum); uint32 fwdPortMask=0; struct rtl_sourceEntry * sourcePtr=NULL;; DEBUG("get CltFwdPortMask fwdPrtMsk>"); if (clientEntry->groupFilterTimer>sysTime) /*exclude mode never expired*/ { fwdPortMask|=portMask; } else/*include mode*/ { sourcePtr=clientEntry->sourceList; while (sourcePtr!=NULL) { if (sourcePtr->portTimer>sysTime) { fwdPortMask|=portMask; break; } sourcePtr=sourcePtr->next; } } return fwdPortMask; } static void rtl_checkSourceTimer(struct rtl_clientEntry * clientEntry , struct rtl_sourceEntry * sourceEntry) { uint8 deleteFlag=FALSE; //delte group? client? source? uint8 oldFwdState,newFwdState; DEBUG("Check GIP.Clt.Src Timer"); oldFwdState=sourceEntry->fwdState; if(sourceEntry->portTimer<=rtl_sysUpSeconds) /*means time out*/ { if (clientEntry->groupFilterTimer<=rtl_sysUpSeconds) /* include mode*/ { deleteFlag=TRUE; } sourceEntry->fwdState=FALSE; } else { //deleteFlag=FALSE; // redundant code sourceEntry->fwdState=TRUE; } #if 0 if(clientEntry->groupFilterTimer<=rtl_sysUpSeconds) /* include mode*/ { timerEventContext.srcFilterMode = RTK_RG_IPV4MC_INCLUDE; // DEBUG("GIP.Client is Inc-Mo"); } else { timerEventContext.srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; // DEBUG("CIP.Client is Exc-Mo"); } #endif newFwdState=sourceEntry->fwdState; DEBUG("GIP.Clt.SrcIP fwdState by {%s}" , (deleteFlag==TRUE)?"<del SrcIP>":((newFwdState!=oldFwdState)&&(newFwdState==TRUE))?"<SrcIP stop fwd>":"SrcIP go on fwd"); if (deleteFlag==TRUE) /*means INCLUDE mode and expired*/ { rtl_deleteSourceEntry(clientEntry,sourceEntry); } if ((deleteFlag==TRUE) || (newFwdState!=oldFwdState)) { #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(timerEventContext.moduleIndex, timerEventContext.ipVersion, timerEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) #ifdef CONFIG_PROC_FS rtl_mCastModuleArray[timerEventContext.moduleIndex].expireEventCnt++; #endif //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &timerEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&timerEventContext); #else rtl_handle_igmpgroup_change_v3(&timerEventContext); #endif #endif } } #if 0 static uint32 rtl_getClientSourceFwdPortMask(uint32 ipVersion, struct rtl_clientEntry *clientEntry, uint32 *sourceAddr, uint32 sysTime) { // Mason Yu. type error //uint8 portMask=(1<<clientEntry->portNum); //uint8 fwdPortMask=0; uint32 portMask=(1<<clientEntry->portNum); uint32 fwdPortMask=0; //uint32 blkPortMask=0; // struct rtl_sourceEntry *sourceEntry=NULL; DEBUG("Call-in rtl_getClientSourceFwdPortMask"); if (clientEntry==NULL) { DEBUG("GIP.Clt is null, flooding all ports, CltSrcFwdPortMask=0xFFFF,FFFF");//// return 0xFFFFFFFF; /*broadcast*/ } else { if (ipVersion == IP_VERSION4) //// DEBUG("Calc Clt(" IP4D ")-SrcIP(" IP4D ") FwdPortMask:",NIP4QUAD(clientEntry->clientAddr), NIP4QUAD(sourceAddr));//// else//// DEBUG("Calc Clt(" IP6H ")-SrcIP(" IP6H ") FwdPortMask:",NIP6QUAD(clientEntry->clientAddr), NIP6QUAD(sourceAddr));//// sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (clientEntry->groupFilterTimer<=sysTime) /*include mode*/ { DEBUG("Clt is <In-Mo>"); if (sourceEntry!=NULL) { if (sourceEntry->portTimer>sysTime) { DEBUG("=> GIP.Clt.SrcIP is time-in, Add Clt.SPA[%d] to CltSrcFwdPortMask",clientEntry->portNum);//// fwdPortMask|=portMask; } else//// {//// DEBUG("=> GIP.Clt.SrcIP is time-out, Del Clt.SPA[%d] from CltSrcFwdPortMask",clientEntry->portNum);//// }//// } else//// {//// DEBUG("=> GIP.Clt.SrcIP is not concern, Del Clt.SPA[%d] from CltSrcFwdPortMask",clientEntry->portNum);//// }//// } else /*exclude mode*/ { DEBUG("Clt is <Ex-Mo>"); if (sourceEntry==NULL) { //DEBUG("=> not exactly right"); DEBUG("=> GIP.Clt.SrcIP is not concern, Add Clt.SPA[%d] to CltSrcFwdPortMask",clientEntry->portNum);//// fwdPortMask|=portMask; } else { if (sourceEntry->portTimer>sysTime) { DEBUG("=> GIP.Clt.SrcIP is time-in, Add Clt.SPA[%d] to CltSrcFwdPortMask",clientEntry->portNum);//// fwdPortMask|=portMask; } else//// {//// DEBUG("=> GIP.Clt.SrcIP is time-out, Del Clt.SPA[%d] from CltSrcFwdPortMask",clientEntry->portNum);//// //blkPortMask|=portMask; //// }//// } //blkPortMask|=portMask; //// } DEBUG("Get GIP.Clt.SrcIP FwdPortMask(=0x%X), return",fwdPortMask); return fwdPortMask; } } static uint32 rtl_getGroupSourceFwdPortMask(struct rtl_groupEntry * groupEntry,uint32 *sourceAddr, uint32 sysTime) { // Mason Yu. type error // uint8 fwdPortMask=0; uint32 fwdPortMask=0; struct rtl_clientEntry *clientEntry=NULL; DEBUG("Call-In rtl_getGroupSourceFwdPortMask"); if (groupEntry==NULL) { DEBUG("GIP is null, set GIP-SrcIP FwdPortMask to be 0xFFFF,FFFF"); return 0xFFFFFFFF; /*broadcast*/ } else { if (groupEntry->ipVersion == IP_VERSION4) DEBUG("Calc GIP(" IP4D ")-SrcIP(" IP4D ") FwdPortMask:",NIP4QUAD(groupEntry->groupAddr), NIP4QUAD(sourceAddr)); else DEBUG("Calc GIP(" IP6H ")-SrcIP(" IP6H ") FwdPortMask:",NIP6QUAD(groupEntry->groupAddr), NIP6QUAD(sourceAddr)); clientEntry=groupEntry->clientList; while (clientEntry!=NULL) { //if (((1<<clientEntry->portNum)&fwdPortMask)==0x0) //improve redundant check, but need pure l2 only fwdPortMask |= rtl_getClientSourceFwdPortMask(groupEntry->ipVersion, clientEntry, sourceAddr, sysTime); clientEntry=clientEntry->next; } } if (groupEntry->ipVersion == IP_VERSION4) DEBUG("Get GIP(" IP4D ")-SrcIP(" IP4D ") FwdPortMask(=0x%X)",NIP4QUAD(groupEntry->groupAddr),NIP4QUAD(sourceAddr),fwdPortMask); else DEBUG("Get GIP(" IP6H ")-SrcIP(" IP6H ") FwdPortMask(=0x%X)",NIP6QUAD(groupEntry->groupAddr),NIP6QUAD(sourceAddr),fwdPortMask); return fwdPortMask; } #endif static void rtl_checkClientEntryTimer(struct rtl_groupEntry * groupEntry, struct rtl_clientEntry * clientEntry) { // Mason Yu. type error //uint8 oldFwdPortMask=0; //uint8 newFwdPortMask=0; uint32 oldFwdPortMask=0; uint32 newFwdPortMask=0; struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; struct rtl_sourceEntry *nextSourceEntry=NULL; DEBUG("Check GIP.Clt Timer"); oldFwdPortMask=rtl_getClientFwdPortMask(clientEntry, rtl_sysUpSeconds); while (sourceEntry!=NULL) { #if 0 timerEventContext.sourceAddr[0]=sourceEntry->sourceAddr[0]; //// #ifdef CONFIG_RG_MLD_SNOOPING timerEventContext.sourceAddr[1]=sourceEntry->sourceAddr[1]; //// timerEventContext.sourceAddr[2]=sourceEntry->sourceAddr[2]; //// timerEventContext.sourceAddr[3]=sourceEntry->sourceAddr[3]; //// #endif #endif nextSourceEntry=sourceEntry->next; rtl_checkSourceTimer(clientEntry, sourceEntry); sourceEntry=nextSourceEntry; } newFwdPortMask=rtl_getClientFwdPortMask(clientEntry, rtl_sysUpSeconds); if (newFwdPortMask==0) /*none active port*/ { rtl_deleteClientEntry(groupEntry,clientEntry); //timerEventContext.srcFilterMode = RTK_RG_IPV4MC_DONT_CARE_SRC; //// } if ((oldFwdPortMask!=newFwdPortMask) || (newFwdPortMask==0)) { #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(timerEventContext.moduleIndex, timerEventContext.ipVersion, timerEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { #ifdef CONFIG_PROC_FS rtl_mCastModuleArray[timerEventContext.moduleIndex].expireEventCnt++; #endif //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &timerEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&timerEventContext); #else rtl_handle_igmpgroup_change_v3(&timerEventContext); #endif } #endif } //Check is client report time is larger then user define if( (system_expire_type==SYS_EXPIRED_USER_FORCE) && (rg_db.systemGlobal.forceReportResponseTime!=0)){ //DEBUG("###Force check clien[0x%x] report time, client jiffie=%lu### (Hz=%d)",clientEntry->clientAddr[0],clientEntry->reportUpdateJiffies,CONFIG_HZ); if((clientEntry->reportUpdateJiffies - last_query_jiffies) < rg_db.systemGlobal.forceReportResponseTime*CONFIG_HZ) { //recieved report in the force time internal, keep the client. } else { DEBUG("###Force delete clien[0x%x] (client update jiffies is %d) ###",clientEntry->clientAddr[0],clientEntry->reportUpdateJiffies); rtl_deleteClientEntry(groupEntry,clientEntry); } } } static void rtl_checkGroupEntryTimer(struct rtl_groupEntry * groupEntry, struct rtl_groupEntry ** hashTable) { uint32 deleteFlag=FALSE; struct rtl_clientEntry *clientEntry=groupEntry->clientList; struct rtl_clientEntry *nextClientEntry=NULL; DEBUG("In rtl_checkGroupEntryTimer"); while(clientEntry!=NULL) { nextClientEntry=clientEntry->next; timerEventContext.portMask=1<<(clientEntry->portNum); rtl_checkClientEntryTimer(groupEntry, clientEntry); clientEntry=nextClientEntry; } if(groupEntry->clientList==NULL) /*none active client*/ { deleteFlag=TRUE; rtl_deleteGroupEntry(groupEntry,hashTable); rtl_handle_igmpgroup_change(&timerEventContext); } /*if(deleteFlag==TRUE) { #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(timerEventContext.moduleIndex, timerEventContext.ipVersion, timerEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { #ifdef CONFIG_PROC_FS rtl_mCastModuleArray[timerEventContext.moduleIndex].expireEventCnt++; #endif //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &timerEventContext); #if 0 rtl_handle_igmpgroup_change(&timerEventContext); #else rtl_handle_igmpgroup_change_v3(&timerEventContext); #endif } #endif }*/ DEBUG("Out rtl_checkGroupEntryTimer"); } static int32 rtl_initHashTable(uint32 moduleIndex, uint32 hashTableSize) { uint32 i=0; /* Allocate memory */ rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable = (struct rtl_groupEntry **)rtk_rg_malloc(4 * hashTableSize); if (rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable!= NULL) { for (i = 0 ; i < hashTableSize ; i++) { rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[i]=NULL; } } else { return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable= (struct rtl_groupEntry **)rtk_rg_malloc(4 * hashTableSize); if (rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable!=NULL) { for (i = 0 ; i < hashTableSize ; i++) { rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[i]=NULL; } } else { if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable!=NULL) { rtk_rg_free(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } return FAIL; } #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_mCastModuleArray[moduleIndex].flowHashTable= (struct rtl_mcastFlowEntry **)rtk_rg_malloc(4 * hashTableSize); if (rtl_mCastModuleArray[moduleIndex].flowHashTable!=NULL) { for (i = 0 ; i < hashTableSize ; i++) { rtl_mCastModuleArray[moduleIndex].flowHashTable[i]=NULL; } } else { if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable!=NULL) { rtk_rg_free(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable!=NULL) { rtk_rg_free(rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif return FAIL; } #endif return SUCCESS; } /************************** Utility **************************/ static void rtl_parseMacFrame(uint32 moduleIndex, uint8* macFrame, rtk_rg_pktHdr_t *pPktHdr, uint32 verifyCheckSum, struct rtl_macFrameInfo* macInfo) { //MAC Frame :DA(6 bytes)+SA(6 bytes)+ CPU tag(4 bytes) + VlAN tag(Optional, 4 bytes) // +Type(IPv4:0x0800, IPV6:0x86DD, PPPOE:0x8864, 2 bytes )+Data(46~1500 bytes)+CRC(4 bytes) #ifdef CONFIG_RG_MLD_SNOOPING int i=0; uint8 routingHead=FALSE; #ifdef PARSE_IGMP_MLD_AGAGIN uint8 *ptr=macFrame; uint8 nextHeader=0; uint8 optionDataLen=0; uint8 optionType=0; uint16 extensionHdrLen=0; uint32 ipv6RAO=0; #endif #endif #ifdef PARSE_IGMP_MLD_AGAGIN uint32 ipAddr[4]={0,0,0,0}; #endif union pseudoHeader pHeader; memset(macInfo,0,sizeof(struct rtl_macFrameInfo)); memset(&pHeader, 0, sizeof(union pseudoHeader)); #ifdef PARSE_IGMP_MLD_AGAGIN ptr=ptr+12; /*check the presence of VLAN tag*/ if(*(int16 *)(ptr)==(int16)htons(VLAN_PROTOCOL_ID)) { ptr=ptr+4; } /*ignore packet with PPPOE header*/ if(*(int16 *)(ptr)==(int16)htons(PPPOE_ETHER_TYPE)) { IGMP("ignore PPPoE packet ethertype(0x8864)"); return; } #else if (pPktHdr->tagif&PPPOE_TAGIF) { IGMP("ignore PPPoE packet PPPOE_TAGIF"); return; } #endif #ifdef PARSE_IGMP_MLD_AGAGIN /*check the presence of ipv4 type*/ if(*(int16 *)(ptr)==(int16)htons(IPV4_ETHER_TYPE)) { ptr=ptr+2; macInfo->ipBuf=ptr; macInfo->ipVersion=IP_VERSION4; } /*check the presence of ipv4 type*/ else if(*(int16 *)(ptr)==(int16)htons(IPV6_ETHER_TYPE)) { ptr=ptr+2; macInfo->ipBuf=ptr; macInfo->ipVersion=IP_VERSION6; }else //if((macInfo->ipVersion!=IP_VERSION4) && (macInfo->ipVersion!=IP_VERSION6)) { IGMP("ignore non-IPv4 or non-IPv6 packet"); return; } #else macInfo->ipBuf = macFrame + pPktHdr->l3Offset; if (pPktHdr->tagif & IPV4_TAGIF) { macInfo->ipVersion=IP_VERSION4; } else if (pPktHdr->tagif & IPV6_TAGIF) { macInfo->ipVersion=IP_VERSION6; }else{ IGMP("ignore non-IPv4 or non-IPv6 packet"); return; } #endif macInfo->checksumFlag=FAIL; if(macInfo->ipVersion==IP_VERSION4) { #ifdef PARSE_IGMP_MLD_AGAGIN IGMP("parsing IP4 IGMP"); macInfo->ipHdrLen=(uint16)((((struct ipv4Pkt *)(macInfo->ipBuf))->vhl&0x0f)<<2); macInfo->l3PktLen=ntohs(((struct ipv4Pkt *)(macInfo->ipBuf))->length)-macInfo->ipHdrLen; ptr=ptr+macInfo->ipHdrLen; //ptr to L4 start macInfo->l3PktBuf=ptr; macInfo->macFrameLen=(uint16)((ptr-macFrame) + macInfo->l3PktLen); macInfo->srcIpAddr[0]=ntohl(((struct ipv4Pkt *)(macInfo->ipBuf))->sourceIp); macInfo->dstIpAddr[0]=ntohl(((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp); #else IGMP("assign IP4 IGMP"); macInfo->ipHdrLen=pPktHdr->ipv4HeaderLen; macInfo->l3PktLen=pPktHdr->l3Len - pPktHdr->ipv4HeaderLen; macInfo->l3PktBuf=macFrame + pPktHdr->l3Offset + pPktHdr->ipv4HeaderLen; macInfo->macFrameLen=(uint16)(pPktHdr->l3Offset + pPktHdr->l3Len); macInfo->srcIpAddr[0]=pPktHdr->ipv4Sip; macInfo->dstIpAddr[0]=pPktHdr->ipv4Dip; #endif /*distinguish different IGMP packet: ip_header_length destination_ip igmp_packet_length igmp_type group_address IGMPv1_general_query: 20 224.0.0.1 8 0x11 0 IGMPv2_general_query: 24 224.0.0.1 8 0x11 0 IGMPv2_group_specific_query: 24 224.0.0.1 8 0x11 !=0 IGMPv3 _query: 24 224.0.0.1 >=12 0x11 according_to_different_situation IGMPv1_join: 20 actual_multicast_address 8 0x12 actual_multicast_address IGMPv2_join: 24 actual_multicast_address 8 0x16 actual_multicast_address IGMPv2_leave: 24 actual_multicast_address 8 0x17 actual_multicast_address IGMPv3_report: 24 actual_multicast_address >=12 0x22 actual_multicast_address*/ /* parse IGMP type and version*/ #ifdef PARSE_IGMP_MLD_AGAGIN if(((struct ipv4Pkt *)(macInfo->ipBuf))->protocol==IGMP_PROTOCOL) { /*check DVMRP*/ if((macInfo->l3PktBuf[0]==DVMRP_TYPE) && (((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp==htonl(DVMRP_ADDR)) ) { macInfo->l3Protocol=DVMRP_PROTOCOL; } else { /*means unicast*/ if((macFrame[0]&0x01)==0) { if(rtl_compareMacAddr(macFrame, rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac)==TRUE) { if(((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp==htonl(rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv4Addr)) { macInfo->l3Protocol=IGMP_PROTOCOL; goto otherpro; } } } else /*means multicast*/ { #ifdef PARSE_IGMP_MLD_AGAGIN ipAddr[0]=ntohl(((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp); #else ipAddr[0]=pPktHdr->ipv4Dip; #endif if(rtl_checkMCastAddrMapping(IP_VERSION4,ipAddr,macFrame)==TRUE) { macInfo->l3Protocol=IGMP_PROTOCOL; } else { return; } } } } otherpro: if(((struct ipv4Pkt *)(macInfo->ipBuf))->protocol==MOSPF_PROTOCOL &&\ ((((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp==htonl(IPV4_MOSPF_ADDR1)) ||\ (((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp==htonl(IPV4_MOSPF_ADDR2)))) { IGMP("parsing MOSPF"); macInfo->l3Protocol=MOSPF_PROTOCOL; } if(((struct ipv4Pkt *)(macInfo->ipBuf))->protocol==PIM_PROTOCOL && (((struct ipv4Pkt *)(macInfo->ipBuf))->destinationIp==htonl(IPV4_PIM_ADDR))) { IGMP("parsing PIM"); macInfo->l3Protocol=PIM_PROTOCOL; } #else //macInfo->l3Protocol= pPktHdr->ipProtocol; if (pPktHdr->tagif&DVMRP_TAGIF) { macInfo->l3Protocol=DVMRP_PROTOCOL; }else if (pPktHdr->tagif&IGMP_TAGIF) { macInfo->l3Protocol=IGMP_PROTOCOL; } if (pPktHdr->tagif&MOSPF_TAGIF) { IGMP("parsing MOSPF"); macInfo->l3Protocol= MOSPF_PROTOCOL; } if (pPktHdr->tagif&PIM_TAGIF) { IGMP("parsing PIM"); macInfo->l3Protocol=PIM_PROTOCOL; } #endif if(verifyCheckSum==TRUE) { IGMP("recalculate checksum"); if(rtl_checksum(macInfo->l3PktBuf, macInfo->l3PktLen)!=0) { macInfo->checksumFlag=FAIL; } else { macInfo->checksumFlag=SUCCESS; } } else { IGMP("Does not recalculate checksum"); macInfo->checksumFlag=SUCCESS; } } #ifdef CONFIG_RG_MLD_SNOOPING if(macInfo->ipVersion==IP_VERSION6) { IGMP("IP6 MLD"); #ifdef PARSE_IGMP_MLD_AGAGIN macInfo->srcIpAddr[0]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->sourceAddr[0]); macInfo->srcIpAddr[1]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->sourceAddr[1]); macInfo->srcIpAddr[2]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->sourceAddr[2]); macInfo->srcIpAddr[3]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->sourceAddr[3]); macInfo->dstIpAddr[0]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[0]); macInfo->dstIpAddr[1]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[1]); macInfo->dstIpAddr[2]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[2]); macInfo->dstIpAddr[3]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[3]); macInfo->macFrameLen=(uint16)(ptr-macFrame+IPV6_HEADER_LENGTH+ntohs(((struct ipv6Pkt *)(macInfo->ipBuf))->payloadLenth)); #else /* macInfo->srcIpAddr[0]= (uint32*)(&pPktHdr->pIpv6Sip[0]); macInfo->srcIpAddr[1]= (uint32*)(&pPktHdr->pIpv6Sip[4]); macInfo->srcIpAddr[2]= (uint32*)(&pPktHdr->pIpv6Sip[8]); macInfo->srcIpAddr[3]= (uint32*)(&pPktHdr->pIpv6Sip[12]); */ macInfo->srcIpAddr[0]=(pPktHdr->pIpv6Sip[0] <<12)+(pPktHdr->pIpv6Sip[1] <<8)+(pPktHdr->pIpv6Sip[2] <<4)+(pPktHdr->pIpv6Sip[3]); macInfo->srcIpAddr[1]=(pPktHdr->pIpv6Sip[4] <<12)+(pPktHdr->pIpv6Sip[5] <<8)+(pPktHdr->pIpv6Sip[6] <<4)+(pPktHdr->pIpv6Sip[7]); macInfo->srcIpAddr[2]=(pPktHdr->pIpv6Sip[8] <<12)+(pPktHdr->pIpv6Sip[9] <<8)+(pPktHdr->pIpv6Sip[10]<<4)+(pPktHdr->pIpv6Sip[11]); macInfo->srcIpAddr[3]=(pPktHdr->pIpv6Sip[12]<<12)+(pPktHdr->pIpv6Sip[13]<<8)+(pPktHdr->pIpv6Sip[14]<<4)+(pPktHdr->pIpv6Sip[15]); macInfo->dstIpAddr[0]=(pPktHdr->pIpv6Dip[0] <<12)+(pPktHdr->pIpv6Dip[1] <<8)+(pPktHdr->pIpv6Dip[2] <<4)+(pPktHdr->pIpv6Dip[3]); macInfo->dstIpAddr[1]=(pPktHdr->pIpv6Dip[4] <<12)+(pPktHdr->pIpv6Dip[5] <<8)+(pPktHdr->pIpv6Dip[6] <<4)+(pPktHdr->pIpv6Dip[7]); macInfo->dstIpAddr[2]=(pPktHdr->pIpv6Dip[8] <<12)+(pPktHdr->pIpv6Dip[9] <<8)+(pPktHdr->pIpv6Dip[10]<<4)+(pPktHdr->pIpv6Dip[11]); macInfo->dstIpAddr[3]=(pPktHdr->pIpv6Dip[12]<<12)+(pPktHdr->pIpv6Dip[13]<<8)+(pPktHdr->pIpv6Dip[14]<<4)+(pPktHdr->pIpv6Dip[15]); //macInfo->macFrameLen=(uint16)(pPktHdr->l3Offset + IPV6_HEADER_LENGTH + pPktHdr->ipv6PayloadLen); macInfo->macFrameLen=(uint16)(pPktHdr->l4Offset + pPktHdr->ipv6PayloadLen); #endif macInfo->ipHdrLen=IPV6_HEADER_LENGTH; IGMP("macFrameLen=%d ipHdrLen=%d(fixed 40)", macInfo->macFrameLen, macInfo->ipHdrLen); #ifdef PARSE_IGMP_MLD_AGAGIN ptr=ptr+IPV6_HEADER_LENGTH; nextHeader=((struct ipv6Pkt *)(macInfo->ipBuf))->nextHeader; IGMP("nextHeader=%d", nextHeader); while((ptr-macInfo->ipBuf)<(ntohs(((struct ipv6Pkt *)(macInfo->ipBuf))->payloadLenth)+IPV6_HEADER_LENGTH)) { switch(nextHeader) { case HOP_BY_HOP_OPTIONS_HEADER: IGMP("parsing/by-pass hop_by_hop header(s)"); /*parse hop-by-hop option*/ nextHeader=ptr[0]; extensionHdrLen=((uint16)(ptr[1])+1)*8; ptr=ptr+2; while((ptr-macInfo->ipBuf-40)<extensionHdrLen) { optionType=ptr[0]; /*pad1 option*/ if(optionType==0) { ptr=ptr+1; continue; } /*padN option*/ if(optionType==1) { optionDataLen=ptr[1]; ptr=ptr+optionDataLen+2; continue; } /*router alter option*/ if(ntohl(*(uint32 *)(ptr))==IPV6_ROUTER_ALTER_OPTION) { ipv6RAO=IPV6_ROUTER_ALTER_OPTION; ptr=ptr+4; continue; } /*other TLV option*/ if((optionType!=0) && (optionType!=1)) { optionDataLen=ptr[1]; ptr=ptr+optionDataLen+2; continue; } } /* if((ptr-macInfo->ipBuf-40)!=extensionHdrLen) { rtlglue_printf("ipv6 packet parse error\n"); }*/ IGMP("parsing hop_by_hop-options-header nextHeader=%d", nextHeader); break; case ROUTING_HEADER: nextHeader=ptr[0]; extensionHdrLen=((uint16)(ptr[1])+1)*8; if (ptr[3]>0) { ptr=ptr+extensionHdrLen; for(i=0; i<4; i++) { pHeader.ipv6_pHdr.destinationAddr[i]=*((uint32 *)(ptr)-4+i); } routingHead=TRUE; } else { ptr=ptr+extensionHdrLen; } IGMP("parsing/by-pass routing-header nextHeader=%d", nextHeader); break; case FRAGMENT_HEADER: nextHeader=ptr[0]; ptr=ptr+8; IGMP("parsing/by-pass fragment-header(size 8) nextHeader=%d", nextHeader); break; case DESTINATION_OPTION_HEADER: nextHeader=ptr[0]; extensionHdrLen=((uint16)(ptr[1])+1)*8; ptr=ptr+extensionHdrLen; IGMP("parsing/by-pass destionation-option-header nextHeader=%d", nextHeader); break; case ICMP_PROTOCOL: IGMP("parsing ICMPv6 header nextHeader=%d(no-next-header), ptr[0]=%d", nextHeader, ptr[0]); nextHeader=NO_NEXT_HEADER; macInfo->l3PktLen=ntohs(((struct ipv6Pkt *)(macInfo->ipBuf))->payloadLenth)-(uint16)(ptr-macInfo->ipBuf-IPV6_HEADER_LENGTH); macInfo->l3PktBuf=ptr; if((ptr[0]==MLD_QUERY) || (ptr[0]==MLDV1_REPORT) || (ptr[0]==MLDV1_DONE) || (ptr[0]==MLDV2_REPORT)) { IGMP("packet is ICMPv6 / MLD\n"); /*means multicast*/ if( (macFrame[0]==0x33)&&\ (macFrame[1]==0x33)) { ipAddr[0]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[0]); ipAddr[1]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[1]); ipAddr[2]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[2]); ipAddr[3]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[3]); if(rtl_checkMCastAddrMapping(IP_VERSION6, ipAddr, macFrame)==TRUE) { macInfo->l3Protocol=ICMP_PROTOCOL; } } else /*means multicast*/ { ipAddr[0]=htonl(rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[0]); ipAddr[1]=htonl(rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[1]); ipAddr[2]=htonl(rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[2]); ipAddr[3]=htonl(rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[3]); if((rtl_compareMacAddr(macFrame, rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac)==TRUE) &&\ (rtl_compareIpv6Addr(((struct ipv6Pkt *)macInfo->ipBuf)->destinationAddr, ipAddr) == TRUE)) { macInfo->l3Protocol=ICMP_PROTOCOL; } } /* if(ipv6RAO!=IPV6_ROUTER_ALTER_OPTION) { rtlglue_printf("router alter option error\n"); }*/ } break; case PIM_PROTOCOL: IGMP("parsing IPv6 PIM nextHeader=%d", nextHeader); nextHeader=NO_NEXT_HEADER; macInfo->l3PktLen=ntohs(((struct ipv6Pkt *)(macInfo->ipBuf))->payloadLenth)-(uint16)(ptr-macInfo->ipBuf-IPV6_HEADER_LENGTH); macInfo->l3PktBuf=ptr; ipAddr[0]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[0]); ipAddr[1]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[1]); ipAddr[2]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[2]); ipAddr[3]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[3]); if(IS_IPV6_PIM_ADDR(ipAddr)) { macInfo->l3Protocol=PIM_PROTOCOL; } break; case MOSPF_PROTOCOL: IGMP("parsing IPv6 MOSPF nextHeader=%d", nextHeader); nextHeader=NO_NEXT_HEADER; macInfo->l3PktLen=ntohs(((struct ipv6Pkt *)(macInfo->ipBuf))->payloadLenth)-(uint16)(ptr-macInfo->ipBuf-IPV6_HEADER_LENGTH); macInfo->l3PktBuf=ptr; ipAddr[0]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[0]); ipAddr[1]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[1]); ipAddr[2]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[2]); ipAddr[3]=ntohl(((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[3]); if(IS_IPV6_MOSPF_ADDR1(ipAddr) || IS_IPV6_MOSPF_ADDR2(ipAddr)) { macInfo->l3Protocol=MOSPF_PROTOCOL; } break; default: goto out; break; } } out: #else //macInfo->l3PktLen=pPktHdr->l3Len - pPktHdr->ipv4HeaderLen; //macInfo->l3PktLen=pPktHdr->l3Len; macInfo->l3PktLen=pPktHdr->ipv6PayloadLen; //macInfo->l3PktBuf=macFrame + pPktHdr->l3Offset; //macInfo->l3PktBuf=macFrame + pPktHdr->l3Offset + 48; //ICMPv6 Header Length macInfo->l3PktBuf=macFrame + pPktHdr->l4Offset; //IGMP("pPktHdr->ipv6PayloadLen=%d", pPktHdr->ipv6PayloadLen); //IGMP("pPktHdr->l3Offset=%d", pPktHdr->l3Offset); //IGMP("pPktHdr->l3Len=%d", pPktHdr->l3Len); //IGMP("pPktHdr->l3Len-pPktHdr->ipv6PayloadLen=%d", pPktHdr->l3Len-pPktHdr->ipv6PayloadLen); //IGMP("pPktHdr->l4Offset=%d", pPktHdr->l4Offset); macInfo->l3Protocol=pPktHdr->ipProtocol; if (pPktHdr->tagif&ICMPV6_TAGIF) { IGMP("assign info: ICMPv6"); macInfo->l3Protocol=ICMP_PROTOCOL; //58, ICMPv6 } if (pPktHdr->tagif&PIM_TAGIF) { IGMP("assign info: PIM"); macInfo->l3Protocol=PIM_PROTOCOL; } if (pPktHdr->tagif&MOSPF_TAGIF) { IGMP("assign info: MOSPF"); macInfo->l3Protocol= MOSPF_PROTOCOL; } if (pPktHdr->tagif&PIM_TAGIF) { IGMP("assign info: PIM"); macInfo->l3Protocol=PIM_PROTOCOL; } #endif if(verifyCheckSum==TRUE) { if(macInfo->l3PktBuf==NULL) { return; } /*generate pseudo header*/ for(i=0; i<4; i++) { pHeader.ipv6_pHdr.sourceAddr[i]=((struct ipv6Pkt *)(macInfo->ipBuf))->sourceAddr[i]; } if(routingHead==FALSE) { for(i=0;i<4;i++) { pHeader.ipv6_pHdr.destinationAddr[i]=((struct ipv6Pkt *)(macInfo->ipBuf))->destinationAddr[i]; } } pHeader.ipv6_pHdr.nextHeader=macInfo->l3Protocol; pHeader.ipv6_pHdr.upperLayerPacketLength=htonl((uint32)(macInfo->l3PktLen)); pHeader.ipv6_pHdr.zeroData[0]=0; pHeader.ipv6_pHdr.zeroData[1]=0; pHeader.ipv6_pHdr.zeroData[2]=0; /*verify checksum*/ if(rtl_ipv6L3Checksum(macInfo->l3PktBuf, macInfo->l3PktLen,&pHeader)!=0) { macInfo->checksumFlag=FAIL; } else { macInfo->checksumFlag=SUCCESS; } } else { macInfo->checksumFlag=SUCCESS; } } #endif return; } static uint32 rtl_getMulticastRouterPortMask(uint32 moduleIndex, uint32 ipVersion, uint32 sysTime) { uint32 portIndex=0; uint8 portMaskn=PORT0_MASK; uint32 routerPortmask=0; if(ipVersion==IP_VERSION4) { for(portIndex=0; portIndex<MAX_SUPPORT_PORT_NUMBER; portIndex++) { if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.querier.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.dvmrpRouter.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.mospfRouter.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.pimRouter.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } portMaskn=portMaskn<<1; /*shift to next port mask*/ } } #ifdef CONFIG_RG_MLD_SNOOPING else { for(portIndex=0; portIndex<MAX_SUPPORT_PORT_NUMBER; portIndex++) { if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.querier.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.mospfRouter.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.pimRouter.portTimer[portIndex]>sysTime) { routerPortmask=routerPortmask|portMaskn; } portMaskn=portMaskn<<1; /*shift to next port mask*/ } } #endif routerPortmask= routerPortmask |rtl_mCastModuleArray[moduleIndex].staticRouterPortMask; return routerPortmask; } static uint32 rtl_processQueries(uint32 moduleIndex, rtk_rg_pktHdr_t *pPktHdr, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint8* pktBuf, uint32 pktLen) { struct rtl_groupEntry *groupEntry=NULL; struct rtl_clientEntry * clientEntry=NULL; struct rtl_sourceEntry*sourceEntry=NULL; uint32 hashIndex=0; uint32 groupAddress[4]={0,0,0,0}; uint32 suppressFlag=0; uint32 *sourceAddr=NULL; uint32 numOfSrc=0; uint32 i=0; /*querier timer update and election process*/ rtl_snoopQuerier(moduleIndex, ipVersion, portNum); if (ipVersion==IP_VERSION4) { if (pktLen>=12) /*means igmpv3 query*/ { groupAddress[0]=ntohl(((struct igmpv3Query*)pktBuf)->groupAddr); suppressFlag=((struct igmpv3Query*)pktBuf)->rsq & S_FLAG_MASK; sourceAddr=&(((struct igmpv3Query*)pktBuf)->srcList); numOfSrc=(uint32)ntohs(((struct igmpv3Query*)pktBuf)->numOfSrc); IGMP("IGMPv3 Query"); pPktHdr->IGMPQueryVer = IGMP_V3; } else { groupAddress[0]=ntohl(((struct igmpv2Pkt *)pktBuf)->groupAddr); //IGMP("IGMPv1 or IGMPv2 Query"); if (ntohl(((struct igmpv2Pkt *)pktBuf)->maxRespTime))// decide to 1, follow timeout field { IGMP("IGMPv2 Query"); pPktHdr->IGMPQueryVer = IGMP_V2; } else { pPktHdr->IGMPQueryVer = IGMP_V1; IGMP("IGMPv1 Query"); } } if (groupAddress[0]==0) /*means general query*/ { IGMP("General-Query"); goto out; } else { IGMP("Not General-Query"); hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); } } #ifdef CONFIG_RG_MLD_SNOOPING else { if (pktLen>=28) /*means mldv2 query*/ { IGMP("MLDv2 Query"); groupAddress[0]=ntohl(((struct mldv2Query*)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mldv2Query*)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mldv2Query*)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mldv2Query*)pktBuf)->mCastAddr[3]); suppressFlag=((struct mldv2Query*)pktBuf)->rsq & S_FLAG_MASK; sourceAddr=&(((struct mldv2Query*)pktBuf)->srcList); numOfSrc=(uint32)ntohs(((struct mldv2Query*)pktBuf)->numOfSrc); } else /*means mldv1 query*/ { IGMP("got MLDv1"); groupAddress[0]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[3]); } if ((groupAddress[0]==0)&& (groupAddress[1]==0)&& (groupAddress[2]==0)&& (groupAddress[3]==0))/*means general query*/ { IGMP("General-Query"); goto out; } else { IGMP("Not General-Query"); hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); } } #endif if(suppressFlag==0) { IGMP("suppressFlag==0"); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.vlan[rg_db.pktHdr->internalVlanID].fid); } }*/ if ((groupEntry!=NULL)) { if(numOfSrc==0) /*means group specific query*/ { IGMP("Group-Specific-Query"); clientEntry=groupEntry->clientList; while(clientEntry!=NULL) { if(clientEntry->groupFilterTimer>(rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime)) { clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } clientEntry=clientEntry->next; } } else /*means group and source specific query*/ { IGMP("Group-Source-Specific-Query"); clientEntry=groupEntry->clientList; while (clientEntry!=NULL) { for (i=0; i<numOfSrc; i++) { sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (sourceEntry!=NULL) { if (sourceEntry->portTimer>(rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime)) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } } if (ipVersion==IP_VERSION4) { sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { sourceAddr=sourceAddr+4; } #endif } clientEntry=clientEntry->next; } } } } //if (suppressFlag==0) reportEventContext.ipVersion=ipVersion; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); } #endif out: return (~(1<<portNum) & ((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static void rtl_snoopQuerier(uint32 moduleIndex, uint32 ipVersion, uint32 portNum) { if(ipVersion==IP_VERSION4) { rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.querier.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.querierPresentInterval;/*update timer value*/ } #ifdef CONFIG_RG_MLD_SNOOPING else { rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.querier.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.querierPresentInterval;/*update timer value*/ } #endif return; } /*Process Report Packet*/ static uint32 rtl_processJoin(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; uint32 hashIndex=0; uint32 multicastRouterPortMask=rtl_getMulticastRouterPortMask(moduleIndex, ipVersion, rtl_sysUpSeconds); if(ipVersion==IP_VERSION4) { if(pktBuf[0]==0x12) { IGMP("IGMPv1_Report"); groupAddress[0]=ntohl(((struct igmpv1Pkt *)pktBuf)->groupAddr); } if(pktBuf[0]==0x16) { IGMP("IGMPv2_Join"); groupAddress[0]=ntohl(((struct igmpv2Pkt *)pktBuf)->groupAddr); } if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) goto out; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("MLDv1_Join"); groupAddress[0]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[3]); } #endif if ((1<<portNum)&(~rg_db.systemGlobal.igmpReportIngressPortmask)) { rg_db.pktHdr->ingressIgmpMldDrop = 1; return 0; //Drop } hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.vlan[rg_db.pktHdr->internalVlanID].fid); } }*/ if (groupEntry==NULL) /*means new group address, create new group entry*/ { DEBUG("record new gip"); newGroupEntry=rtl_allocateGroupEntry(); if(newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); goto out; } assert(newGroupEntry->clientList==NULL); #ifdef CONFIG_RG_MLD_SNOOPING newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; #else newGroupEntry->groupAddr[0]=groupAddress[0]; #endif newGroupEntry->ipVersion=ipVersion; newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { newGroupEntry->vlanId=rg_db.vlan[rg_db.pktHdr->internalVlanID].fid; } }*/ if(ipVersion==IP_VERSION4) { rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { DEBUG("record new client"); newClientEntry=rtl_allocateClientEntry(); if (newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); goto out; } assert(newClientEntry->sourceList==NULL); newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif if (pktBuf[0]==0x12) ////++ newClientEntry->igmpVersion=IGMP_V1; ////++ else ////++ newClientEntry->igmpVersion=IGMP_V2; if (ipVersion==IP_VERSION4) { newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V1; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; } clientEntry->reportUpdateJiffies=jiffies; //DEBUG("update client[0x%x] jiffies to %lu",clientEntry->clientAddr[0],clientEntry->reportUpdateJiffies); rtl_deleteSourceList(clientEntry); //clientEntry->igmpVersion=IGMP_V2; clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { reportEventContext.vlanId=rg_db.vlan[rg_db.pktHdr->internalVlanID].fid; } }*/ #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); } #endif out: return (multicastRouterPortMask&(~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static uint32 rtl_processLeave(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_clientEntry *clientEntry=NULL; struct rtl_sourceEntry *sourceEntry=NULL; struct rtl_sourceEntry *nextSourceEntry=NULL; uint32 hashIndex=0; uint32 multicastRouterPortMask=rtl_getMulticastRouterPortMask(moduleIndex, ipVersion, rtl_sysUpSeconds); IGMP("IGMP/MLD Leave packet"); if(ipVersion==IP_VERSION4) { groupAddress[0]=ntohl(((struct igmpv2Pkt *)pktBuf)->groupAddr); } #ifdef CONFIG_RG_MLD_SNOOPING else { groupAddress[0]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mldv1Pkt *)pktBuf)->mCastAddr[3]); } #endif hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.vlan[rg_db.pktHdr->internalVlanID].fid); } }*/ if(groupEntry!=NULL) { clientEntry=rtl_searchClientEntry( ipVersion, groupEntry, portNum, clientAddr); if(clientEntry!=NULL) { if(rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { rtl_deleteClientEntry(groupEntry, clientEntry); } else { // //-Error: why sourceEntry is always NULL ? // //-Error: sourceEntry = rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); while(sourceEntry!=NULL) { nextSourceEntry=sourceEntry->next; if(sourceEntry->portTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } sourceEntry=nextSourceEntry; } if(clientEntry->groupFilterTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) { clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } } } } reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; /*if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (rg_db.vlan[rg_db.pktHdr->internalVlanID].fidMode==VLAN_FID_SVL) { reportEventContext.vlanId=rg_db.vlan[rg_db.pktHdr->internalVlanID].fid; } }*/ #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); if(rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); } } #endif if((groupEntry!=NULL) && (groupEntry->clientList==NULL)) { if(ipVersion==IP_VERSION4) { rtl_deleteGroupEntry(groupEntry,rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } } //return (multicastRouterPortMask&(~(1<<portNum))&0x3f); return (multicastRouterPortMask&(~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static int32 rtl_processIsInclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceAddr=NULL; if(ipVersion==IP_VERSION4) { IGMP("process IGMPv3-IsInclude"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2-IsInclude"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) /*means new group address, create new group entry*/ { DEBUG("New GIP"); newGroupEntry=rtl_allocateGroupEntry(); if(newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); return FAIL; } assert(newGroupEntry->clientList==NULL); /*set new multicast entry*/ #ifdef CONFIG_RG_MLD_SNOOPING newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; #else newGroupEntry->groupAddr[0]=groupAddress[0]; #endif newGroupEntry->ipVersion=ipVersion; newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; if(ipVersion==IP_VERSION4) { rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } /*from here groupEntry is the same as newGroupEntry*/ clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { DEBUG("New GIP.Clt"); newClientEntry=rtl_allocateClientEntry(); if (newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); return FAIL; } assert(newClientEntry->sourceList==NULL); newClientEntry->sourceList=NULL; newClientEntry->igmpVersion=IGMP_V3; newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif if(ipVersion==IP_VERSION4) { newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V2; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; clientEntry->groupFilterTimer=rtl_sysUpSeconds; //// } #if 0 else //// { //// newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } //// #endif //// need to delete #if 0 /*from here client entry is the same as the newClientEntry*/ rtl_deleteSourceList(clientEntry); assert(clientEntry->sourceList==NULL); clientEntry->groupFilterTimer=rtl_sysUpSeconds; #endif if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif DEBUG("GIP.Clt"); /*here to handle the source list*/ for (j=0; j<numOfSrc; j++) { #if 0 DEBUG("New GIP.Clt.Src(%d)",j); newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; DEBUG("SrcList[%d]=" IP4D , j, NIP4QUAD(newSourceEntry->sourceAddr)); sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; sourceAddr=sourceAddr+4; } #endif newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; rtl_linkSourceEntry(clientEntry,newSourceEntry); #else newSourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (clientEntry->groupFilterTimer>rtl_sysUpSeconds) { if (newSourceEntry!=NULL) //had recorded source-ip { #if 0 if (newSourceEntry->portTimer <= rtl_sysUpSeconds) { rtl_deleteSourceEntry(clientEntry,newSourceEntry); } else { newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } #else newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; #endif } else { DEBUG("New GIP.Clt.Src(%d)",j); newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; DEBUG("SrcList[%d]=" IP4D , j, NIP4QUAD(newSourceEntry->sourceAddr)); } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif rtl_linkSourceEntry(clientEntry,newSourceEntry); newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } } else { if (newSourceEntry==NULL) { DEBUG("New GIP.Clt.Src(%d)",j); newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; DEBUG("SrcList[%d]=" IP4D , j, NIP4QUAD(newSourceEntry->sourceAddr)); } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif rtl_linkSourceEntry(clientEntry,newSourceEntry); } newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } if (ipVersion==IP_VERSION4) sourceAddr++; #ifdef CONFIG_RG_MLD_SNOOPING else sourceAddr=sourceAddr+4; #endif #endif } ////: considerate per M-SIP //reportEventContext.srcFilterMode = RTK_RG_IPV4MC_INCLUDE; //// reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; reportEventContext.groupAddr[0]=groupAddress[0]; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #endif if (newSourceEntry) { reportEventContext.sourceAddr[0]=newSourceEntry->sourceAddr[0]; //// #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.sourceAddr[1]=newSourceEntry->sourceAddr[1]; //// reportEventContext.sourceAddr[2]=newSourceEntry->sourceAddr[2]; //// reportEventContext.sourceAddr[3]=newSourceEntry->sourceAddr[3]; //// #endif } #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } #endif //} ////: considerate per M-SIP return SUCCESS; } static int32 rtl_processIsExclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceArray=NULL; uint32 *sourceAddr=NULL; if(ipVersion==IP_VERSION4) { IGMP("process IGMPv3-IsExclude"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceArray=&(((struct groupRecord *)pktBuf)->srcList); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2-IsExclude"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceArray=&(((struct mCastAddrRecord *)pktBuf)->srcList); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm( ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) /*means new group address, create new group entry*/ { newGroupEntry=rtl_allocateGroupEntry(); if (newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); return FAIL; } assert(newGroupEntry->clientList==NULL); /*set new multicast entry*/ newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; newGroupEntry->ipVersion=ipVersion; if (ipVersion==IP_VERSION4) { newGroupEntry->groupAddr[0]=groupAddress[0]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } /*from here groupEntry is the same as newGroupEntry*/ clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { newClientEntry=rtl_allocateClientEntry(); if (newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); return FAIL; } assert(newClientEntry->sourceList==NULL); newClientEntry->sourceList=NULL; newClientEntry->igmpVersion=IGMP_V3; newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif if(ipVersion==IP_VERSION4) { newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V2; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; //clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime;//// } /*from here clientEntry is the same as newClientEntry*/ if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif /*flush the old source list*/ #if 0 clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; rtl_deleteSourceList(clientEntry); assert(clientEntry->sourceList==NULL); #else // delete ((X-A) | (Y-A)) or (A-B) { struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { sourceEntry->setOpFlag=1; sourceEntry=sourceEntry->next; } } #endif /*link the new source list*/ for (j=0; j<numOfSrc; j++) { #if 1 newSourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (clientEntry->groupFilterTimer>rtl_sysUpSeconds) //ex-mo { if (newSourceEntry!=NULL) // A*X or A*Y { if (newSourceEntry->portTimer <= rtl_sysUpSeconds) // A*Y { //rtl_deleteSourceEntry(clientEntry,newSourceEntry); newSourceEntry->portTimer=rtl_sysUpSeconds; } else //A*X { //newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } newSourceEntry->setOpFlag=0; } else //A-X-Y = GMI { DEBUG("New GIP.Clt.Src(%d)",j); newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; DEBUG("SrcList[%d]=" IP4D , j, NIP4QUAD(newSourceEntry->sourceAddr)); } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif rtl_linkSourceEntry(clientEntry,newSourceEntry); newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; newSourceEntry->setOpFlag=0; } } else { if (newSourceEntry==NULL) //B-A { DEBUG("New GIP.Clt.Src(Record index:%d)",j); newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; DEBUG("SrcList[%d]=" IP4D , j, NIP4QUAD(newSourceEntry->sourceAddr)); } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif rtl_linkSourceEntry(clientEntry,newSourceEntry); newSourceEntry->portTimer=rtl_sysUpSeconds; } else //B*A { //newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } newSourceEntry->setOpFlag=0; } if (ipVersion==IP_VERSION4) sourceAddr++; #ifdef CONFIG_RG_MLD_SNOOPING else sourceAddr=sourceAddr+4; #endif #else newSourceEntry=rtl_allocateSourceEntry(); if(newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if(ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; sourceAddr=sourceAddr+4; } #endif /*time out the sources included in the MODE_IS_EXCLUDE report*/ newSourceEntry->portTimer=rtl_sysUpSeconds; rtl_linkSourceEntry(clientEntry,newSourceEntry); #endif } ////: considerate per M-SIP // delete ((X-A) | (Y-A)) or (A-B) { struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; struct rtl_sourceEntry *nextSourceEntry; while (sourceEntry!=NULL) { nextSourceEntry=sourceEntry->next; if (sourceEntry->setOpFlag) { rtl_deleteSourceEntry(clientEntry, sourceEntry); } sourceEntry=nextSourceEntry; } } clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; //reportEventContext.srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; //// reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; reportEventContext.ipVersion=ipVersion; reportEventContext.groupAddr[0]=groupAddress[0]; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #endif if (newSourceEntry) { reportEventContext.sourceAddr[0]=newSourceEntry->sourceAddr[0]; //// #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.sourceAddr[1]=newSourceEntry->sourceAddr[1]; //// reportEventContext.sourceAddr[2]=newSourceEntry->sourceAddr[2]; //// reportEventContext.sourceAddr[3]=newSourceEntry->sourceAddr[3]; //// #endif } #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } #endif //} ////: considerate per M-SIP return SUCCESS; } static int32 rtl_processToInclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *sourceEntry=NULL; //struct rtl_sourceEntry *nextSourceEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceAddr=NULL; uint16 numOfQuerySrc=0; //int tmp_interVID = rg_db.pktHdr->internalVlanID; //int tmp_rx_src_port_num=rg_db.pktHdr->pRxDesc->rx_src_port_num; //int tmp_ingressPort=rg_db.pktHdr->ingressPort; if (ipVersion==IP_VERSION4) { IGMP("process IGMPv3-ToInclude"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2-ToInclude"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) /*means new group address, create new group entry*/ { newGroupEntry=rtl_allocateGroupEntry(); if (newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); return FAIL; } newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; newGroupEntry->ipVersion=ipVersion; if (ipVersion==IP_VERSION4) { newGroupEntry->groupAddr[0]=groupAddress[0]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } /*from here groupEntry is the same as newGroupEntry*/ clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { newClientEntry=rtl_allocateClientEntry(); if (newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); return FAIL; } assert(newClientEntry->sourceList==NULL); newClientEntry->sourceList=NULL; newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif if (ipVersion==IP_VERSION4) { newClientEntry->igmpVersion=IGMP_V3; newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V2; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; } /*here to handle the source list*/ if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif if (rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { IGMP("enableFastLeave==TRUE"); clientEntry->groupFilterTimer=rtl_sysUpSeconds; rtl_deleteSourceList(clientEntry); /*link the new source list*/ for (j=0; j<numOfSrc; j++) { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; sourceAddr=sourceAddr+4; } #endif newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; rtl_linkSourceEntry(clientEntry,newSourceEntry); } } else { // //-Error: why sourceEntry is always NULL ? // //-Error: #if 0 //sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { //nextSourceEntry=sourceEntry->next; if (sourceEntry->portTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } //sourceEntry=nextSourceEntry; sourceEntry=sourceEntry->next; } #endif #if 0 // delete ((X-A) | (Y-A)) or (A-B) { struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { sourceEntry->setOpFlag=1; sourceEntry=sourceEntry->next; } } // delete ((X-A) | (Y-A)) or (A-B) { struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; struct rtl_sourceEntry *nextSourceEntry; while (sourceEntry!=NULL) { nextSourceEntry=sourceEntry->next; if (sourceEntry->setOpFlag) { rtl_deleteSourceEntry(clientEntry, sourceEntry); } sourceEntry=nextSourceEntry; } } #endif // query in-mo for Q(A-B) // query ex-mo for Q(G,X-A) & Q(G) { //struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { if (sourceEntry->portTimer>rtl_sysUpSeconds) //ex-mo X or in-mo A { sourceEntry->setOpFlag=1; numOfQuerySrc++; } else sourceEntry->setOpFlag=0; sourceEntry=sourceEntry->next; } } DEBUG("numOfQuerySrc=%d, numOfSrc=%d", numOfQuerySrc, numOfSrc); /*add new source list*/ for (j=0; j<numOfSrc; j++) { sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (sourceEntry!=NULL) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; if (sourceEntry->setOpFlag) { numOfQuerySrc--; sourceEntry->setOpFlag=0; } } else { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; /*if (newSourceEntry->setOpFlag) { numOfQuerySrc--; newSourceEntry->setOpFlag=0; }*/ newSourceEntry->setOpFlag=0; rtl_linkSourceEntry(clientEntry,newSourceEntry); } if (ipVersion==IP_VERSION4) { sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { sourceAddr=sourceAddr+4; } #endif } if (clientEntry->groupFilterTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) //ex-mo { DEBUG("Shrink ex-mo client to lastMemberAgingTime=%d", rtl_mCastTimerParas.lastMemberAgingTime); clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } #if 1 DEBUG("before query, check original rg_db.pktHdr->internalVlanID=%d",rg_db.pktHdr->internalVlanID); DEBUG("before query, check original rg_db.pktHdr->rx.src_port_num=%d,rg_db.pktHdr->ingressPort=%d", rg_db.pktHdr->pRxDesc->rx_src_port_num, rg_db.pktHdr->ingressPort); DEBUG("numOfQuerySrc=%d, numOfSrc=%d", numOfQuerySrc, numOfSrc); // query in-mo for Q(G,A-B) // query ex-mo for Q(G,X-A) & Q(G) DEBUG("Group-Source Specific Query"); rtl_igmpQueryTimerExpired(0, IGMP_V3, (char *)groupAddress, numOfQuerySrc, clientEntry->sourceList, NULL); if (clientEntry->groupFilterTimer>rtl_sysUpSeconds && numOfQuerySrc!=0) //ex-mo { DEBUG("Group Specific Query"); rtl_igmpQueryTimerExpired(0, IGMP_V3, (char *)groupAddress, 0, NULL, NULL); } #endif } //reportEventContext.srcFilterMode = RTK_RG_IPV4MC_INCLUDE; //// reportEventContext.ipVersion=ipVersion; //reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; #if 0 reportEventContext.vlanId=tmp_interVID; rg_db.pktHdr->pRxDesc->rx_src_port_num = tmp_rx_src_port_num; rg_db.pktHdr->ingressPort=tmp_ingressPort; #endif DEBUG("after query, check curr rg_db.pktHdr->internalVlanID=%d",rg_db.pktHdr->internalVlanID); DEBUG("after query, check curr rg_db.pktHdr->rx.src_port_num=%d,rg_db.pktHdr->ingressPort=%d", rg_db.pktHdr->pRxDesc->rx_src_port_num, rg_db.pktHdr->ingressPort); DEBUG("after query, check curr rg_db.pktHdr->IGMPType=%d (v3 0x22)",rg_db.pktHdr->IGMPType); #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); if(rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } } #endif return SUCCESS; } static int32 rtl_processToExclude(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *sourceEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceArray=NULL; uint32 *sourceAddr=NULL; //uint32 *tmpAddress=NULL; uint32 tmpAddress[4]={0, 0, 0, 0}; uint16 numOfQuerySrc=0; if (ipVersion==IP_VERSION4) { IGMP("process IGMPv3-ToExclude"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceArray=&(((struct groupRecord *)pktBuf)->srcList); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2-ToExclude"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceArray=&(((struct mCastAddrRecord *)pktBuf)->srcList); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) /*means new group address, create new group entry*/ { newGroupEntry=rtl_allocateGroupEntry(); if(newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); return FAIL; } assert(newGroupEntry->clientList==NULL); newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; newGroupEntry->ipVersion=ipVersion; if (ipVersion==IP_VERSION4) { newGroupEntry->groupAddr[0]=groupAddress[0]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { newClientEntry=rtl_allocateClientEntry(); if (newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); return FAIL; } assert(newClientEntry->sourceList==NULL); newClientEntry->sourceList=NULL; newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE /* if (newClientEntry->portNum == RTK_RG_EXT_PORT0 || newClientEntry->portNum == RTK_RG_EXT_PORT1) { rtk_rg_lookupIdxReturn_t retIdx=_rtk_rg_wlanMbssidLookup(pktBuf+6, &newClientEntry->wlan_dev_idx); if(retIdx==RG_RET_LOOKUPIDX_NOT_FOUND) { WARNING("MBSSID had not learned, error"); } } else { newClientEntry->wlan_dev_idx=RG_RET_LOOKUPIDX_NOT_FOUND; } */ newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif if (ipVersion==IP_VERSION4) { newClientEntry->igmpVersion=IGMP_V3; newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V2; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; } /*flush the old source list*/ #if 0 clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; rtl_deleteSourceList(clientEntry); assert(clientEntry->sourceList==NULL); #else // delete ((X-A) | (Y-A)) or (A-B) { //struct rtl_sourceEntry *sourceEntry=clientEntry->sourceList; sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { sourceEntry->setOpFlag=1; sourceEntry=sourceEntry->next; } } #endif if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if(ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif /*link the new source list*/ #if 0 for(j=0; j<numOfSrc; j++) { newSourceEntry=rtl_allocateSourceEntry(); if(newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if(ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; sourceAddr=sourceAddr+4; } #endif /*time out the sources included in the MODE_IS_EXCLUDE report*/ newSourceEntry->portTimer=rtl_sysUpSeconds; rtl_linkSourceEntry(clientEntry,newSourceEntry); } #else for (j=0; j<numOfSrc; j++) { sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (clientEntry->groupFilterTimer>rtl_sysUpSeconds) //ex-mo { if (sourceEntry!=NULL) // A*X + A*Y { sourceEntry->setOpFlag=0; if (sourceEntry->portTimer>rtl_sysUpSeconds) //A*X { } else { if (ipVersion==IP_VERSION4) sourceAddr++; #ifdef CONFIG_RG_MLD_SNOOPING else sourceAddr=sourceAddr+4; #endif continue; } } else // A-X-Y { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif /*time out the sources included in the MODE_IS_EXCLUDE report*/ newSourceEntry->portTimer=rtl_sysUpSeconds; rtl_linkSourceEntry(clientEntry,newSourceEntry); //newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; newSourceEntry->portTimer=clientEntry->groupFilterTimer; newSourceEntry->setOpFlag=0; } #if 1 if (ipVersion==IP_VERSION4) { //querySourceAddr DEBUG("Block.GIP.Clt.SrcIP("IP4D") in A-Y",NIP4QUAD(sourceAddr));//// *tmpAddress = *sourceAddr; *sourceAddr = *(sourceAddr + (numOfSrc-j-1)); *(sourceAddr + (numOfSrc-j-1)) = *tmpAddress; DEBUG("sourceAddr Head("IP4D") Tail("IP4D")",NIP4QUAD(sourceAddr), NIP4QUAD((sourceAddr+(numOfSrc-j-1)))); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; DEBUG("Block.GIP6.Clt.SrcIP6("IP6H") in A-Y",NIP6QUAD(sourceAddr));//// for (i=0; i<4; i++) { *(tmpAddress+i) = *(sourceAddr+i); *(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc -j - 1))); *(sourceAddr+i + ((numOfSrc - j - 1))) = *(tmpAddress+i); } } #endif j--; numOfSrc--; numOfQuerySrc++; DEBUG(""); continue; //no need to move sourceAddr #endif } else //in-mo { if (sourceEntry!=NULL) // A*B { sourceEntry->setOpFlag=0; #if 1 if (ipVersion==IP_VERSION4) { //querySourceAddr DEBUG("To_Ex.GIP.Clt.SrcIP("IP4D") in A*B",NIP4QUAD(sourceAddr));//// *tmpAddress = *sourceAddr; *sourceAddr = *(sourceAddr + (numOfSrc-j-1)); *(sourceAddr + (numOfSrc-j-1)) = *tmpAddress; DEBUG("sourceAddr Head("IP4D") Tail("IP4D")",NIP4QUAD(sourceAddr), NIP4QUAD((sourceAddr+(numOfSrc-j-1)))); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; DEBUG("To_Ex.GIP6.Clt.SrcIP6("IP6H") in A*B",NIP6QUAD(sourceAddr));//// for (i=0; i<4; i++) { *(tmpAddress+i) = *(sourceAddr+i); *(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc -j - 1))); *(sourceAddr+i + ((numOfSrc - j - 1))) = *(tmpAddress+i); } } #endif j--; numOfSrc--; numOfQuerySrc++; DEBUG(""); continue; //no need to move sourceAddr #endif } else //B-A { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; sourceAddr=sourceAddr+4; } #endif /*time out the sources included in the MODE_IS_EXCLUDE report*/ newSourceEntry->portTimer=rtl_sysUpSeconds; rtl_linkSourceEntry(clientEntry,newSourceEntry); newSourceEntry->setOpFlag=0; } /* if (ipVersion==IP_VERSION4) sourceAddr++; #ifdef CONFIG_RG_MLD_SNOOPING else sourceAddr=sourceAddr+4; #endif */ } } #endif // delete ((X-A) | (Y-A)) or (A-B) { struct rtl_sourceEntry *nextSourceEntry; sourceEntry=clientEntry->sourceList; while (sourceEntry!=NULL) { nextSourceEntry=sourceEntry->next; if (sourceEntry->setOpFlag) { rtl_deleteSourceEntry(clientEntry, sourceEntry); } sourceEntry=nextSourceEntry; } } clientEntry->groupFilterTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; if (ipVersion==IP_VERSION4) { int i ; for (i=0; i<numOfQuerySrc; i++) { DEBUG("Query GIP("IP4D")-SrcIP("IP4D")", NIP4QUAD(groupAddress), NIP4QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; rtl_igmpQueryTimerExpired(0, IGMP_V3, (char *)groupAddress, numOfQuerySrc, NULL, (char *)sourceAddr); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; for (i=0; i<numOfQuerySrc; i+=4) { DEBUG("Query GIP6("IP6H")-SrcIP("IP6H")", NIP6QUAD(groupAddress), NIP6QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; ??????????????????????????????????????????????? rtl_mldQueryTimerExpired(0); } #endif //reportEventContext.srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; //// reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } #endif return SUCCESS; } static int32 rtl_processAllow(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_groupEntry* newGroupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *sourceEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceAddr=NULL; if (ipVersion==IP_VERSION4) { IGMP("process IGMPv3 Allow packet"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2 Allow packet"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm( ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) /*means new group address, create new group entry*/ { newGroupEntry=rtl_allocateGroupEntry(); if (newGroupEntry==NULL) { rtlglue_printf("run out of group entry!\n"); return FAIL; } newGroupEntry->vlanId=rg_db.pktHdr->internalVlanID; newGroupEntry->ipVersion=ipVersion; if (ipVersion==IP_VERSION4) { newGroupEntry->groupAddr[0]=groupAddress[0]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); } #ifdef CONFIG_RG_MLD_SNOOPING else { newGroupEntry->groupAddr[0]=groupAddress[0]; newGroupEntry->groupAddr[1]=groupAddress[1]; newGroupEntry->groupAddr[2]=groupAddress[2]; newGroupEntry->groupAddr[3]=groupAddress[3]; rtl_linkGroupEntry(newGroupEntry, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); } #endif groupEntry=newGroupEntry; } clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { newClientEntry=rtl_allocateClientEntry(); if(newClientEntry==NULL) { rtlglue_printf("run out of client entry!\n"); return FAIL; } assert(newClientEntry->sourceList==NULL); newClientEntry->sourceList=NULL; newClientEntry->portNum=portNum; #ifdef CONFIG_MASTER_WLAN0_ENABLE newClientEntry->wlan_dev_idx=wlan_dev_idx; #endif newClientEntry->igmpVersion=IGMP_V3; newClientEntry->groupFilterTimer=rtl_sysUpSeconds; if(ipVersion==IP_VERSION4) { newClientEntry->clientAddr[0]=clientAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newClientEntry->igmpVersion=MLD_V2; newClientEntry->clientAddr[0]=clientAddr[0]; newClientEntry->clientAddr[1]=clientAddr[1]; newClientEntry->clientAddr[2]=clientAddr[2]; newClientEntry->clientAddr[3]=clientAddr[3]; } #endif rtl_linkClientEntry(groupEntry, newClientEntry); clientEntry=newClientEntry; } if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif /*here to handle the source list*/ for (j=0; j<numOfSrc; j++) { sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (sourceEntry==NULL) { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; rtl_linkSourceEntry(clientEntry,newSourceEntry); } else { /*just update source timer*/ sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; } if (ipVersion==IP_VERSION4) sourceAddr++; #ifdef CONFIG_RG_MLD_SNOOPING else sourceAddr=sourceAddr+4; #endif } reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } #endif return SUCCESS; } static int32 rtl_processBlock(uint32 moduleIndex, uint32 ipVersion,uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 j=0; uint32 groupAddress[4]={0, 0, 0, 0}; struct rtl_groupEntry* groupEntry=NULL; struct rtl_clientEntry* clientEntry=NULL; //struct rtl_clientEntry* newClientEntry=NULL; struct rtl_sourceEntry *sourceEntry=NULL; struct rtl_sourceEntry *newSourceEntry=NULL; uint32 hashIndex=0; uint16 numOfSrc=0; uint32 *sourceAddr=NULL; uint16 numOfQuerySrc=0; //uint32 *querySourceAddr=NULL; uint32 tmpAddress[4]={0, 0, 0, 0}; if (ipVersion==IP_VERSION4) { IGMP("process IGMPv3-Block"); groupAddress[0]=ntohl(((struct groupRecord *)pktBuf)->groupAddr); numOfSrc=ntohs(((struct groupRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct groupRecord *)pktBuf)->srcList); if ((groupAddress[0] < 0xe0000100) || (groupAddress[0] == 0xeffffffa)) return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING else { IGMP("process MLDv2-Block"); groupAddress[0]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[0]); groupAddress[1]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[1]); groupAddress[2]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[2]); groupAddress[3]=ntohl(((struct mCastAddrRecord *)pktBuf)->mCastAddr[3]); numOfSrc=ntohs(((struct mCastAddrRecord *)pktBuf)->numOfSrc); sourceAddr=&(((struct mCastAddrRecord *)pktBuf)->srcList); } #endif hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddress); groupEntry=rtl_searchGroupEntry(moduleIndex, ipVersion, groupAddress, rg_db.pktHdr->internalVlanID); if (groupEntry==NULL) { goto out; } clientEntry=rtl_searchClientEntry(ipVersion, groupEntry, portNum, clientAddr); if (clientEntry==NULL) { goto out; } if (ipVersion==IP_VERSION4) clientEntry->igmpVersion=IGMP_V3; #ifdef CONFIG_RG_MLD_SNOOPING else //if (ipVersion==IP_VERSION6) clientEntry->igmpVersion=MLD_V2; #endif if (clientEntry->groupFilterTimer>rtl_sysUpSeconds) /*means exclude mode*/ { DEBUG("<Ex-Mo> GIP.Clt"); numOfQuerySrc=0; for (j=0; j<numOfSrc; j++) { DEBUG("current j(%d), numOfSrc(%d), numOfQuerySrc(%d)", j, numOfSrc, numOfQuerySrc);//// sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr, clientEntry); if (sourceEntry==NULL) // A-X-Y { newSourceEntry=rtl_allocateSourceEntry(); if (newSourceEntry==NULL) { rtlglue_printf("run out of source entry!\n"); return FAIL; } if (ipVersion==IP_VERSION4) { newSourceEntry->sourceAddr[0]=sourceAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { newSourceEntry->sourceAddr[0]=sourceAddr[0]; newSourceEntry->sourceAddr[1]=sourceAddr[1]; newSourceEntry->sourceAddr[2]=sourceAddr[2]; newSourceEntry->sourceAddr[3]=sourceAddr[3]; } #endif #if 0 newSourceEntry->portTimer=rtl_sysUpSeconds; #else //newSourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.groupMemberAgingTime; newSourceEntry->portTimer=clientEntry->groupFilterTimer; #endif rtl_linkSourceEntry(clientEntry,newSourceEntry); } else // A*X+A*Y { if (rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { sourceEntry->portTimer=rtl_sysUpSeconds; } else { #if 0 if (sourceEntry->portTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } #endif } #if 1 if (sourceEntry->portTimer>rtl_sysUpSeconds) // A*X { } else //A*Y { if (ipVersion==IP_VERSION4) { sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { sourceAddr=sourceAddr+4; } #endif DEBUG(""); continue; } #endif } // A-X-Y + A*X = A-Y #if 1 if (ipVersion==IP_VERSION4) { //querySourceAddr DEBUG("Block.GIP.Clt.SrcIP("IP4D") in A-Y",NIP4QUAD(sourceAddr));//// *tmpAddress = *sourceAddr; *sourceAddr = *(sourceAddr + (numOfSrc-j-1)); *(sourceAddr + (numOfSrc-j-1)) = *tmpAddress; DEBUG("sourceAddr Head("IP4D") Tail("IP4D")",NIP4QUAD(sourceAddr), NIP4QUAD((sourceAddr+(numOfSrc-j-1)))); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; DEBUG("Block.GIP6.Clt.SrcIP6("IP6H") in A-Y",NIP6QUAD(sourceAddr));//// for (i=0; i<4; i++) { *(tmpAddress+i) = *(sourceAddr+i); *(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc -j - 1))); *(sourceAddr+i + ((numOfSrc - j - 1))) = *(tmpAddress+i); } } #endif j--; numOfSrc--; numOfQuerySrc++; DEBUG(""); continue; //no need to move sourceAddr #endif if (ipVersion==IP_VERSION4) { sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { sourceAddr=sourceAddr+4; } #endif } #if 0 if (ipVersion==IP_VERSION4) { int i ; for (i=0; i<numOfQuerySrc; i++) { DEBUG("Query GIP("IP4D")-SrcIP("IP4D")", NIP4QUAD(groupAddress), NIP4QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; rtl_igmpQueryTimerExpired(0, 3, (char *)groupAddress, numOfQuerySrc, NULL, (char *)sourceAddr); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; for (i=0; i<numOfQuerySrc; i+=4) { DEBUG("Query GIP6("IP6H")-SrcIP("IP6H")", NIP6QUAD(groupAddress), NIP6QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; ??????????????????????????????????????????????? rtl_mldQueryTimerExpired(0); } #endif #endif } else /*means include mode*/ { DEBUG("<In-Mo> GIP.Clt"); /*if (ipVersion==IP_VERSION4) querySourceAddr=sourceAddr + numOfSrc; else querySourceAddr=sourceAddr + (numOfSrc<<2); */ numOfQuerySrc=0; for (j=0; j<numOfSrc; j++) { DEBUG("current j(%d), numOfSrc(%d), numOfQuerySrc(%d)", j, numOfSrc, numOfQuerySrc);//// sourceEntry=rtl_searchSourceEntry(ipVersion, sourceAddr,clientEntry); if (sourceEntry!=NULL) // { if (rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { sourceEntry->portTimer=rtl_sysUpSeconds; } else { #if 0 if (sourceEntry->portTimer>rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime) { sourceEntry->portTimer=rtl_sysUpSeconds+rtl_mCastTimerParas.lastMemberAgingTime; } #endif } if (ipVersion==IP_VERSION4) { //querySourceAddr DEBUG("Block.GIP.Clt.SrcIP("IP4D") in A*B",NIP4QUAD(sourceAddr));//// *tmpAddress = *sourceAddr; #if 0 *sourceAddr = *(sourceAddr + (numOfSrc - 1 - numOfQuerySrc)); *(sourceAddr + (numOfSrc - 1 - numOfQuerySrc)) = *tmpAddress; DEBUG("sourceAddr Head("IP4D") Tail("IP4D")",NIP4QUAD(sourceAddr), NIP4QUAD((sourceAddr+(numOfSrc-1-numOfQuerySrc)))); #else *sourceAddr = *(sourceAddr + (numOfSrc-j-1)); *(sourceAddr + (numOfSrc-j-1)) = *tmpAddress; DEBUG("sourceAddr Head("IP4D") Tail("IP4D")",NIP4QUAD(sourceAddr), NIP4QUAD((sourceAddr+(numOfSrc-j-1)))); #endif } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; DEBUG("Block.GIP6.Clt.SrcIP6("IP6H") in A*B",NIP6QUAD(sourceAddr));//// for (i=0; i<4; i++) { *(tmpAddress+i) = *(sourceAddr+i); #if 0 //*(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc - 1 - numOfQuerySrc)<<2)); //*(sourceAddr+i + ((numOfSrc - 1 - numOfQuerySrc)<<2)) = *(tmpAddress+i); *(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc - 1 - numOfQuerySrc))); *(sourceAddr+i + ((numOfSrc - 1 - numOfQuerySrc))) = *(tmpAddress+i); #else *(sourceAddr+i) = *(sourceAddr+i + ((numOfSrc-j-1))); *(sourceAddr+i + ((numOfSrc-j-1))) = *(tmpAddress+i); #endif } } #endif j--; numOfSrc--; numOfQuerySrc++; continue; //no need to move sourceAddr } else { if (ipVersion==IP_VERSION4) { //querySourceAddr DEBUG("Block.GIP.Clt.SrcIP("IP4D") no in A*B",NIP4QUAD(sourceAddr));//// } #ifdef CONFIG_RG_MLD_SNOOPING else { DEBUG("Block.GIP6.Clt.SrcIP6("IP6H") no in A*B",NIP6QUAD(sourceAddr));//// } #endif } if (ipVersion==IP_VERSION4) { sourceAddr++; } #ifdef CONFIG_RG_MLD_SNOOPING else { sourceAddr=sourceAddr+4; } #endif DEBUG(""); } #if 0 if (ipVersion==IP_VERSION4) { int i ; for (i=0; i<numOfQuerySrc; i++) { DEBUG("Query GIP("IP4D")-SrcIP("IP4D")", NIP4QUAD(groupAddress), NIP4QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; rtl_igmpQueryTimerExpired(0, 3, (char *)groupAddress, numOfQuerySrc, NULL, (char *)sourceAddr); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; for (i=0; i<numOfQuerySrc; i+=4) { DEBUG("Query GIP6("IP6H")-SrcIP("IP6H")", NIP6QUAD(groupAddress), NIP6QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; ??????????????????????????????????????????????? rtl_mldQueryTimerExpired(0); } #endif #endif } if (ipVersion==IP_VERSION4) { int i ; for (i=0; i<numOfQuerySrc; i++) { DEBUG("Query GIP("IP4D")-SrcIP("IP4D")", NIP4QUAD(groupAddress), NIP4QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; rtl_igmpQueryTimerExpired(0, IGMP_V3, (char *)groupAddress, numOfQuerySrc, NULL, (char *)sourceAddr); } #ifdef CONFIG_RG_MLD_SNOOPING else { int i ; for (i=0; i<numOfQuerySrc; i+=4) { DEBUG("Query GIP6("IP6H")-SrcIP("IP6H")", NIP6QUAD(groupAddress), NIP6QUAD((sourceAddr+i))); } //IGMPQueryVersion=3; ??????????????????????????????????????????????? rtl_mldQueryTimerExpired(0); } #endif out: reportEventContext.ipVersion=ipVersion; reportEventContext.vlanId=rg_db.pktHdr->internalVlanID; #ifdef CONFIG_RG_MLD_SNOOPING reportEventContext.groupAddr[0]=groupAddress[0]; reportEventContext.groupAddr[1]=groupAddress[1]; reportEventContext.groupAddr[2]=groupAddress[2]; reportEventContext.groupAddr[3]=groupAddress[3]; #else reportEventContext.groupAddr[0]=groupAddress[0]; #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); if(rtl_mCastModuleArray[moduleIndex].enableFastLeave==TRUE) { //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); #ifndef CONFIG_RG_SIMPLE_IGMP_v3 rtl_handle_igmpgroup_change(&reportEventContext); #else rtl_handle_igmpgroup_change_v3(&reportEventContext); #endif } } #endif return SUCCESS; } static uint32 rtl_processIgmpv3Mldv2Reports(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8 *pktBuf) { uint32 i=0; uint16 numOfRecords=0; uint8 *groupRecords=NULL; uint8 recordType=0xff; uint16 numOfSrc=0; int32 returnVal=0; uint32 multicastRouterPortMask=rtl_getMulticastRouterPortMask(moduleIndex, ipVersion, rtl_sysUpSeconds); IGMP("IGMPv3/MLDv2 Report packet"); if (ipVersion==IP_VERSION4) { numOfRecords=ntohs(((struct igmpv3Report *)pktBuf)->numOfRecords); if (numOfRecords!=0) { groupRecords=(uint8 *)(&(((struct igmpv3Report *)pktBuf)->recordList)); } } #ifdef CONFIG_RG_MLD_SNOOPING else { numOfRecords=ntohs(((struct mldv2Report *)pktBuf)->numOfRecords); if (numOfRecords!=0) { groupRecords=(uint8 *)(&(((struct mldv2Report *)pktBuf)->recordList)); } } #endif IGMP("numOfRecords=%d", numOfRecords); if ((1<<portNum)&(~rg_db.systemGlobal.igmpReportIngressPortmask)) { rg_db.pktHdr->ingressIgmpMldDrop = 1; return 0; } for (i=0; i<numOfRecords; i++) { if (ipVersion==IP_VERSION4) { recordType=((struct groupRecord *)groupRecords)->type; } #ifdef CONFIG_RG_MLD_SNOOPING else { recordType=((struct mCastAddrRecord *)groupRecords)->type; } #endif switch (recordType) { case MODE_IS_INCLUDE: returnVal=rtl_processIsInclude(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, groupRecords); break; case MODE_IS_EXCLUDE: returnVal=rtl_processIsExclude(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, groupRecords); break; case CHANGE_TO_INCLUDE_MODE: returnVal=rtl_processToInclude(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, groupRecords); break; case CHANGE_TO_EXCLUDE_MODE: returnVal=rtl_processToExclude(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, groupRecords); break; case ALLOW_NEW_SOURCES: returnVal=rtl_processAllow(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, groupRecords); break; case BLOCK_OLD_SOURCES: returnVal=rtl_processBlock(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr ,groupRecords); break; default:break; } if (ipVersion==IP_VERSION4) { numOfSrc=ntohs(((struct groupRecord *)groupRecords)->numOfSrc); /*shift pointer to another group record*/ groupRecords=groupRecords+8+numOfSrc*4+(((struct groupRecord *)(groupRecords))->auxLen)*4; } #ifdef CONFIG_RG_MLD_SNOOPING else { numOfSrc=ntohs(((struct mCastAddrRecord *)groupRecords)->numOfSrc); /*shift pointer to another group record*/ groupRecords=groupRecords+20+numOfSrc*16+(((struct mCastAddrRecord *)(groupRecords))->auxLen)*4; } #endif } return (multicastRouterPortMask&(~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static uint32 rtl_processIgmpMld(uint32 moduleIndex, rtk_rg_pktHdr_t *pPktHdr, uint32 ipVersion, uint32 portNum, uint32 wlan_dev_idx, uint32 *clientAddr, uint8* pktBuf, uint32 pktLen) { uint32 fwdPortMask=0; IGMP("pktLen=%d", pktLen); IGMP("%02x %02x %02x %02x-%02x %02x %02x %02x",pktBuf[ 0],pktBuf[ 1],pktBuf[ 2],pktBuf[ 3],pktBuf[ 4],pktBuf[ 5],pktBuf[ 6],pktBuf[ 7]); IGMP("%02x %02x %02x %02x-%02x %02x %02x %02x",pktBuf[ 8],pktBuf[ 9],pktBuf[10],pktBuf[11],pktBuf[12],pktBuf[13],pktBuf[14],pktBuf[15]); IGMP(""); IGMP("%02x %02x %02x %02x-%02x %02x %02x %02x",pktBuf[16],pktBuf[17],pktBuf[18],pktBuf[19],pktBuf[20],pktBuf[21],pktBuf[22],pktBuf[23]); IGMP("%02x %02x %02x %02x-%02x %02x %02x %02x",pktBuf[24],pktBuf[25],pktBuf[26],pktBuf[27],pktBuf[28],pktBuf[29],pktBuf[30],pktBuf[31]); reportEventContext.moduleIndex=moduleIndex; switch (pktBuf[0]) { case IGMP_QUERY: IGMP("IGMP Queries"); fwdPortMask=rtl_processQueries(moduleIndex, pPktHdr, ipVersion, portNum, wlan_dev_idx, pktBuf, pktLen); break; case IGMPV1_REPORT: IGMP("IGMPv1 Report"); rg_db.pktHdr->IGMPType=pktBuf[0]; DEBUG("copy IGMPtype(0x%x) to pktHdr",rg_db.pktHdr->IGMPType); fwdPortMask=rtl_processJoin(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr,pktBuf); break; case IGMPV2_REPORT: IGMP("IGMPv2 Report"); rg_db.pktHdr->IGMPType=pktBuf[0]; DEBUG("copy IGMPtype(0x%x) to pktHdr",rg_db.pktHdr->IGMPType); fwdPortMask=rtl_processJoin(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, pktBuf); break; case IGMPV2_LEAVE: IGMP("IGMPv2 Leave"); fwdPortMask=rtl_processLeave(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr,pktBuf); break; case IGMPV3_REPORT: IGMP("IGMPv3 Report"); fwdPortMask=rtl_processIgmpv3Mldv2Reports(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, pktBuf); break; case MLD_QUERY: IGMP("MLD Query"); fwdPortMask=rtl_processQueries(moduleIndex, pPktHdr, ipVersion, portNum, wlan_dev_idx, pktBuf, pktLen); break; case MLDV1_REPORT: IGMP("MLDv1 Report"); fwdPortMask=rtl_processJoin(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, pktBuf); break; case MLDV1_DONE: IGMP("MLDv1 Done"); fwdPortMask=rtl_processLeave(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, pktBuf); break; case MLDV2_REPORT: IGMP("MLDv2 Report"); fwdPortMask=rtl_processIgmpv3Mldv2Reports(moduleIndex, ipVersion, portNum, wlan_dev_idx, clientAddr, pktBuf); break; default: fwdPortMask=((~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); IGMP("fwdPortMask=0x%x",fwdPortMask); break; } return fwdPortMask; } static uint32 rtl_processDvmrp(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen) { IGMP("process Router Dvmrp packet"); { rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.dvmrpRouter.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.dvmrpRouterAgingTime; /*update timer*/ } { reportEventContext.ipVersion=ipVersion; reportEventContext.groupAddr[0]=0; reportEventContext.groupAddr[1]=0; reportEventContext.groupAddr[2]=0; reportEventContext.groupAddr[3]=0; #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) /*we only support ipv4 hardware multicast*/ strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); #endif } return ((~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static uint32 rtl_processMospf(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen) { struct ipv4MospfHdr *ipv4MospfHeader=(struct ipv4MospfHdr*)pktBuf; struct ipv4MospfHello *ipv4HelloPkt=(struct ipv4MospfHello*)pktBuf; #ifdef CONFIG_RG_MLD_SNOOPING struct ipv6MospfHdr *ipv6MospfHeader=(struct ipv6MospfHdr*)pktBuf; struct ipv6MospfHello *ipv6HelloPkt=(struct ipv6MospfHello*)pktBuf; #endif IGMP("process Router Mospf packet"); if(ipVersion==IP_VERSION4) { /*mospf is built based on ospfv2*/ if((ipv4MospfHeader->version==2) && (ipv4MospfHeader->type==MOSPF_HELLO_TYPE)) { if((ipv4HelloPkt->options & 0x04)!=0) { rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.mospfRouter.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.mospfRouterAgingTime; /*update timer*/ } } } #ifdef CONFIG_RG_MLD_SNOOPING else { if((ipv6MospfHeader->version==3) && (ipv6MospfHeader->type==MOSPF_HELLO_TYPE)) { if((ipv6HelloPkt->options[2] & 0x04)!=0) { rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.mospfRouter.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.mospfRouterAgingTime; /*update timer*/ } } } #endif reportEventContext.ipVersion=ipVersion; reportEventContext.groupAddr[0]=0; reportEventContext.groupAddr[1]=0; reportEventContext.groupAddr[2]=0; reportEventContext.groupAddr[3]=0; #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); } #endif return ((~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } static uint32 rtl_processPim(uint32 moduleIndex, uint32 ipVersion, uint32 portNum, uint8* pktBuf, uint32 pktLen) { IGMP("process Router PIM packet"); if(ipVersion==IP_VERSION4) { rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters.pimRouter.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.pimRouterAgingTime; /*update timer*/ } #ifdef CONFIG_RG_MLD_SNOOPING else { rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters.pimRouter.portTimer[portNum]=rtl_sysUpSeconds+rtl_mCastTimerParas.pimRouterAgingTime; /*update timer*/ } #endif reportEventContext.ipVersion=ipVersion; reportEventContext.groupAddr[0]=0; reportEventContext.groupAddr[1]=0; reportEventContext.groupAddr[2]=0; reportEventContext.groupAddr[3]=0; #ifdef CONFIG_RECORD_MCAST_FLOW rtl_invalidateMCastFlow(reportEventContext.moduleIndex, reportEventContext.ipVersion, reportEventContext.groupAddr); #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) { strcpy(reportEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &reportEventContext); rtl_handle_igmpgroup_change(&reportEventContext); } #endif return ((~(1<<portNum))&((1<<MAX_SUPPORT_PORT_NUMBER)-1)); } /********************************************* External Function *********************************************/ //External called function by high level program int32 rtl_registerIgmpSnoopingModule(uint32 *moduleIndex) { int32 i=0; uint32 index=0xFFFFFFFF; *moduleIndex=0xFFFFFFFF; for (i=0; i<MAX_MCAST_MODULE_NUM; i++) { if (rtl_mCastModuleArray[i].enableSnooping==FALSE) { index=i; break; } } if (i>=MAX_MCAST_MODULE_NUM) { IGMP("register IgmpSnooping Module Fail"); return FAIL; } IGMP("register IgmpSnooping Module [%d]", i); if (rtl_mCastModuleArray[index].enableSnooping==FALSE) { /*initialize multicast Routers information*/ for (i=0; i<MAX_SUPPORT_PORT_NUMBER; i++) { rtl_mCastModuleArray[index].rtl_ipv4MulticastRouters.querier.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv4MulticastRouters.dvmrpRouter.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv4MulticastRouters.pimRouter.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv4MulticastRouters.mospfRouter.portTimer[i]=0; #ifdef CONFIG_RG_MLD_SNOOPING rtl_mCastModuleArray[index].rtl_ipv6MulticastRouters.querier.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv6MulticastRouters.dvmrpRouter.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv6MulticastRouters.pimRouter.portTimer[i]=0; rtl_mCastModuleArray[index].rtl_ipv6MulticastRouters.mospfRouter.portTimer[i]=0; #endif } /*initialize hash table*/ rtl_initHashTable(index, rtl_hashTableSize); if((rtl_mCastModuleArray[index].rtl_ipv4HashTable==NULL) ) { return FAIL; } #ifdef CONFIG_RG_MLD_SNOOPING if(rtl_mCastModuleArray[index].rtl_ipv6HashTable==NULL) { return FAIL; } #endif #if defined (CONFIG_RG_HARDWARE_MULTICAST) memset(&rtl_mCastModuleArray[index].deviceInfo,0, sizeof(rtl_multicastDeviceInfo_t)); #endif for(i=0; i<6; i++) { rtl_mCastModuleArray[index].rtl_gatewayMac[i]=0; } rtl_mCastModuleArray[index]. rtl_gatewayIpv4Addr=0; #ifdef CONFIG_RG_MLD_SNOOPING for(i=0; i<4; i++) { rtl_mCastModuleArray[index].rtl_gatewayIpv6Addr[i]=0; } #endif rtl_mCastModuleArray[index].enableFastLeave=FALSE; rtl_mCastModuleArray[index].enableSnooping=TRUE; rtl_mCastModuleArray[index].unknownMCastFloodMap=0; rtl_mCastModuleArray[index].staticRouterPortMask=0; #ifdef CONFIG_PROC_FS rtl_mCastModuleArray[index].expireEventCnt=0; #endif *moduleIndex=index; return SUCCESS; } else { return FAIL; } } int32 rtl_unregisterIgmpSnoopingModule(uint32 moduleIndex) { uint32 i=0; struct rtl_groupEntry *groupEntryPtr=NULL; #ifdef CONFIG_RECORD_MCAST_FLOW struct rtl_mcastFlowEntry *mcastFlowEntryPtr=NULL; #endif IGMP("unregister IgmpSnooping Module[%d]", moduleIndex); if (moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if (rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv4Addr=0; for (i=0; i<6; i++) { rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[i]=0; } #ifdef CONFIG_RG_MLD_SNOOPING for (i=0;i<4;i++) { rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[i]=0; } #endif /*delete ipv4 multicast entry*/ for (i=0;i<rtl_hashTableSize;i++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[i]; while(groupEntryPtr!=NULL) { rtl_deleteGroupEntry(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[i]; } } rtk_rg_free(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable=NULL; memset(&(rtl_mCastModuleArray[moduleIndex].rtl_ipv4MulticastRouters), 0, sizeof(struct rtl_multicastRouters)); #ifdef CONFIG_RG_MLD_SNOOPING /*delete ipv6 multicast entry*/ for(i=0; i<rtl_hashTableSize; i++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[i]; while(groupEntryPtr!=NULL) { rtl_deleteGroupEntry(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[i]; } } rtk_rg_free(rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable=NULL; memset(&(rtl_mCastModuleArray[moduleIndex].rtl_ipv6MulticastRouters), 0, sizeof(struct rtl_multicastRouters)); #endif #ifdef CONFIG_RECORD_MCAST_FLOW /*delete multicast flow entry*/ for (i=0;i<rtl_hashTableSize;i++) { mcastFlowEntryPtr=rtl_mCastModuleArray[moduleIndex].flowHashTable[i]; while(mcastFlowEntryPtr!=NULL) { rtl_deleteMcastFlowEntry(mcastFlowEntryPtr, rtl_mCastModuleArray[moduleIndex].flowHashTable); mcastFlowEntryPtr=rtl_mCastModuleArray[moduleIndex].flowHashTable[i]; } } rtk_rg_free(rtl_mCastModuleArray[moduleIndex].flowHashTable); rtl_mCastModuleArray[moduleIndex].flowHashTable=NULL; #endif rtl_mCastModuleArray[moduleIndex].enableSnooping=FALSE; rtl_mCastModuleArray[moduleIndex].enableFastLeave=FALSE; rtl_mCastModuleArray[moduleIndex].unknownMCastFloodMap=0; rtl_mCastModuleArray[moduleIndex].staticRouterPortMask=0; #if defined (CONFIG_RG_HARDWARE_MULTICAST) memset(&rtl_mCastModuleArray[moduleIndex].deviceInfo,0,sizeof(rtl_multicastDeviceInfo_t)); #endif return SUCCESS; } return SUCCESS; } static void _rtl865x_configIgmpSnoopingExpire(int32 disableExpire) { uint32 maxTime=0xffffffff; //IGMP("got in _rtl865x_configIgmpSnoopingExpire"); if((rtl_mCastTimerParas.disableExpire==FALSE) && (disableExpire==TRUE)) { rtl_mCastTimerParas.disableExpire=TRUE; } if((rtl_mCastTimerParas.disableExpire==TRUE) && (disableExpire==FALSE) ) { //#if 0 #if defined(__linux__) && defined(__KERNEL__) //struct timeval currentTimeVector; //do_gettimeofday(¤tTimeVector); /*reset start time*/ // if(currentTimeVector.tv_sec>=rtl_sysUpSeconds) if(rtk_rg_getTimeSec()>=rtl_sysUpSeconds) { rtl_startTime=(uint32)(rtk_rg_getTimeSec())-rtl_sysUpSeconds; } else { /*avoid timer wrap back*/ rtl_startTime=maxTime-rtl_sysUpSeconds+(uint32)(rtk_rg_getTimeSec())+1; } #endif rtl_mCastTimerParas.disableExpire=FALSE; } return; } //External called function by high level program void rtl_setMulticastParameters(struct rtl_mCastTimerParameters mCastTimerParameters) { //IGMP("got in rtl_mCastTimerParameters"); _rtl865x_configIgmpSnoopingExpire(mCastTimerParameters.disableExpire); if(mCastTimerParameters.groupMemberAgingTime!=0) { rtl_mCastTimerParas.groupMemberAgingTime= mCastTimerParameters.groupMemberAgingTime; } if(mCastTimerParameters.lastMemberAgingTime!=0) { rtl_mCastTimerParas.lastMemberAgingTime= mCastTimerParameters.lastMemberAgingTime; } if(mCastTimerParameters.querierPresentInterval!=0) { rtl_mCastTimerParas.querierPresentInterval=mCastTimerParameters.querierPresentInterval; } if(mCastTimerParameters.dvmrpRouterAgingTime!=0) { rtl_mCastTimerParas.dvmrpRouterAgingTime=mCastTimerParameters.dvmrpRouterAgingTime; } if(mCastTimerParameters.mospfRouterAgingTime!=0) { rtl_mCastTimerParas.mospfRouterAgingTime=mCastTimerParameters.mospfRouterAgingTime; } if(mCastTimerParameters.pimRouterAgingTime!=0) { rtl_mCastTimerParas.pimRouterAgingTime=mCastTimerParameters.pimRouterAgingTime; } return; } int32 rtl_configIgmpSnoopingModule(uint32 moduleIndex, struct rtl_mCastSnoopingLocalConfig *mCastSnoopingLocalConfig) { //IGMP("got in rtl_configIgmpSnoopingModule"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(mCastSnoopingLocalConfig==NULL) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } rtl_mCastModuleArray[moduleIndex].enableFastLeave=mCastSnoopingLocalConfig->enableFastLeave; rtl_mCastModuleArray[moduleIndex].unknownMCastFloodMap=mCastSnoopingLocalConfig->unknownMcastFloodMap; rtl_mCastModuleArray[moduleIndex].staticRouterPortMask=mCastSnoopingLocalConfig->staticRouterPortMask; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[0]=mCastSnoopingLocalConfig->gatewayMac[0]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[1]=mCastSnoopingLocalConfig->gatewayMac[1]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[2]=mCastSnoopingLocalConfig->gatewayMac[2]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[3]=mCastSnoopingLocalConfig->gatewayMac[3]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[4]=mCastSnoopingLocalConfig->gatewayMac[4]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayMac[5]=mCastSnoopingLocalConfig->gatewayMac[5]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv4Addr=mCastSnoopingLocalConfig->gatewayIpv4Addr; #ifdef CONFIG_RG_MLD_SNOOPING rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[0]=mCastSnoopingLocalConfig->gatewayIpv6Addr[0]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[1]=mCastSnoopingLocalConfig->gatewayIpv6Addr[1]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[2]=mCastSnoopingLocalConfig->gatewayIpv6Addr[2]; rtl_mCastModuleArray[moduleIndex].rtl_gatewayIpv6Addr[3]=mCastSnoopingLocalConfig->gatewayIpv6Addr[3]; #endif return SUCCESS; } /* @func int32 | rtl_maintainMulticastSnoopingTimerList | Multicast snooping timer list maintenance function. @parm uint32 | currentSystemTime |The current system time (unit: seconds). @rvalue SUCCESS | Always return SUCCESS. @comm This function should be called once a second to maintain multicast timer list. */ int32 rtl_maintainMulticastSnoopingTimerList(uint32 currentSystemTime) { /* maintain current time */ uint32 i=0; uint32 maxTime=0xffffffff; struct rtl_groupEntry* groupEntryPtr=NULL; struct rtl_groupEntry* nextEntry=NULL; uint32 moduleIndex; //DEBUG("In rtl_maintainMulticastSnoopingTimerList"); #ifdef CONFIG_RECORD_MCAST_FLOW for(moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM; moduleIndex++) { if(rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { if((currentSystemTime%DEFAULT_MCAST_FLOW_EXPIRE_TIME)==0) { rtl_doMcastFlowRecycle(moduleIndex, BOTH_IPV4_IPV6); } } } #endif if(rtl_mCastTimerParas.disableExpire==TRUE) { return SUCCESS; } /*handle timer conter overflow*/ if(currentSystemTime>rtl_startTime) { rtl_sysUpSeconds=currentSystemTime-rtl_startTime; } else { rtl_sysUpSeconds=(maxTime-rtl_startTime)+currentSystemTime+1; } for(moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM; moduleIndex++) { if(rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { #if defined (CONFIG_RG_HARDWARE_MULTICAST) strcpy(timerEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); timerEventContext.moduleIndex=moduleIndex; #endif /*maintain ipv4 group entry timer */ for(i=0; i<rtl_hashTableSize; i++) { /*scan the hash table*/ if(rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable!=NULL) { timerEventContext.ipVersion=IP_VERSION4; groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[i]; while(groupEntryPtr) /*traverse each group list*/ { nextEntry=groupEntryPtr->next; timerEventContext.vlanId=groupEntryPtr->vlanId; timerEventContext.groupAddr[0]=groupEntryPtr->groupAddr[0]; timerEventContext.groupAddr[1]=0; timerEventContext.groupAddr[2]=0; timerEventContext.groupAddr[3]=0; //timerEventContext.srcFilterMode=groupEntryPtr->srcFilterMode; //// rtl_checkGroupEntryTimer(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable); groupEntryPtr=nextEntry;/*because expired group entry will be cleared*/ } } } #ifdef CONFIG_RG_MLD_SNOOPING /*maintain ipv6 group entry timer */ for(i=0; i<rtl_hashTableSize; i++) { /*scan the hash table*/ if(rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable!=NULL) { timerEventContext.ipVersion=IP_VERSION6; groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[i]; while(groupEntryPtr) /*traverse each group list*/ { nextEntry=groupEntryPtr->next; timerEventContext.vlanId=groupEntryPtr->vlanId; timerEventContext.groupAddr[0]=groupEntryPtr->groupAddr[0]; timerEventContext.groupAddr[1]=groupEntryPtr->groupAddr[1]; timerEventContext.groupAddr[2]=groupEntryPtr->groupAddr[2]; timerEventContext.groupAddr[3]=groupEntryPtr->groupAddr[3]; //timerEventContext.srcFilterMode=groupEntryPtr->srcFilterMode; //// rtl_checkGroupEntryTimer(groupEntryPtr, rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable); groupEntryPtr=nextEntry;/*because expired group entry will be cleared*/ } } } #endif } } return SUCCESS; } int32 rtl_getQueryPortMask(uint32 moduleIndex, rtk_rg_pktHdr_t * pPktHdr, uint32 *fwdPortMask, uint32 *fwdMbssidMask) { int j; *fwdPortMask=0; *fwdMbssidMask=0; if(moduleIndex>=MAX_MCAST_MODULE_NUM) { TRACE("Error: IGMP module id is invalid"); return FAIL; } if (pPktHdr->IGMPQueryVer<IGMP_V1 || pPktHdr->IGMPQueryVer>=IGMP_MLD_VER_MAX) { TRACE("Error: Unknown Query Version"); return FAIL; } if (pPktHdr->IGMPQueryVer>=MLD_V1) IGMP("IGMPQueryVer=MLD_V%d", pPktHdr->IGMPQueryVer-MLD_V1+1); else IGMP("IGMPQueryVer=IGMP_V%d", pPktHdr->IGMPQueryVer-IGMP_V1+1); for (j=0; j<RTK_RG_MAX_MAC_PORT; j++) { if (igmpSnoopingCounterVer_Port[j][pPktHdr->IGMPQueryVer-IGMP_V1]) { *fwdPortMask |= (1<<j); } DEBUG("igmpSnoopingCounterVer_Port[%d][%d]=%d", j, pPktHdr->IGMPQueryVer-IGMP_V1, igmpSnoopingCounterVer_Port[j][pPktHdr->IGMPQueryVer-IGMP_V1]); } IGMP("igmpSnoopingVer[%d] PortMask=0x%x", j, pPktHdr->IGMPQueryVer-IGMP_V1+1, *fwdPortMask); #ifdef CONFIG_MASTER_WLAN0_ENABLE for (j=0; j<MAX_WLAN_DEVICE_NUM; j++) { if (igmpSnoopingCounterVer_MBSSID[j][pPktHdr->IGMPQueryVer-IGMP_V1]) { *fwdMbssidMask |= (1<<j); } DEBUG("igmpSnoopingCounterVer_MBSSID[%d][%d]=%d", j, pPktHdr->IGMPQueryVer-IGMP_V1, igmpSnoopingCounterVer_MBSSID[j][pPktHdr->IGMPQueryVer-IGMP_V1]); } IGMP("igmpSnoopingVer[%d] MBSSIDMask=0x%x", j, pPktHdr->IGMPQueryVer-IGMP_V1+1, *fwdPortMask); #endif /*if (pPktHdr->ingressPort) RTK_RG_MAC_PORT_CPU *fwdPortMask &= (~(1<<portNum)); */ return SUCCESS; } int32 rtl_igmpMldProcess(uint32 moduleIndex, uint8 *macFrame, rtk_rg_pktHdr_t *pPktHdr, uint32 portNum, uint32 *fwdPortMask) { struct rtl_macFrameInfo macFrameInfo; IGMP("IGMP&MLD Process(moduleIndex:%d portIdx=%d, wlanDevIdx=%d)\n",moduleIndex, portNum, pPktHdr->wlan_dev_idx); #if defined (CONFIG_RG_HARDWARE_MULTICAST) reportEventContext.portMask=1<<portNum; #endif *fwdPortMask=(~(1<<portNum)) & 0xFFFFFFFF; if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } //rtl_parseMacFrame(moduleIndex, macFrame, pPktHdr, TRUE, &macFrameInfo); rtl_parseMacFrame(moduleIndex, macFrame, pPktHdr, FALSE, &macFrameInfo); if (rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { if(macFrameInfo.ipBuf==NULL) { return FAIL; } if((macFrameInfo.ipVersion!=IP_VERSION4) && (macFrameInfo.ipVersion!=IP_VERSION6)) { return FAIL; } #ifndef CONFIG_RG_MLD_SNOOPING if (macFrameInfo.ipVersion==IP_VERSION6) { return FAIL; } #endif /*port num starts from 0*/ if(portNum>=MAX_SUPPORT_PORT_NUMBER) { return FAIL; } if(macFrameInfo.checksumFlag!=SUCCESS) { return FAIL; } switch(macFrameInfo.l3Protocol) { case IGMP_PROTOCOL: IGMP("process IGMP"); /*#ifdef CONFIG_MASTER_WLAN0_ENABLE #if 0 if (portNum == RTK_RG_EXT_PORT0 || portNum == RTK_RG_EXT_PORT1) { rtk_rg_lookupIdxReturn_t retIdx=_rtk_rg_wlanMbssidLookup(pPktHdr->pSmac, &wlan_dev_idx); if(retIdx==RG_RET_LOOKUPIDX_NOT_FOUND) { WARNING("Error: MBSSID had not learned!!"); } } #else wlan_dev_idx = pPktHdr->wlan_dev_idx; IGMP("the wlan device is from %d",wlan_dev_idx); #endif #endif */ #if defined(CONFIG_RTL9600_SERIES) if (pPktHdr->tagif & PPPOE_TAGIF) { //if(macFrameInfo.l3PktBuf[0] ==IGMP_QUERY) pPktHdr->ipv4Dip = 0xe0000001; //switch ((skb->data + pPktHdr->l3Offset + pPktHdr->ipv4HeaderLen)[0]) switch ((macFrame + pPktHdr->l3Offset + pPktHdr->ipv4HeaderLen)[0]) { case IGMP_QUERY: TRACE("old cs(%x)", *pPktHdr->pIpv4Checksum); //pPktHdr->ipv4Dip = 0xe0000001; pPktHdr->pIpv4Dip[0] = 0xe0000001; if (pPktHdr->pDmac[0]==0x01 && pPktHdr->pDmac[1]==0x00 && pPktHdr->pDmac[2]==0x5e) { pPktHdr->pDmac[3]=0; pPktHdr->pDmac[4]=0; pPktHdr->pDmac[5]=1; } pPktHdr->tagif |= IGMP_TAGIF; TRACE("Modify packet to formal query"); *pPktHdr->pIpv4Checksum=htons(_rtk_rg_fwdengine_L3checksumUpdate(*pPktHdr->pIpv4Checksum,pPktHdr->ipv4Dip,pPktHdr->ipv4TTL,pPktHdr->ipProtocol,ntohl(*pPktHdr->pIpv4Dip),*pPktHdr->pIpv4TTL)); TRACE("new cs(%x)", *pPktHdr->pIpv4Checksum); break; #if 0 case IGMPV1_REPORT: case IGMPV2_REPORT: TRACE("old cs(%x)", *pPktHdr->pIpv4Checksum); //pPktHdr->ipv4Dip = 0xe0000002; pPktHdr->pIpv4Dip[0] = 0xe0000002; if(pPktHdr->pDmac[0]==0x01 && pPktHdr->pDmac[1]==0x00 && pPktHdr->pDmac[2]==0x5e) { pPktHdr->pDmac[3]=0; pPktHdr->pDmac[4]=0; pPktHdr->pDmac[5]=2; } pPktHdr->tagif |= IGMP_TAGIF; TRACE("Modify packet to formal report"); *pPktHdr->pIpv4Checksum=htons(_rtk_rg_fwdengine_L3checksumUpdate(*pPktHdr->pIpv4Checksum,pPktHdr->ipv4Dip,pPktHdr->ipv4TTL,pPktHdr->ipProtocol,ntohl(*pPktHdr->pIpv4Dip),*pPktHdr->pIpv4TTL)); TRACE("new cs(%x)", *pPktHdr->pIpv4Checksum); break; #endif } //switch } //if #endif *fwdPortMask=rtl_processIgmpMld(moduleIndex, pPktHdr, (uint32)(macFrameInfo.ipVersion), portNum, pPktHdr->wlan_dev_idx, macFrameInfo.srcIpAddr, macFrameInfo.l3PktBuf, macFrameInfo.l3PktLen); break; case ICMP_PROTOCOL: IGMP("process MLD"); *fwdPortMask=rtl_processIgmpMld(moduleIndex, pPktHdr, (uint32)(macFrameInfo.ipVersion), portNum, pPktHdr->wlan_dev_idx, macFrameInfo.srcIpAddr, macFrameInfo.l3PktBuf, macFrameInfo.l3PktLen); break; case DVMRP_PROTOCOL: IGMP("process DVMRP"); *fwdPortMask=rtl_processDvmrp(moduleIndex, (uint32)(macFrameInfo.ipVersion), portNum, macFrameInfo.l3PktBuf, macFrameInfo.l3PktLen); break; case MOSPF_PROTOCOL: IGMP("process MOSPF"); *fwdPortMask=rtl_processMospf(moduleIndex, (uint32)(macFrameInfo.ipVersion), portNum, macFrameInfo.l3PktBuf, macFrameInfo.l3PktLen); break; case PIM_PROTOCOL: IGMP("process PIM"); *fwdPortMask=rtl_processPim(moduleIndex, (uint32)(macFrameInfo.ipVersion),portNum, macFrameInfo.l3PktBuf, macFrameInfo.l3PktLen); break; default: break; } } return SUCCESS; } #ifdef CONFIG_RECORD_MCAST_FLOW static int32 rtl_recordMcastFlow(uint32 moduleIndex,uint32 ipVersion, uint32 *sourceIpAddr, uint32 *groupAddr, struct rtl_multicastFwdInfo * multicastFwdInfo) { struct rtl_mcastFlowEntry *mcastFlowEntry=NULL; IGMP("got in rtl_recordMcastFlow"); if(multicastFwdInfo==NULL) { return FAIL; } #if defined(CONFIG_XDSL_NEW_HWNAT_DRIVER) if( ( (ipVersion==IP_VERSION4) && (sourceIpAddr[0]==0 || groupAddr[0]==0)) || ( (ipVersion==IP_VERSION6) && ((sourceIpAddr[0]==0 && sourceIpAddr[1]==0 && sourceIpAddr[2]==0 && sourceIpAddr[3]==0) || (groupAddr[0]==0 && groupAddr[1]==0 && groupAddr[2]==0 && groupAddr[3]==0)))) return FAIL; #endif mcastFlowEntry=rtl_searchMcastFlowEntry(moduleIndex, ipVersion, sourceIpAddr, groupAddr); if(mcastFlowEntry==NULL) { mcastFlowEntry=rtl_allocateMcastFlowEntry(); if(mcastFlowEntry==NULL) { rtl_doMcastFlowRecycle(moduleIndex, ipVersion); mcastFlowEntry=rtl_allocateMcastFlowEntry(); if(mcastFlowEntry==NULL) { rtlglue_printf("run out of multicast flow entry!\n"); return FAIL; } } if(ipVersion==IP_VERSION4) { mcastFlowEntry->serverAddr[0]=sourceIpAddr[0]; mcastFlowEntry->groupAddr[0]=groupAddr[0]; } #ifdef CONFIG_RG_MLD_SNOOPING else { mcastFlowEntry->serverAddr[0]=sourceIpAddr[0]; mcastFlowEntry->serverAddr[1]=sourceIpAddr[1]; mcastFlowEntry->serverAddr[2]=sourceIpAddr[2]; mcastFlowEntry->serverAddr[3]=sourceIpAddr[3]; mcastFlowEntry->groupAddr[0]=groupAddr[0]; mcastFlowEntry->groupAddr[1]=groupAddr[1]; mcastFlowEntry->groupAddr[2]=groupAddr[2]; mcastFlowEntry->groupAddr[3]=groupAddr[3]; } #endif mcastFlowEntry->ipVersion=ipVersion; memcpy(&mcastFlowEntry->multicastFwdInfo, multicastFwdInfo, sizeof(struct rtl_multicastFwdInfo )); mcastFlowEntry->refreshTime=rtl_sysUpSeconds; rtl_linkMcastFlowEntry(mcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); //return SUCCESS; } else { /*update forward port mask information */ memcpy(&mcastFlowEntry->multicastFwdInfo, multicastFwdInfo, sizeof(struct rtl_multicastFwdInfo )); mcastFlowEntry->refreshTime=rtl_sysUpSeconds; //return SUCCESS; } #if defined(CONFIG_XDSL_NEW_HWNAT_DRIVER) if(ipVersion==IP_VERSION4 && sourceIpAddr[0] && groupAddr[0]) { rtk_rg_table_v4multicast_t mcEntry; bzero(&mcEntry,sizeof(mcEntry)); mcEntry.dip = groupAddr[0]; mcEntry.sip = sourceIpAddr[0] ; mcEntry.port= rg_db.pktHdr->pRxDesc->rx_src_port_num; mcEntry.mbr = multicastFwdInfo ->fwdPortMask ; mcEntry.vaild = 1; RTK_MULTICAST_ADD(&mcEntry); } #endif return SUCCESS; } static void rtl_invalidateMCastFlow(uint32 moduleIndex,uint32 ipVersion, uint32 *groupAddr) { uint32 hashIndex; struct rtl_mcastFlowEntry* mcastFlowEntry = NULL; struct rtl_mcastFlowEntry* nextMcastFlowEntry = NULL; if (NULL==groupAddr) { return ; } hashIndex=rtl_igmpHashAlgorithm(ipVersion, groupAddr); mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[hashIndex]; while (mcastFlowEntry!=NULL) { nextMcastFlowEntry=mcastFlowEntry->next; if(ipVersion==mcastFlowEntry->ipVersion) { #ifdef CONFIG_RG_MLD_SNOOPING if ((groupAddr[0]==0)&&(groupAddr[1]==0)&&(groupAddr[2]==0)&&(groupAddr[3]==0)) #else if (groupAddr[0]==0) #endif { rtl_deleteMcastFlowEntry(mcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); } else { #ifdef CONFIG_RG_MLD_SNOOPING if ((mcastFlowEntry->groupAddr[0]==groupAddr[0])&&(mcastFlowEntry->groupAddr[1]==groupAddr[1])&& (mcastFlowEntry->groupAddr[2]==groupAddr[2])&&(mcastFlowEntry->groupAddr[3]==groupAddr[3])) #else if(mcastFlowEntry->groupAddr[0] == groupAddr[0]) #endif { rtl_deleteMcastFlowEntry(mcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); } } } mcastFlowEntry = nextMcastFlowEntry; } return ; } static void rtl_doMcastFlowRecycle(uint32 moduleIndex, uint32 ipVersion) { uint32 i; uint32 freeCnt=0; struct rtl_mcastFlowEntry* mcastFlowEntry = NULL; struct rtl_mcastFlowEntry* nextMcastFlowEntry = NULL; struct rtl_mcastFlowEntry* oldestMcastFlowEntry = NULL; for (i = 0 ; i < rtl_hashTableSize ; i++) { mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[i]; if (oldestMcastFlowEntry==NULL) { oldestMcastFlowEntry=mcastFlowEntry; } while (mcastFlowEntry!=NULL) { nextMcastFlowEntry=mcastFlowEntry->next; /*keep the most recently used entry*/ if ((mcastFlowEntry->refreshTime+DEFAULT_MCAST_FLOW_EXPIRE_TIME) < rtl_sysUpSeconds) { rtl_deleteMcastFlowEntry(mcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); freeCnt++; } mcastFlowEntry=nextMcastFlowEntry; } } if(freeCnt>0) { return; } /*if too many concurrent flow,we have to do LRU*/ for (i = 0 ; i < rtl_hashTableSize ; i++) { mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[i]; if (oldestMcastFlowEntry==NULL) { oldestMcastFlowEntry=mcastFlowEntry; } while (mcastFlowEntry!=NULL) { nextMcastFlowEntry=mcastFlowEntry->next; if (mcastFlowEntry->refreshTime < oldestMcastFlowEntry->refreshTime) { oldestMcastFlowEntry=mcastFlowEntry; } mcastFlowEntry=nextMcastFlowEntry; } } if (oldestMcastFlowEntry!=NULL) { rtl_deleteMcastFlowEntry(oldestMcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); } return ; } #endif int32 rtl_getMulticastDataFwdPortMask(uint32 moduleIndex, struct rtl_multicastDataInfo *multicastDataInfo, uint32 *fwdPortMask) { int32 retVal=FAIL; struct rtl_multicastFwdInfo multicastFwdInfo; //DEBUG("got in rtl_getMulticastDataFwdPortMask"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(multicastDataInfo==NULL) { return FAIL; } if(fwdPortMask==NULL) { return FAIL; } retVal=rtl_getMulticastDataFwdInfo( moduleIndex, multicastDataInfo, &multicastFwdInfo); *fwdPortMask=multicastFwdInfo.fwdPortMask; if(retVal==SUCCESS) { if(multicastFwdInfo.unknownMCast==TRUE) { return FAIL; } else { return SUCCESS; } } return FAIL; } /*ccwei- for debug*/ #define CCDBG 0 #if CCDBG #define DD_PRINT(fmt, args...) printk(fmt, ##args) #else #define DD_PRINT(fmt, args...) #endif int32 rtl_getMulticastDataFwdInfo(uint32 moduleIndex, struct rtl_multicastDataInfo *multicastDataInfo, struct rtl_multicastFwdInfo *multicastFwdInfo) { #ifdef CONFIG_RECORD_MCAST_FLOW struct rtl_mcastFlowEntry *mcastFlowEntry=NULL; #endif struct rtl_groupEntry * groupEntry=NULL; unsigned int blkPortMask=0; uint32 multicastRouterPortMask=0; DEBUG("in rtl_getMulticastDataFwdInfo"); if (moduleIndex>=MAX_MCAST_MODULE_NUM) { DEBUG("IGMP module index(%d) is invalid, return\n", moduleIndex); return FAIL; } if (multicastDataInfo==NULL) { DEBUG("multicastDataInfo is null, return\n"); return FAIL; } if (multicastFwdInfo==NULL) { DEBUG("multicastFwdInfo is null, return\n"); return FAIL; } memset(multicastFwdInfo, 0, sizeof(struct rtl_multicastFwdInfo)); if (multicastDataInfo->groupAddr[0]==RESERVE_MULTICAST_ADDR1) { /* implicit using RTK_RG_IPV4MC_DONT_CARE_SRC mode*/ multicastFwdInfo->reservedMCast=TRUE; multicastFwdInfo->fwdPortMask=0xFFFFFFFF; multicastFwdInfo->l2PortMask=0xFFFFFFFF; #ifdef CONFIG_MASTER_WLAN0_ENABLE multicastFwdInfo->wlan0DevMask=0xFFFFFFFF; #endif multicastFwdInfo->cpuFlag=TRUE; IGMP("reserved GIP(239.255.255.250), return\n"); return FAIL; } #if 0 if (IN_MULTICAST_RESV1(multicastDataInfo->groupAddr[0]) ) { multicastFwdInfo->reservedMCast=TRUE; multicastFwdInfo->fwdPortMask=0xFFFFFFFF; multicastFwdInfo->l2PortMask=0xFFFFFFFF; multicastFwdInfo->cpuFlag=TRUE; return FAIL; } #endif #ifdef CONFIG_RECORD_MCAST_FLOW mcastFlowEntry=rtl_searchMcastFlowEntry(moduleIndex, multicastDataInfo->ipVersion, multicastDataInfo->sourceIp, multicastDataInfo->groupAddr); if (mcastFlowEntry!=NULL) { memcpy(multicastFwdInfo, &mcastFlowEntry->multicastFwdInfo, sizeof(struct rtl_multicastFwdInfo)); return SUCCESS; } #endif groupEntry=rtl_searchGroupEntry(moduleIndex, multicastDataInfo->ipVersion, multicastDataInfo->groupAddr, multicastDataInfo->vlanId); if (groupEntry==NULL) { DEBUG("GIP had not recorded"); multicastFwdInfo->unknownMCast=TRUE; multicastFwdInfo->fwdPortMask= rtl_mCastModuleArray[moduleIndex].unknownMCastFloodMap; #if defined (CONFIG_RG_HARDWARE_MULTICAST) if((multicastFwdInfo->fwdPortMask & rtl_mCastModuleArray[moduleIndex].deviceInfo.swPortMask)!=0) { multicastFwdInfo->cpuFlag=TRUE; } #endif #if 1 if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==1) { multicastDataInfo->srcFilterMode=RTK_RG_IPV4MC_DONT_CARE_SRC; } else if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==2) { if (multicastDataInfo->ipVersion==IP_VERSION4) { //if v2 v1 don`t care source mode, else in/ex mode multicastDataInfo->srcFilterMode=RTK_RG_IPV4MC_INCLUDE; }else //IP_VERSION6 { multicastDataInfo->srcFilterMode=RTK_RG_IPV4MC_DONT_CARE_SRC; } } #endif DEBUG("set GIP IN-Mode & multicastFwdInfo->fwdPortMask=0x%X, return\n",multicastFwdInfo->fwdPortMask); return FAIL; } else { DEBUG("GIP had recorded"); /*here to get multicast router port mask and forward port mask*/ if ((rg_db.systemGlobal.initParam.igmpSnoopingEnable==1)||(multicastDataInfo->ipVersion==IP_VERSION6)) //#if 0 { //uint32 *sourceAddr = NULL; struct rtl_clientEntry * clientEntry=NULL; struct rtl_sourceEntry * sourceEntry=NULL; DEBUG("Decide GIP-SrcIP is Dc-Mo(path4-fwd)"); //// #if 0 //multicastRouterPortMask=rtl_getMulticastRouterPortMask(moduleIndex, multicastDataInfo->ipVersion, rtl_sysUpSeconds); multicastFwdInfo->fwdPortMask = rtl_getGroupSourceFwdPortMask(groupEntry, multicastDataInfo->sourceIp, rtl_sysUpSeconds); #else for (clientEntry=groupEntry->clientList; clientEntry!=NULL; clientEntry=clientEntry->next) { if (clientEntry->groupFilterTimer<=rtl_sysUpSeconds) /*include mode*/ { sourceEntry = clientEntry->sourceList; while (sourceEntry) { if (sourceEntry->portTimer>rtl_sysUpSeconds) { multicastFwdInfo->fwdPortMask |= (1<<clientEntry->portNum); DEBUG("add in-mo clt.port(%d)", clientEntry->portNum); //// break; } sourceEntry = sourceEntry->next; } } else /*exclude mode*/ { DEBUG("add ex-mo clt.port(%d)", clientEntry->portNum); //// multicastFwdInfo->fwdPortMask |= (1<<clientEntry->portNum); } } #endif multicastFwdInfo->srcFilterMode = RTK_RG_IPV4MC_DONT_CARE_SRC; } else if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==2) //#else { uint32 *sourceAddr = multicastDataInfo->sourceIp; struct rtl_clientEntry * clientEntry=NULL; struct rtl_sourceEntry * sourceEntry=NULL; DEBUG("Decide GIP-SrcIP is In-Mo(path3-fwd,grpTb-blk) / Ex-Mo(path3-fwd/blk,grpTb-fwd/blk)"); //// multicastFwdInfo->srcFilterMode = RTK_RG_IPV4MC_INCLUDE; for (clientEntry=groupEntry->clientList; clientEntry!=NULL; clientEntry=clientEntry->next) { sourceEntry=NULL; if (clientEntry->groupFilterTimer<=rtl_sysUpSeconds) /*include mode*/ { if (groupEntry->ipVersion == IP_VERSION4) //// DEBUG("GIP.Clt(" IP4D ") is <In-Mo>",NIP4QUAD(clientEntry->clientAddr));//// else//// DEBUG("GIP.Clt(" IP6H ") is <In-Mo>",NIP6QUAD(clientEntry->clientAddr));//// sourceEntry = rtl_searchSourceEntry(groupEntry->ipVersion, sourceAddr, clientEntry); if (sourceEntry!=NULL) { if (sourceEntry->portTimer>rtl_sysUpSeconds) { if (groupEntry->ipVersion == IP_VERSION4) //// DEBUG("GIP.SrcIP(" IP4D ") must be forward",NIP4QUAD(sourceAddr));//// else//// DEBUG("GIP.SrcIP(" IP6H ") must be forward",NIP6QUAD(sourceAddr));//// multicastFwdInfo->fwdPortMask |= (1<<clientEntry->portNum); #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum > RTK_RG_MAC_PORT_CPU) multicastFwdInfo->wlan0DevMask |= (1<<clientEntry->wlan_dev_idx); #endif continue; } } //blkPortMask |= (1<<clientEntry->portNum); //wrong //blkPortMask |= 0; //corret, but redundant } else /*exclude mode*/ { if (groupEntry->ipVersion == IP_VERSION4) //// DEBUG("GIP.Clt(" IP4D ") is <Ex-Mo>",NIP4QUAD(clientEntry->clientAddr));//// else//// DEBUG("GIP.Clt(" IP6H ") is <Ex-Mo>",NIP6QUAD(clientEntry->clientAddr));//// #if 0 if (groupEntry->clientList->sourceList == NULL) { multicastFwdInfo->srcFilterMode = RTK_RG_IPV4MC_DONT_CARE_SRC; DEBUG("GIP.Clt is <Ex-Mo> with empty source list",NIP6QUAD(clientEntry->clientAddr));//// DEBUG("GIP must be <Dc-Mo>, forward by GIP-only(path4)",NIP6QUAD(sourceAddr));//// break; //!!! must with rtl_getMulticastRouterPortMask } #endif multicastFwdInfo->srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; sourceEntry = rtl_searchSourceEntry(groupEntry->ipVersion, sourceAddr, clientEntry); if (sourceEntry == NULL) { if (groupEntry->ipVersion == IP_VERSION4) //// DEBUG("GIP.SrcIP(" IP4D ") must be forward",NIP4QUAD(sourceAddr));//// else//// DEBUG("GIP.SrcIP(" IP6H ") must be forward",NIP6QUAD(sourceAddr));//// multicastFwdInfo->fwdPortMask |= (1<<clientEntry->portNum); #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum > RTK_RG_MAC_PORT_CPU) multicastFwdInfo->wlan0DevMask |= (1<<clientEntry->wlan_dev_idx); #endif } else { if (sourceEntry->portTimer>rtl_sysUpSeconds) { if (groupEntry->ipVersion == IP_VERSION4) //// DEBUG("GIP.SrcIP(" IP4D ") must be forward",NIP4QUAD(sourceAddr));//// else//// DEBUG("GIP.SrcIP(" IP6H ") must be forward",NIP6QUAD(sourceAddr));//// multicastFwdInfo->fwdPortMask |= (1<<clientEntry->portNum); #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum > RTK_RG_MAC_PORT_CPU) multicastFwdInfo->wlan0DevMask |= (1<<clientEntry->wlan_dev_idx); #endif } else { //blkPortMask |= (1<<clientEntry->portNum); } //blkPortMask |= (1<<clientEntry->portNum); } blkPortMask |= (1<<clientEntry->portNum); #if 0 #if defined(CONFIG_RTL9600_SERIES) if (clientEntry->portNum>6) blkPortMask |= 0x40; //cpu port #elif defined(CONFIG_RTL9602C_SERIES) if (clientEntry->portNum>3) blkPortMask |= 0x8; //cpu port #endif #endif if (clientEntry->portNum>RTK_RG_MAC_PORT_CPU) blkPortMask |= (1<<RTK_RG_MAC_PORT_CPU); //cpu port } } //for if (multicastFwdInfo->srcFilterMode == RTK_RG_IPV4MC_EXCLUDE) //blkPortMask!=0 { //if (blkPortMask==multicastFwdInfo->fwdPortMask) { #if 0 //src from clt.src-list => 6266 path3 dc-mode, multicastFwdInfo->srcFilterMode = RTK_RG_IPV4MC_DONT_CARE_SRC; DEBUG("GIP : Dc-Mo"); #else /* multicastFwdInfo->l2PortMask = multicastFwdInfo->fwdPortMask; multicastFwdInfo->fwdPortMask = 0; api error*/ /* multicastFwdInfo->l2PortMask = 0; multicastFwdInfo->fwdPortMask = blkPortMask; still exclue*/ /*multicastFwdInfo->l2PortMask = 0; multicastFwdInfo->fwdPortMask = 0;*/ #endif DEBUG("GIP : Ex-Mo fwd src"); multicastFwdInfo->l2PortMask = multicastFwdInfo->fwdPortMask; multicastFwdInfo->fwdPortMask = blkPortMask; } /*else { DEBUG("GIP : Ex-Mo blk src"); multicastFwdInfo->l2PortMask = multicastFwdInfo->fwdPortMask; multicastFwdInfo->fwdPortMask = blkPortMask; }*/ }else{ //pure include mode DEBUG("GIP : In-Mo"); } } //#endif multicastFwdInfo->fwdPortMask = (multicastFwdInfo->fwdPortMask|multicastRouterPortMask); #if defined (CONFIG_RG_HARDWARE_MULTICAST) if ((multicastFwdInfo->fwdPortMask & rtl_mCastModuleArray[moduleIndex].deviceInfo.swPortMask)!=0) { multicastFwdInfo->cpuFlag=TRUE; } #endif #ifdef CONFIG_RECORD_MCAST_FLOW rtl_recordMcastFlow(moduleIndex,multicastDataInfo->ipVersion, multicastDataInfo->sourceIp, multicastDataInfo->groupAddr, multicastFwdInfo); #endif //DEBUG("multicastFwdInfo->fwdPortMask =0x%X\n",multicastFwdInfo->fwdPortMask); DEBUG("multicastFwdInfo->fwdPortMask =0x%X, multicastFwdInfo->l2PortMask =0x%X\n", multicastFwdInfo->fwdPortMask, multicastFwdInfo->l2PortMask); #ifdef CONFIG_MASTER_WLAN0_ENABLE DEBUG("multicastFwdInfo->fwdPortMask =0x%X, multicastFwdInfo->l2PortMask =0x%X, multicastFwdInfo->wlan0DevMask=0x%X\n", multicastFwdInfo->fwdPortMask, multicastFwdInfo->l2PortMask, multicastFwdInfo->wlan0DevMask); #else DEBUG("multicastFwdInfo->fwdPortMask =0x%X, multicastFwdInfo->l2PortMask =0x%X\n", multicastFwdInfo->fwdPortMask, multicastFwdInfo->l2PortMask); #endif return SUCCESS; } //if (group == NULL) DEBUG(""); return FAIL; } //#if 0 #if defined(__linux__) && defined(__KERNEL__) void rtl_multicastSysTimerExpired(uint32 expireDada) { //struct timeval currentTimeVector; //printk("[Timer rtl_multicastSysTimerExpired]\n"); system_expire_type = expireDada; //distinguid the timer is triggered by normal schedual(querierPresentInterval) or user force(/proc/rg/mcast_force_report_sec) //DEBUG("###Expire check by %s ###",system_expire_type?"USER FORCE":"NORMAL"); //do_gettimeofday(¤tTimeVector); //rtl_maintainMulticastSnoopingTimerList((uint32)(currentTimeVector.tv_sec)); rtl_maintainMulticastSnoopingTimerList((uint32)rtk_rg_getTimeSec()); if (system_expire_type==SYS_EXPIRED_NORMAL) mod_timer(&igmpSysTimer, jiffies+rg_db.systemGlobal.igmp_sys_timer_sec*CONFIG_HZ); } void rtl_multicastSysTimerInit(void) { //struct timeval startTimeVector; //do_gettimeofday(&startTimeVector); //rtl_startTime=(uint32)(startTimeVector.tv_sec); rtl_startTime=0;//(uint32)(startTimeVector.tv_sec); rtl_sysUpSeconds=0; lastjiffies=jiffies; init_timer(&igmpSysTimer); //igmpSysTimer.data=igmpSysTimer.expires; igmpSysTimer.data=SYS_EXPIRED_NORMAL; igmpSysTimer.expires=jiffies+rg_db.systemGlobal.igmp_sys_timer_sec*CONFIG_HZ; igmpSysTimer.function=(void*)rtl_multicastSysTimerExpired; //add_timer(&igmpSysTimer); //move to rg init. } static void rtl_multicastSysTimerDestroy(void) { del_timer(&igmpSysTimer); } #endif int32 rtl_getDeviceIgmpSnoopingModuleIndex(rtl_multicastDeviceInfo_t *devInfo,uint32 *moduleIndex) { int i; *moduleIndex=0xFFFFFFFF; if(devInfo==NULL) { return FAIL; } for(i=0; i<MAX_MCAST_MODULE_NUM; i++) { if(rtl_mCastModuleArray[i].enableSnooping==TRUE) { if(strcmp(rtl_mCastModuleArray[i].deviceInfo.devName, devInfo->devName)==0) { *moduleIndex=i; return SUCCESS; } } } return FAIL; } int32 rtl865x_getDeviceIgmpSnoopingModuleIndex(rtl_multicastDeviceInfo_t *devInfo,uint32 *moduleIndex) { return rtl_getDeviceIgmpSnoopingModuleIndex(devInfo,moduleIndex); } int32 rtl_setIgmpSnoopingModuleDevInfo(uint32 moduleIndex, rtl_multicastDeviceInfo_t *devInfo) { if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(devInfo==NULL) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } memcpy(&rtl_mCastModuleArray[moduleIndex].deviceInfo, devInfo, sizeof(rtl_multicastDeviceInfo_t)); return SUCCESS; } int32 rtl_getIgmpSnoopingModuleDevInfo(uint32 moduleIndex, rtl_multicastDeviceInfo_t *devInfo) { if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(devInfo==NULL) { return FAIL; } memset(devInfo,0,sizeof(rtl_multicastDeviceInfo_t)); if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } memcpy(devInfo,&rtl_mCastModuleArray[moduleIndex].deviceInfo, sizeof(rtl_multicastDeviceInfo_t)); return SUCCESS; } int32 rtl_setIgmpSnoopingModuleStaticRouterPortMask(uint32 moduleIndex,uint32 staticRouterPortMask) { //DEBUG("got in rtl_setIgmpSnoopingModuleStaticRouterPortMask"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } rtl_mCastModuleArray[moduleIndex].staticRouterPortMask=staticRouterPortMask; return SUCCESS; } int32 rtl_getIgmpSnoopingModuleStaticRouterPortMask(uint32 moduleIndex,uint32 *staticRouterPortMask) { //DEBUG("got in rtl_getIgmpSnoopingModuleStaticRouterPortMask"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(staticRouterPortMask==NULL) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } *staticRouterPortMask=rtl_mCastModuleArray[moduleIndex].staticRouterPortMask; return SUCCESS; } int32 rtl_setIgmpSnoopingModuleUnknownMCastFloodMap(uint32 moduleIndex,uint32 unknownMCastFloodMap) { //DEBUG("got in rtl_setIgmpSnoopingModuleUnknownMCastFloodMap"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } rtl_mCastModuleArray[moduleIndex].unknownMCastFloodMap=unknownMCastFloodMap; return SUCCESS; } int32 rtl_getIgmpSnoopingModuleUnknownMCastFloodMap(uint32 moduleIndex,uint32 *unknownMCastFloodMap) { //DEBUG("got in rtl_getIgmpSnoopingModuleUnknownMCastFloodMap"); if(moduleIndex>=MAX_MCAST_MODULE_NUM) { return FAIL; } if(unknownMCastFloodMap==NULL) { return FAIL; } if(rtl_mCastModuleArray[moduleIndex].enableSnooping==FALSE) { return FAIL; } *unknownMCastFloodMap=rtl_mCastModuleArray[moduleIndex].unknownMCastFloodMap; return SUCCESS; } #ifdef CONFIG_PROC_FS int igmp_show(struct seq_file *s, void *v) { int32 moduleIndex; int32 hashIndex,groupCnt,clientCnt; struct rtl_groupEntry *groupEntryPtr; struct rtl_clientEntry* clientEntry=NULL; struct rtl_sourceEntry *sourceEntryPtr; #ifdef CONFIG_RECORD_MCAST_FLOW int32 flowCnt; struct rtl_mcastFlowEntry *mcastFlowEntry=NULL; #endif int len=0; //PROC_PRINTF( "IGMP Snopping: %s\n",rg_db.systemGlobal.initParam.igmpSnoopingEnable?"on":"off"); switch (rg_db.systemGlobal.initParam.igmpSnoopingEnable) { case 0: PROC_PRINTF("IGMP Snopping: Off\n"); break; case 1: PROC_PRINTF("IGMP Snopping: Don`t Care Source\n"); break; case 2: PROC_PRINTF("IGMP Snopping: Care Source\n"); break; default:PROC_PRINTF("IGMP Snopping: Undefined Defined\n"); break; } /*PROC_PRINTF( "Multicast Protocol: %s\n",rg_db.systemGlobal.multicastProtocol==RG_MC_BOTH_IGMP_MLD?"IGMP and MLD": rg_db.systemGlobal.multicastProtocol==RG_MC_IGMP_ONLY?"IGMP Only":"MLD Only");*/ switch (rg_db.systemGlobal.multicastProtocol) { case RG_MC_BOTH_IGMP_MLD:PROC_PRINTF("Multicast Protocol: RG_MC_BOTH_IGMP_MLD\n"); break; case RG_MC_IGMP_ONLY :PROC_PRINTF("Multicast Protocol: RG_MC_BOTH_IGMP_ONLY\n"); break; case RG_MC_MLD_ONLY :PROC_PRINTF("Multicast Protocol: RG_MC_BOTH_MLD_ONLY\n"); break; default :PROC_PRINTF("Multicast Protocol: Undefined Defined\n"); break; } PROC_PRINTF( "fastLeave: %s\n",rtl_mCastModuleArray[rg_db.systemGlobal.nicIgmpModuleIndex].enableFastLeave?"on":"off"); PROC_PRINTF( "groupMemberAgingTime: %d\n",rtl_mCastTimerParas.groupMemberAgingTime); PROC_PRINTF( "lastMemberAgingTime: %d\n",rtl_mCastTimerParas.lastMemberAgingTime); PROC_PRINTF( "querierPresentInterval: %d\n",rtl_mCastTimerParas.querierPresentInterval); PROC_PRINTF( "dvmrpRouterAgingTime: %d\n",rtl_mCastTimerParas.dvmrpRouterAgingTime); PROC_PRINTF( "mospfRouterAgingTime: %d\n",rtl_mCastTimerParas.mospfRouterAgingTime); PROC_PRINTF( "pimRouterAgingTime: %d\n",rtl_mCastTimerParas.pimRouterAgingTime); PROC_PRINTF( "forceReportResponseTime: %d\n",rg_db.systemGlobal.forceReportResponseTime); for (moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM ;moduleIndex++) { if (rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { PROC_PRINTF( "-------------------------------------------------------------------------\n"); PROC_PRINTF( "module index:%d, ",moduleIndex); #ifdef CONFIG_RG_HARDWARE_MULTICAST PROC_PRINTF( "device:%s, portMask:0x%x\n\n",rtl_mCastModuleArray[moduleIndex].deviceInfo.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.portMask); #else PROC_PRINTF( "\n\n"); #endif if (rg_db.systemGlobal.multicastProtocol!=RG_MC_MLD_ONLY) { PROC_PRINTF("igmp list: V1=%d, V2=%d, V3=%d\n",igmpSnoopingCounterVer_1,igmpSnoopingCounterVer_2,igmpSnoopingCounterVer_3); ////** groupCnt=0; for (hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[hashIndex]; while (groupEntryPtr!=NULL) { groupCnt++; PROC_PRINTF( " [%d] Group address:%d.%d.%d.%d vlanID[%d]\n",groupCnt,//hashIndex groupEntryPtr->groupAddr[0]>>24, (groupEntryPtr->groupAddr[0]&0x00ff0000)>>16, (groupEntryPtr->groupAddr[0]&0x0000ff00)>>8, (groupEntryPtr->groupAddr[0]&0xff),groupEntryPtr->vlanId); clientEntry=groupEntryPtr->clientList; clientCnt=0; while (clientEntry!=NULL) { clientCnt++; /* PROC_PRINTF( " <%d>%d.%d.%d.%d\\port %d\\IGMPv%d\\",clientCnt, clientEntry->clientAddr[0]>>24, (clientEntry->clientAddr[0]&0x00ff0000)>>16, (clientEntry->clientAddr[0]&0x0000ff00)>>8, clientEntry->clientAddr[0]&0xff,clientEntry->portNum, clientEntry->igmpVersion); // delete*/ #ifdef CONFIG_MASTER_WLAN0_ENABLE if (clientEntry->portNum>RTK_RG_MAC_PORT_CPU) { PROC_PRINTF( " <%d>" IP4D "\\port %d(mbssid %d)\\IGMPv%d\\",clientCnt, NIP4QUAD(clientEntry->clientAddr),clientEntry->portNum, clientEntry->wlan_dev_idx, (clientEntry->igmpVersion-IGMP_V1 + 1)); } else #endif { PROC_PRINTF( " <%d>" IP4D "\\port %d\\IGMPv%d\\",clientCnt, NIP4QUAD(clientEntry->clientAddr),clientEntry->portNum, (clientEntry->igmpVersion-IGMP_V1 + 1)); } PROC_PRINTF( "%s",(clientEntry->groupFilterTimer>rtl_sysUpSeconds)?"EXCLUDE":"INCLUDE"); if(clientEntry->groupFilterTimer>rtl_sysUpSeconds) { PROC_PRINTF( ":%ds",clientEntry->groupFilterTimer-rtl_sysUpSeconds); } else { PROC_PRINTF( ":0s"); } sourceEntryPtr=clientEntry->sourceList; if(sourceEntryPtr!=NULL) { PROC_PRINTF( "\\source list:"); } while(sourceEntryPtr!=NULL) { PROC_PRINTF( "%d.%d.%d.%d:", sourceEntryPtr->sourceAddr[0]>>24, (sourceEntryPtr->sourceAddr[0]&0x00ff0000)>>16, (sourceEntryPtr->sourceAddr[0]&0x0000ff00)>>8, (sourceEntryPtr->sourceAddr[0]&0xff)); if(sourceEntryPtr->portTimer>rtl_sysUpSeconds) { PROC_PRINTF( "%ds",sourceEntryPtr->portTimer-rtl_sysUpSeconds); } else { PROC_PRINTF( "0s"); } if(sourceEntryPtr->next!=NULL) { PROC_PRINTF( ", "); } sourceEntryPtr=sourceEntryPtr->next; } PROC_PRINTF( "\n"); clientEntry = clientEntry->next; } PROC_PRINTF( "\n"); groupEntryPtr=groupEntryPtr->next; } } if(groupCnt==0) { PROC_PRINTF("\tnone\n"); } } #if defined (CONFIG_RG_MLD_SNOOPING) if(rg_db.systemGlobal.multicastProtocol!=RG_MC_IGMP_ONLY) { PROC_PRINTF( "\n\n"); PROC_PRINTF( "mld list: V1=%d, V2=%d\n",MLDCounterVer_1,MLDCounterVer_2); groupCnt=0; for(hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[hashIndex]; while(groupEntryPtr!=NULL) { groupCnt++; PROC_PRINTF( " [%d] Group address:%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x vlanID[%d]\n",groupCnt, (groupEntryPtr->groupAddr[0])>>28,(groupEntryPtr->groupAddr[0]<<4)>>28, (groupEntryPtr->groupAddr[0]<<8)>>28,(groupEntryPtr->groupAddr[0]<<12)>>28, (groupEntryPtr->groupAddr[0]<<16)>>28,(groupEntryPtr->groupAddr[0]<<20)>>28,(groupEntryPtr->groupAddr[0]<<24)>>28, (groupEntryPtr->groupAddr[0]<<28)>>28, (groupEntryPtr->groupAddr[1])>>28,(groupEntryPtr->groupAddr[1]<<4)>>28, (groupEntryPtr->groupAddr[1]<<8)>>28,(groupEntryPtr->groupAddr[1]<<12)>>28, (groupEntryPtr->groupAddr[1]<<16)>>28,(groupEntryPtr->groupAddr[1]<<20)>>28,(groupEntryPtr->groupAddr[1]<<24)>>28, (groupEntryPtr->groupAddr[1]<<28)>>28, (groupEntryPtr->groupAddr[2])>>28,(groupEntryPtr->groupAddr[2]<<4)>>28, (groupEntryPtr->groupAddr[2]<<8)>>28,(groupEntryPtr->groupAddr[2]<<12)>>28, (groupEntryPtr->groupAddr[2]<<16)>>28,(groupEntryPtr->groupAddr[2]<<20)>>28,(groupEntryPtr->groupAddr[2]<<24)>>28, (groupEntryPtr->groupAddr[2]<<28)>>28, (groupEntryPtr->groupAddr[3])>>28,(groupEntryPtr->groupAddr[3]<<4)>>28, (groupEntryPtr->groupAddr[3]<<8)>>28,(groupEntryPtr->groupAddr[3]<<12)>>28, (groupEntryPtr->groupAddr[3]<<16)>>28,(groupEntryPtr->groupAddr[3]<<20)>>28,(groupEntryPtr->groupAddr[3]<<24)>>28, (groupEntryPtr->groupAddr[3]<<28)>>28, groupEntryPtr->vlanId); clientEntry=groupEntryPtr->clientList; clientCnt=0; while (clientEntry!=NULL) { clientCnt++; PROC_PRINTF( " <%d>%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x\\port %d\\MLDv%d\\",clientCnt, (clientEntry->clientAddr[0])>>28,(clientEntry->clientAddr[0]<<4)>>28, (clientEntry->clientAddr[0]<<8)>>28,(clientEntry->clientAddr[0]<<12)>>28, (clientEntry->clientAddr[0]<<16)>>28,(clientEntry->clientAddr[0]<<20)>>28,(clientEntry->clientAddr[0]<<24)>>28, (clientEntry->clientAddr[0]<<28)>>28, (clientEntry->clientAddr[1])>>28,(clientEntry->clientAddr[1]<<4)>>28, (clientEntry->clientAddr[1]<<8)>>28,(clientEntry->clientAddr[1]<<12)>>28, (clientEntry->clientAddr[1]<<16)>>28,(clientEntry->clientAddr[1]<<20)>>28,(clientEntry->clientAddr[1]<<24)>>28, (clientEntry->clientAddr[1]<<28)>>28, (clientEntry->clientAddr[2])>>28,(clientEntry->clientAddr[2]<<4)>>28, (clientEntry->clientAddr[2]<<8)>>28,(clientEntry->clientAddr[2]<<12)>>28, (clientEntry->clientAddr[2]<<16)>>28,(clientEntry->clientAddr[2]<<20)>>28,(clientEntry->clientAddr[2]<<24)>>28, (clientEntry->clientAddr[2]<<28)>>28, (clientEntry->clientAddr[3])>>28,(clientEntry->clientAddr[3]<<4)>>28, (clientEntry->clientAddr[3]<<8)>>28,(clientEntry->clientAddr[3]<<12)>>28, (clientEntry->clientAddr[3]<<16)>>28,(clientEntry->clientAddr[3]<<20)>>28,(clientEntry->clientAddr[3]<<24)>>28, (clientEntry->clientAddr[3]<<28)>>28, //clientEntry->portNum, clientEntry->igmpVersion-IGMP_V3); clientEntry->portNum, (clientEntry->igmpVersion-MLD_V1+1)); PROC_PRINTF( "%s",(clientEntry->groupFilterTimer>rtl_sysUpSeconds)?"EXCLUDE":"INCLUDE"); if(clientEntry->groupFilterTimer>rtl_sysUpSeconds) { PROC_PRINTF( ":%ds",clientEntry->groupFilterTimer-rtl_sysUpSeconds); } else { PROC_PRINTF( ":0s"); } sourceEntryPtr=clientEntry->sourceList; if(sourceEntryPtr!=NULL) { PROC_PRINTF( "\\source list:"); } while(sourceEntryPtr!=NULL) { PROC_PRINTF( "%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x-%x%x%x%x%x%x%x%x:", (sourceEntryPtr->sourceAddr[0])>>28,(sourceEntryPtr->sourceAddr[0]<<4)>>28, (sourceEntryPtr->sourceAddr[0]<<8)>>28,(sourceEntryPtr->sourceAddr[0]<<12)>>28, (sourceEntryPtr->sourceAddr[0]<<16)>>28,(sourceEntryPtr->sourceAddr[0]<<20)>>28,(sourceEntryPtr->sourceAddr[0]<<24)>>28, (sourceEntryPtr->sourceAddr[0]<<28)>>28, (sourceEntryPtr->sourceAddr[1])>>28,(sourceEntryPtr->sourceAddr[1]<<4)>>28, (sourceEntryPtr->sourceAddr[1]<<8)>>28,(sourceEntryPtr->sourceAddr[1]<<12)>>28, (sourceEntryPtr->sourceAddr[1]<<16)>>28,(sourceEntryPtr->sourceAddr[1]<<20)>>28,(sourceEntryPtr->sourceAddr[1]<<24)>>28, (sourceEntryPtr->sourceAddr[1]<<28)>>28, (sourceEntryPtr->sourceAddr[2])>>28,(sourceEntryPtr->sourceAddr[2]<<4)>>28, (sourceEntryPtr->sourceAddr[2]<<8)>>28,(sourceEntryPtr->sourceAddr[2]<<12)>>28, (sourceEntryPtr->sourceAddr[2]<<16)>>28,(sourceEntryPtr->sourceAddr[2]<<20)>>28,(sourceEntryPtr->sourceAddr[2]<<24)>>28, (sourceEntryPtr->sourceAddr[2]<<28)>>28, (sourceEntryPtr->sourceAddr[3])>>28,(sourceEntryPtr->sourceAddr[3]<<4)>>28, (sourceEntryPtr->sourceAddr[3]<<8)>>28,(sourceEntryPtr->sourceAddr[3]<<12)>>28, (sourceEntryPtr->sourceAddr[3]<<16)>>28,(sourceEntryPtr->sourceAddr[3]<<20)>>28,(sourceEntryPtr->sourceAddr[3]<<24)>>28, (sourceEntryPtr->sourceAddr[3]<<28)>>28); if(sourceEntryPtr->portTimer>rtl_sysUpSeconds) { PROC_PRINTF( "%ds",sourceEntryPtr->portTimer-rtl_sysUpSeconds); } else { PROC_PRINTF( "0s"); } if(sourceEntryPtr->next!=NULL) { PROC_PRINTF( ", "); } sourceEntryPtr=sourceEntryPtr->next; } PROC_PRINTF( "\n"); clientEntry = clientEntry->next; } PROC_PRINTF( "\n"); groupEntryPtr=groupEntryPtr->next; } } if(groupCnt==0) { PROC_PRINTF("\tnone\n"); } } #endif #ifdef CONFIG_RECORD_MCAST_FLOW PROC_PRINTF("ipv4 flow list:\n"); flowCnt=1; for(hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { /*to dump multicast flow information*/ mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[hashIndex]; while(mcastFlowEntry!=NULL) { if(mcastFlowEntry->ipVersion==IP_VERSION4) { PROC_PRINTF( " [%d] %d.%d.%d.%d-->",flowCnt, mcastFlowEntry->serverAddr[0]>>24, (mcastFlowEntry->serverAddr[0]&0x00ff0000)>>16, (mcastFlowEntry->serverAddr[0]&0x0000ff00)>>8, (mcastFlowEntry->serverAddr[0]&0xff)); PROC_PRINTF( "%d.%d.%d.%d-->", mcastFlowEntry->groupAddr[0]>>24, (mcastFlowEntry->groupAddr[0]&0x00ff0000)>>16, (mcastFlowEntry->groupAddr[0]&0x0000ff00)>>8, (mcastFlowEntry->groupAddr[0]&0xff)); PROC_PRINTF( "port mask:0x%x\n",mcastFlowEntry->multicastFwdInfo.fwdPortMask); } flowCnt++; mcastFlowEntry=mcastFlowEntry->next; } } PROC_PRINTF( "ipv6 flow list:\n"); flowCnt=1; for(hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { /*to dump multicast flow information*/ mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[hashIndex]; while(mcastFlowEntry!=NULL) { if(mcastFlowEntry->ipVersion==IP_VERSION6) { PROC_PRINTF( " [%d] %x-%x-%x-%x-->",flowCnt, mcastFlowEntry->serverAddr[0], mcastFlowEntry->serverAddr[1], mcastFlowEntry->serverAddr[2], (mcastFlowEntry->serverAddr[3])); PROC_PRINTF( "%x-%x-%x-%x-->", mcastFlowEntry->groupAddr[1], mcastFlowEntry->groupAddr[1], mcastFlowEntry->groupAddr[2], mcastFlowEntry->groupAddr[3]); PROC_PRINTF( "port mask:0x%x\n",mcastFlowEntry->multicastFwdInfo.fwdPortMask); } flowCnt++; mcastFlowEntry=mcastFlowEntry->next; } } #endif } } PROC_PRINTF( "------------------------------------------------------------------\n"); return len; } int igmp_groupList_memDump(struct seq_file *s, void *v) { struct rtl_groupEntry *gp = NULL; int i; int len=0; rg_lock(&rg_kernel.igmpsnoopingLock); PROC_PRINTF("rtl_totalMaxGroupCnt=%d \n",rtl_totalMaxGroupCnt); if (rtl_groupMemory!=NULL) { if (rtl_groupEntryPool!=NULL) PROC_PRINTF("current rtl_groupEntryPool point to %p \n",rtl_groupEntryPool); gp = (struct rtl_groupEntry *)rtl_groupMemory; for (i=0;i<rtl_totalMaxGroupCnt;i++){ PROC_PRINTF("rtl_groupMemory[%d]=%p (gip=0x%x, vlanId=%d) ", i, &gp[i],gp[i].groupAddr[0], gp[i].vlanId); if(gp[i].previous!=NULL) PROC_PRINTF("prev=%p ",gp[i].previous); else PROC_PRINTF("prev=NULL "); if(gp[i].next!=NULL) PROC_PRINTF("next=%p \n",gp[i].next); else PROC_PRINTF("next=NULL \n"); } } rg_unlock(&rg_kernel.igmpsnoopingLock); return len; } #endif void rtl865x_igmpLinkStatusChangeCallback(uint32 moduleIndex, rtl_igmpPortInfo_t * portInfo) { int32 hashIndex; int32 clearFlag=FALSE; struct rtl_groupEntry *groupEntryPtr; struct rtl_clientEntry* clientEntry=NULL; struct rtl_clientEntry* nextClientEntry=NULL; #ifdef CONFIG_RECORD_MCAST_FLOW struct rtl_mcastFlowEntry *mcastFlowEntry, *nextMcastFlowEntry; #endif DEBUG("In rtl865x_igmpLinkStatusChangeCallback"); if (portInfo==NULL) { return ; } if (moduleIndex>=MAX_MCAST_MODULE_NUM) { return ; } #ifdef CONFIG_RECORD_MCAST_FLOW for (hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { mcastFlowEntry=rtl_mCastModuleArray[moduleIndex].flowHashTable[hashIndex]; while(mcastFlowEntry!=NULL) { nextMcastFlowEntry=mcastFlowEntry->next; /*clear multicast forward flow cache*/ rtl_deleteMcastFlowEntry( mcastFlowEntry, rtl_mCastModuleArray[moduleIndex].flowHashTable); mcastFlowEntry=nextMcastFlowEntry; } } #endif if (rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { for (hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[hashIndex]; while (groupEntryPtr!=NULL) { clientEntry=groupEntryPtr->clientList; while (clientEntry!=NULL) { /*save next client entry first*/ nextClientEntry=clientEntry->next; if (((1<<clientEntry->portNum) & portInfo->linkPortMask)==0) { rtl_deleteClientEntry(groupEntryPtr,clientEntry); clearFlag=TRUE; } clientEntry = nextClientEntry; } #if defined (CONFIG_RG_HARDWARE_MULTICAST) if (clearFlag==TRUE) { strcpy(linkEventContext.devName,rtl_mCastModuleArray[moduleIndex].deviceInfo.devName); linkEventContext.moduleIndex=moduleIndex; linkEventContext.groupAddr[0]=groupEntryPtr->groupAddr[0]; linkEventContext.groupAddr[1]=groupEntryPtr->groupAddr[1]; linkEventContext.groupAddr[2]=groupEntryPtr->groupAddr[2]; linkEventContext.groupAddr[3]=groupEntryPtr->groupAddr[3]; linkEventContext.sourceAddr[0]=0; linkEventContext.sourceAddr[1]=0; linkEventContext.sourceAddr[2]=0; linkEventContext.sourceAddr[3]=0; //rtl865x_raiseEvent(EVENT_UPDATE_MCAST, &linkEventContext); rtl_handle_igmpgroup_change(&linkEventContext); } #endif groupEntryPtr=groupEntryPtr->next; } } #if defined (CONFIG_RG_MLD_SNOOPING) for(hashIndex=0;hashIndex<rtl_hashTableSize;hashIndex++) { groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv6HashTable[hashIndex]; while(groupEntryPtr!=NULL) { clientEntry=groupEntryPtr->clientList; while (clientEntry!=NULL) { /*save next client entry first*/ nextClientEntry=clientEntry->next; if(((1<<clientEntry->portNum) & portInfo->linkPortMask)==0) { rtl_deleteClientEntry(groupEntryPtr,clientEntry); } clientEntry = nextClientEntry; } groupEntryPtr=groupEntryPtr->next; } } #endif } return ; } int32 rtl_getGroupInfo(uint32 groupAddr, struct rtl_groupInfo * groupInfo) { int32 moduleIndex; int32 hashIndex; struct rtl_groupEntry *groupEntryPtr; //DEBUG("got in rtl_getGroupInfo"); if(groupInfo==NULL) { return FAIL; } memset(groupInfo, 0 , sizeof(struct rtl_groupInfo)); for(moduleIndex=0; moduleIndex<MAX_MCAST_MODULE_NUM ;moduleIndex++) { if(rtl_mCastModuleArray[moduleIndex].enableSnooping==TRUE) { hashIndex=rtl_hashMask&groupAddr; groupEntryPtr=rtl_mCastModuleArray[moduleIndex].rtl_ipv4HashTable[hashIndex]; while(groupEntryPtr!=NULL) { if(groupEntryPtr->groupAddr[0]==groupAddr) { groupInfo->ownerMask |= (1<<moduleIndex); break; } groupEntryPtr=groupEntryPtr->next; } } } return SUCCESS; } #if defined (CONFIG_RG_HARDWARE_MULTICAST) static int _rtl_handle_igmpgroup_addhw(rtl_multicast_index_mapping_t* mapping_entry) { rtk_rg_multicastFlow_t mcFlow; memset(&mcFlow,0,sizeof(rtk_rg_multicastFlow_t)); mcFlow.port_mask.portmask = mapping_entry->fwdmembr; mcFlow.srcFilterMode = mapping_entry->srcFilterMode; //// if (mapping_entry->ipVersion == IP_VERSION4) { IGMP("Add IP4 lut info"); mcFlow.isIPv6 = 0; mcFlow.multicast_ipv4_addr = mapping_entry->groupIP[0]; mcFlow.routingMode = mapping_entry->routingMode; if (RTK_RG_IPV4MC_DONT_CARE_SRC!=mapping_entry->srcFilterMode) { mcFlow.includeOrExcludeIp = mapping_entry->sourceIP[0]; IGMP( IP4D, NIP4QUAD((&mcFlow.includeOrExcludeIp))); //mcFlow.routingMode = RTK_RG_IPV4MC_DIS_ROUTING; } #ifdef CONFIG_RTL9602C_SERIES #elif defined(CONFIG_RTL9600_SERIES) #else #endif } else { IGMP("Add IP6 lut info"); mcFlow.isIPv6 = 1; mcFlow.multicast_ipv6_addr[0] = mapping_entry->groupIP[0]; mcFlow.multicast_ipv6_addr[1] = mapping_entry->groupIP[1]; mcFlow.multicast_ipv6_addr[2] = mapping_entry->groupIP[2]; mcFlow.multicast_ipv6_addr[3] = mapping_entry->groupIP[3]; } mcFlow.port_mask.portmask = mapping_entry->fwdmembr; //rev1668 already skip packets which from CPU port into igmpSnooping module. //skip joining CPU Port when IGMP Proxy send from CPU. //if(rg_db.pktHdr->ingressPort==RTK_RG_PORT_CPU) // return FAIL; if(rg_db.systemGlobal.initParam.ivlMulticastSupport) { /* mcFlow.vlanID=mapping_entry->vlanId; if(rg_db.vlan[mapping_entry->vlanId].fidMode==VLAN_FID_IVL)mcFlow.isIVL=1;*/ if(rg_db.vlan[mapping_entry->vlanId].fidMode==VLAN_FID_IVL) { mcFlow.isIVL=1; mcFlow.vlanID=mapping_entry->vlanId; }else{ mcFlow.vlanID=rg_db.vlan[mapping_entry->vlanId].fid; } } if((pf.rtk_rg_multicastFlow_add)(&mcFlow, &mapping_entry->hwflow_index)!=RT_ERR_RG_OK){ return FAIL; }else{ IGMP("add multicast flow at L2[%d]",mapping_entry->hwflow_index); return SUCCESS; } } static int _rtl_handle_igmpgroup_delhw(rtl_multicast_index_mapping_t* mapping_entry) { IGMP("#####delete multicast flow at L2[%d]######",mapping_entry->hwflow_index); return (pf.rtk_rg_multicastFlow_del)(mapping_entry->hwflow_index); } #ifdef CONFIG_RG_SIMPLE_IGMP_v3 /*cxy 2014-8-19:for IGMPv3 hw can't support include or exclude case, so we want to get the fwd mask of group that all situations can forward mc pkts. Firstly we want to get all specified src fwdmask of this group and for include we use OR op and for exclude we use AND op. But we can't specify src ip for group fwdmask lookup. Because it is complicated to find all different src ip under group entry. I(g,<s1,s3>) ____ client1-------------| | I(g,<s1,s2>) | |-------server1,server2 g:group, s1,s2,s3:source client2-------------|____| so hw forward to that port if the port client is exclude mode or include mode with src. */ int rtl_handle_igmpgroup_change_v3(rtl_multicastEventContext_t* param) { rtl_multicast_index_mapping_t* mapping_entry_rm=NULL; IGMP("IGMPv3 Group change.\n"); if (strlen(param->devName)==0) { DEBUG("IGMPv3 devname==NULL\n"); return FAIL; } #ifndef RTK_RG_MULTICAST_MODE_MACFID if (param->ipVersion == IP_VERSION6) { DEBUG("IPv6 HWACC is not supported IGMPV3!\n"); return FAIL; } #endif if (strcmp(param->devName, RG_IGMP_SNOOPING_MODULE_NAME)==0) { struct rtl_multicastDeviceInfo_s igmp_snooping_module; rtl_multicast_index_mapping_t* mapping_entry_temp; rtl_multicast_index_mapping_t* mapping_entry=NULL; int retVal; struct rtl_groupEntry* groupEntry; unsigned int fwdPortMask=0; struct rtl_clientEntry *clientEntry; groupEntry=rtl_searchGroupEntry(param->moduleIndex, param->ipVersion, param->groupAddr, param->vlanId); if (groupEntry==NULL) { fwdPortMask = rtl_mCastModuleArray[param->moduleIndex].unknownMCastFloodMap; } else { clientEntry = groupEntry->clientList; while (clientEntry != NULL) { /* //: * G.C.In.SrcList is empty => do not add, means leave * G.C.In.SrcList not empty => do not care src, add client spa * G.C.Ex.SrcList is empty => like v2 join, add client spa * G.C.Ex.Srclist not emtpy => do not care src, add client spa */ if (!((clientEntry->groupFilterTimer <= rtl_sysUpSeconds) && (clientEntry->sourceList == NULL)) ) { fwdPortMask|= (1<<clientEntry->portNum); } clientEntry=clientEntry->next; } } if (param->groupAddr[0] == 0xEFFFFFFA) { fwdPortMask |= 0x40; } //printk("in <%s>,add igmp hw mc --grp:%x fwd:%x\n",__func__, //param->groupAddr[0],fwdPortMask); retVal = rtl_getIgmpSnoopingModuleDevInfo(param->moduleIndex,&igmp_snooping_module); if(retVal!=SUCCESS) { DEBUG("FAIL: igmpv3 rtl_getIgmpSnoopingModuleDevInfo=%d",retVal); return FAIL; } list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if(mapping_entry_temp->groupIP[0] == param->groupAddr[0] && mapping_entry_temp->groupIP[1] == param->groupAddr[1] && mapping_entry_temp->groupIP[2] == param->groupAddr[2] && mapping_entry_temp->groupIP[3] == param->groupAddr[3] && mapping_entry_temp->ipVersion == param->ipVersion) { if(rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; /* (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (mapping_entry_temp->vlanId!=param->vlanId) goto NEXT; return groupPtr; }*/ mapping_entry = mapping_entry_temp; } } if (!mapping_entry) { /* create sw_entry */ mapping_entry = _rtk_hwMappingEntry_malloc(); if (!mapping_entry) { DEBUG("IGMPv3 alloc fail!"); return FAIL; } mapping_entry->groupIP[0] = param->groupAddr[0]; mapping_entry->groupIP[1] = param->groupAddr[1]; mapping_entry->groupIP[2] = param->groupAddr[2]; mapping_entry->groupIP[3] = param->groupAddr[3]; mapping_entry->ipVersion = param->ipVersion; mapping_entry->vlanId = param->vlanId; mapping_entry->fwdmembr = fwdPortMask; /* add it into hw */ if(mapping_entry->fwdmembr!=0) //have member port in this entry { int r=_rtl_handle_igmpgroup_addhw(mapping_entry); if (param->ipVersion==IP_VERSION4) { DEBUG("IGMPv3 SNOOPING ADD:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMPv3 SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),fwdPortMask ,mapping_entry->hwflow_index); } if (r!=SUCCESS) { DEBUG("IGMPv3 SNOOPING ADD:FAIL\n"); return FAIL; } } } else { int ret; if(param->ipVersion==IP_VERSION4) { DEBUG("IGMPv3 SNOOPING CHANGE:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMPv3 SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),fwdPortMask ,mapping_entry->hwflow_index); } /* modify member port */ mapping_entry->fwdmembr = fwdPortMask; /* add it into hw */ if(mapping_entry->fwdmembr!=0) //have member port in this entry { if(_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMPv3 SNOOPING ADD:FAIL\n"); return FAIL; } } else { /* no member ports, clean it in hw */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if( ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK ) { DEBUG("IGMPv3 SNOOPING DEL:FAIL\n"); return FAIL; } } } DEBUG("(%s %d) SUCCESS!! ",__func__,__LINE__); return SUCCESS; } return FAIL; } #endif int rtl_handle_igmpgroup_change(rtl_multicastEventContext_t* param) { int retVal; int refReset; struct rtl_multicastFwdInfo multicastFwdInfo; struct rtl_multicastDataInfo multicastDataInfo; struct rtl_multicastDeviceInfo_s igmp_snooping_module; struct rtl_groupEntry *groupEntry = NULL; struct rtl_clientEntry *clientEntry= NULL; //rtk_rg_ipv4MulticastFlowMode_t tmp_srcFilterMode=RTK_RG_IPV4MC_DONT_CARE_SRC; rtl_multicast_index_mapping_t* mapping_entry_temp=NULL; rtl_multicast_index_mapping_t* mapping_entry=NULL; rtl_multicast_index_mapping_t* mapping_entry_rm=NULL; IGMP("=========Group change processing======\n"); if(strlen(param->devName)==0) { DEBUG("param->devname==NULL, return fail\n"); return FAIL; } /* path3,4 do not support IPv6 multicast-hwacc */ #ifndef RTK_RG_MULTICAST_MODE_MACFID if(param->ipVersion == IP_VERSION6) { DEBUG("IPv6 HWACC is not supported!, return fail\n"); return FAIL; } #endif /*case 1:this is multicast event from bridge(br0) module */ if (strcmp(param->devName, RG_IGMP_SNOOPING_MODULE_NAME)!=0) { DEBUG("param->devname!=RG_IGMP_SNOOPING_MODULE_NAME, return fail\n"); return FAIL; } //if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==1)//not IGMPv2 only, just don`t care source if (0) { multicastDataInfo.ipVersion=param->ipVersion; multicastDataInfo.vlanId=param->vlanId; multicastDataInfo.sourceIp[0]= param->sourceAddr[0]; multicastDataInfo.sourceIp[1]= param->sourceAddr[1]; multicastDataInfo.sourceIp[2]= param->sourceAddr[2]; multicastDataInfo.sourceIp[3]= param->sourceAddr[3]; multicastDataInfo.groupAddr[0]= param->groupAddr[0]; multicastDataInfo.groupAddr[1]= param->groupAddr[1]; multicastDataInfo.groupAddr[2]= param->groupAddr[2]; multicastDataInfo.groupAddr[3]= param->groupAddr[3]; retVal= rtl_getMulticastDataFwdInfo(param->moduleIndex, &multicastDataInfo, &multicastFwdInfo); if(retVal!=SUCCESS) { DEBUG("FAIL: rtl_getMulticastDataFwdInfo=%d\n",retVal); return FAIL; } retVal = rtl_getIgmpSnoopingModuleDevInfo(param->moduleIndex,&igmp_snooping_module); if(retVal!=SUCCESS) { DEBUG("FAIL: rtl_getIgmpSnoopingModuleDevInfo=%d",retVal); return FAIL; } list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if(mapping_entry_temp->groupIP[0] == param->groupAddr[0] && mapping_entry_temp->groupIP[1] == param->groupAddr[1] && mapping_entry_temp->groupIP[2] == param->groupAddr[2] && mapping_entry_temp->groupIP[3] == param->groupAddr[3] && mapping_entry_temp->ipVersion == param->ipVersion) { /* if(rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; */ if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { #if 0 if (mapping_entry_temp->vlanId!=param->vlanId) continue; #else if (rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; #endif } mapping_entry = mapping_entry_temp; } } if(!mapping_entry) { /* create sw_entry */ mapping_entry = _rtk_hwMappingEntry_malloc(); if(!mapping_entry) { DEBUG("alloc fail!"); return FAIL; } mapping_entry->groupIP[0] = param->groupAddr[0]; mapping_entry->groupIP[1] = param->groupAddr[1]; mapping_entry->groupIP[2] = param->groupAddr[2]; mapping_entry->groupIP[3] = param->groupAddr[3]; mapping_entry->ipVersion = param->ipVersion; mapping_entry->vlanId = param->vlanId; mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; /* add it into hw */ if(mapping_entry->fwdmembr!=0) //have member port in this entry { int r=_rtl_handle_igmpgroup_addhw(mapping_entry); if(param->ipVersion==4) { DEBUG("IGMP SNOOPING ADD:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMP SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),multicastFwdInfo.fwdPortMask ,mapping_entry->hwflow_index); } if(r!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL\n"); return FAIL; } } } else { int ret; if(param->ipVersion==4) { DEBUG("IGMP SNOOPING CHANGE:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMP SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),multicastFwdInfo.fwdPortMask ,mapping_entry->hwflow_index); } /* modify member port */ mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; /* update it into hw */ if(mapping_entry->fwdmembr!=0) //have member port in this entry { if(_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL\n"); return FAIL; } } else { /* no member ports, clean it in hw */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if( ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK ) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); return FAIL; } } } DEBUG("(%s %d) SUCCESS!! ",__func__,__LINE__); return SUCCESS; } //else if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==2) //just care source //else if (1) { #if 1 //per source considerate //groupEntry=rtl_searchGroupEntry(param->moduleIndex,multicastDataInfo.ipVersion, multicastDataInfo.groupAddr, multicastDataInfo.vlanId); groupEntry=rtl_searchGroupEntry(param->moduleIndex, param->ipVersion, param->groupAddr, param->vlanId); if (groupEntry==NULL) { DEBUG("Group non-exist"); DEBUG("===Start to Dump & Del igmp non-existing group mapping-hw-list====\n"); //list_for_each_entry(mapping_entry_temp,&rtl_multicast_index_mapping_listhead,entry) list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { /*{ if(rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) }*/ if (mapping_entry_temp != NULL) { if (mapping_entry_temp->ipVersion == IP_VERSION4) { //DEBUG("(GIP4: " IP4D ") pMask:0x%X LUT_IDX=%d\n",NIP4QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); DEBUG("IGMP HW Entry: GIP4:%d.%d.%d.%d SIP4:%d.%d.%d.%d l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" /*,((param->groupAddr[0])&0x000000ff) ,((param->groupAddr[0])&0x0000ff00)>>8 ,((param->groupAddr[0])&0x00ff0000)>>16 ,((param->groupAddr[0])&0xff000000)>>24*/ //,NIPQUAD(param->groupAddr), NIPQUAD(param->sourceAddr), multicastFwdInfo.fwdPortMask); //,NIPQUAD(param->groupAddr), NIPQUAD(multicastDataInfo.sourceIp), multicastFwdInfo.fwdPortMask); ,NIPQUAD(mapping_entry_temp->groupIP), NIPQUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } else { //DEBUG("(GIP6: " IP6H ") pMask:0x%X LUT_IDX=%d\n",NIP6QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); DEBUG("MLD HW Entry:GIP6:" IP6H "SIP6" IP6H "l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIP6QUAD(mapping_entry_temp->groupIP), NIP6QUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } if (mapping_entry_temp->ipVersion == param->ipVersion) { if (IP_VERSION4 == param->ipVersion) { if (mapping_entry_temp->groupIP[0] != param->groupAddr[0]) { continue; } } else //IP_VERSION6 { if(mapping_entry_temp->groupIP[0] != param->groupAddr[0] || mapping_entry_temp->groupIP[1] != param->groupAddr[1] || mapping_entry_temp->groupIP[2] != param->groupAddr[2] || mapping_entry_temp->groupIP[3] != param->groupAddr[3]) { continue; } } #if 0 if (mapping_entry_temp->groupIP[0] != param->groupAddr[0]) continue; if (IP_VERSION6 == param->ipVersion) { if(mapping_entry_temp->groupIP[1] != param->groupAddr[1] || mapping_entry_temp->groupIP[2] != param->groupAddr[2] || mapping_entry_temp->groupIP[3] != param->groupAddr[3]) { continue; } } if ((mapping_entry_temp->groupIP[0] != param->groupAddr[0]) || ( (IP_VERSION6 == param->ipVersion) &&(mapping_entry_temp->groupIP[1] != param->groupAddr[1] || mapping_entry_temp->groupIP[2] != param->groupAddr[2] || mapping_entry_temp->groupIP[3] != param->groupAddr[3]) )) #endif } else { continue; } DEBUG("delete : l2 entry index [%d]\n", mapping_entry_temp->hwflow_index); _rtl_handle_igmpgroup_delhw(mapping_entry_temp); mapping_entry_temp->refCnt=0; DEBUG("delete : sw mapping hw entry-list\n"); }else{ DEBUG("mapping_entry_temp is NULL\n"); } } DEBUG("===End to Dump & Del igmp non-existing group mapping-hw-list====\n"); DEBUG("return Fail"); return FAIL; } else { //rtk_rg_ipv4MulticastFlowMode_t groupMode = RTK_RG_IPV4MC_INCLUDE; DEBUG("GIP exist"); refReset=1; if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==2) { list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if (mapping_entry_temp != NULL) { if (mapping_entry_temp->ipVersion == IP_VERSION4) { DEBUG("IGMP HW Entry: GIP4:%d.%d.%d.%d SIP4:%d.%d.%d.%d l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(mapping_entry_temp->groupIP), NIPQUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } else { DEBUG("IGMP HW Entry:GIP6:" IP6H "SIP6" IP6H "l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIP6QUAD(mapping_entry_temp->groupIP), NIP6QUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } if (mapping_entry_temp->ipVersion == param->ipVersion) { if (IP_VERSION4 == param->ipVersion) { if (mapping_entry_temp->groupIP[0] != param->groupAddr[0]) { continue; } } else //IP_VERSION6 { if(mapping_entry_temp->groupIP[0] != param->groupAddr[0] || mapping_entry_temp->groupIP[1] != param->groupAddr[1] || mapping_entry_temp->groupIP[2] != param->groupAddr[2] || mapping_entry_temp->groupIP[3] != param->groupAddr[3]) { continue; } } if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //6266 or 9602C force path2, follow rg init { if (rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; } DEBUG("delete : l2 entry index [%d]\n", mapping_entry_temp->hwflow_index); _rtl_handle_igmpgroup_delhw(mapping_entry_temp); DEBUG("delete : sw mapping hw entry-list\n"); } else { continue; } mapping_entry_temp->refCnt=0; } } } clientEntry=groupEntry->clientList; while (clientEntry!=NULL) { struct rtl_sourceEntry *sourceEntry = NULL; //struct rtl_sourceEntry * nextSourceEntry=NULL; sourceEntry=clientEntry->sourceList; //while(sourceEntry!=NULL) do { //nextSourceEntry=sourceEntry->next; #endif struct rtl_clientEntry *preClientEntry; int HadFound; preClientEntry= NULL; HadFound = 0; /* for (preClientEntry=clientEntry->previous;preClientEntry!=NULL;preClientEntry=preClientEntry->previous) { if (sourceAddr!=NULL) { if (rtl_searchSourceEntry(groupEntry->ipVersion, sourceAddr, preClientEntry) != NULL) { } } } */ bzero(&multicastDataInfo, sizeof(struct rtl_multicastDataInfo)); multicastDataInfo.ipVersion=param->ipVersion; multicastDataInfo.vlanId=param->vlanId; multicastDataInfo.srcFilterMode = param->srcFilterMode; //// multicastDataInfo.groupAddr[0]= param->groupAddr[0]; if (IP_VERSION6==param->ipVersion) { multicastDataInfo.groupAddr[1]= param->groupAddr[1]; multicastDataInfo.groupAddr[2]= param->groupAddr[2]; multicastDataInfo.groupAddr[3]= param->groupAddr[3]; } /* multicastDataInfo.sourceIp[0]= param->sourceAddr[0]; multicastDataInfo.sourceIp[1]= param->sourceAddr[1]; multicastDataInfo.sourceIp[2]= param->sourceAddr[2]; multicastDataInfo.sourceIp[3]= param->sourceAddr[3];*/ if (sourceEntry!=NULL) { multicastDataInfo.sourceIp[0]= sourceEntry->sourceAddr[0]; if (IP_VERSION6==param->ipVersion) { multicastDataInfo.sourceIp[1]= sourceEntry->sourceAddr[1]; multicastDataInfo.sourceIp[2]= sourceEntry->sourceAddr[2]; multicastDataInfo.sourceIp[3]= sourceEntry->sourceAddr[3]; DEBUG("test SrcIP(" IP6H ")", NIP6QUAD(sourceEntry->sourceAddr)); } else { DEBUG("test SrcIP(" IP4D ")", NIPQUAD(sourceEntry->sourceAddr)); } } else { //multicastDataInfo.sourceIp[0]= 0; //multicastDataInfo.sourceIp[1]= 0; //multicastDataInfo.sourceIp[2]= 0; //multicastDataInfo.sourceIp[3]= 0; DEBUG("GIP.Clt.SrcIP-list is <Empty>"); } retVal = rtl_getMulticastDataFwdInfo(param->moduleIndex, &multicastDataInfo, &multicastFwdInfo); if (retVal!=SUCCESS) { DEBUG("FAIL: rtl_getMulticastDataFwdInfo=%d, return\n",retVal); return FAIL; } retVal = rtl_getIgmpSnoopingModuleDevInfo(param->moduleIndex, &igmp_snooping_module); if (retVal!=SUCCESS) { DEBUG("FAIL: rtl_getIgmpSnoopingModuleDevInfo=%d, return",retVal); return FAIL; } #if 1 DEBUG("===Start to Dump igmp mapping-hw-list====\n"); //list_for_each_entry(mapping_entry_temp,&rtl_multicast_index_mapping_listhead,entry) list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { /*{ if(rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) }*/ if (mapping_entry_temp!=NULL) { if (mapping_entry_temp->ipVersion==IP_VERSION4) { //DEBUG("(GIP4: " IP4D ") pMask:0x%X LUT_IDX=%d\n",NIP4QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); DEBUG("IGMP HW Entry: GIP4:%d.%d.%d.%d SIP4:%d.%d.%d.%d l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" /*,((param->groupAddr[0])&0x000000ff) ,((param->groupAddr[0])&0x0000ff00)>>8 ,((param->groupAddr[0])&0x00ff0000)>>16 ,((param->groupAddr[0])&0xff000000)>>24*/ //,NIPQUAD(param->groupAddr), NIPQUAD(param->sourceAddr), multicastFwdInfo.fwdPortMask); //,NIPQUAD(param->groupAddr), NIPQUAD(multicastDataInfo.sourceIp), multicastFwdInfo.fwdPortMask); ,NIPQUAD(mapping_entry_temp->groupIP), NIPQUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } else { //DEBUG("(GIP6: " IP6H ") pMask:0x%X LUT_IDX=%d\n",NIP6QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); DEBUG("IGMP HW Entry:GIP6:" IP6H "SIP6" IP6H "l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIP6QUAD(mapping_entry_temp->groupIP), NIP6QUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } /* DEBUG("delete : hw list\n"); _rtl_handle_igmpgroup_delhw(mapping_entry_temp); DEBUG("delete : mapping hw list\n"); list_del_init(&mapping_entry_temp->entry); //list_del(&mapping_entry_temp->entry); */ }else{ DEBUG("mapping_entry_temp is NULL\n"); } } DEBUG("===End of Dump mapping-hw-list====\n"); #endif mapping_entry = NULL; list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { #if 0 if(mapping_entry_temp->groupIP[0] == param->groupAddr[0] && mapping_entry_temp->groupIP[1] == param->groupAddr[1] && mapping_entry_temp->groupIP[2] == param->groupAddr[2] && mapping_entry_temp->groupIP[3] == param->groupAddr[3] && mapping_entry_temp->ipVersion == param->ipVersion) { /* if(rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; */ if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //force path2 { if (mapping_entry_temp->vlanId!=param->vlanId) continue; } mapping_entry = mapping_entry_temp; } #endif if (mapping_entry_temp->ipVersion == param->ipVersion) { if (IP_VERSION4 == param->ipVersion) { if (mapping_entry_temp->groupIP[0] != param->groupAddr[0]) { continue; } } else //IP_VERSION6 { if (mapping_entry_temp->groupIP[0] != param->groupAddr[0] || mapping_entry_temp->groupIP[1] != param->groupAddr[1] || mapping_entry_temp->groupIP[2] != param->groupAddr[2] || mapping_entry_temp->groupIP[3] != param->groupAddr[3]) { continue; } } } else { continue; } if (rg_db.systemGlobal.initParam.ivlMulticastSupport) //6266 or 9602C force path2, follow rg init { if (rg_db.vlan[mapping_entry_temp->vlanId].fidMode!=VLAN_FID_SVL && mapping_entry_temp->vlanId!=param->vlanId) continue; } else { if (mapping_entry_temp->srcFilterMode != RTK_RG_IPV4MC_DONT_CARE_SRC) { if (sourceEntry!=NULL) { if (IP_VERSION4 == param->ipVersion) { //if (mapping_entry_temp->sourceIP[0] != param->sourceAddr[0]) if (mapping_entry_temp->sourceIP[0] != sourceEntry->sourceAddr[0]) { continue; } } else //IP_VERSION6 { /* if (mapping_entry_temp->sourceIP[0] != param->sourceAddr[0] || mapping_entry_temp->sourceIP[1] != param->sourceAddr[1] || mapping_entry_temp->sourceIP[2] != param->sourceAddr[2] || mapping_entry_temp->sourceIP[3] != param->sourceAddr[3])*/ if (mapping_entry_temp->sourceIP[0] != sourceEntry->sourceAddr[0] || mapping_entry_temp->sourceIP[1] != sourceEntry->sourceAddr[1] || mapping_entry_temp->sourceIP[2] != sourceEntry->sourceAddr[2] || mapping_entry_temp->sourceIP[3] != sourceEntry->sourceAddr[3]) { continue; } } } } } DEBUG("find hw entry\n"); mapping_entry = mapping_entry_temp; break; } if (!mapping_entry) { /* create sw_entry */ DEBUG("Not found\n"); mapping_entry = _rtk_hwMappingEntry_malloc(); if (!mapping_entry) { DEBUG("alloc fail, return!"); return FAIL; } mapping_entry->groupIP[0] = param->groupAddr[0]; mapping_entry->groupIP[1] = param->groupAddr[1]; mapping_entry->groupIP[2] = param->groupAddr[2]; mapping_entry->groupIP[3] = param->groupAddr[3]; #if 0 mapping_entry->sourceIP[0] = param->sourceAddr[0]; mapping_entry->sourceIP[1] = param->sourceAddr[1]; mapping_entry->sourceIP[2] = param->sourceAddr[2]; mapping_entry->sourceIP[3] = param->sourceAddr[3]; #else if (multicastFwdInfo.srcFilterMode != RTK_RG_IPV4MC_DONT_CARE_SRC) { /* mapping_entry->sourceIP[0] = param->sourceAddr[0]; mapping_entry->sourceIP[1] = param->sourceAddr[1]; mapping_entry->sourceIP[2] = param->sourceAddr[2]; mapping_entry->sourceIP[3] = param->sourceAddr[3];*/ if (sourceEntry!=NULL) { mapping_entry->sourceIP[0] = sourceEntry->sourceAddr[0]; mapping_entry->sourceIP[1] = sourceEntry->sourceAddr[1]; mapping_entry->sourceIP[2] = sourceEntry->sourceAddr[2]; mapping_entry->sourceIP[3] = sourceEntry->sourceAddr[3]; DEBUG("SIP4 : " IP4D , NIP4QUAD(mapping_entry->sourceIP)); } else { mapping_entry->sourceIP[0] = 0; mapping_entry->sourceIP[1] = 0; mapping_entry->sourceIP[2] = 0; mapping_entry->sourceIP[3] = 0; DEBUG("sourceEntry is NULL"); } #if defined(CONFIG_RTL9600_SERIES) mapping_entry->routingMode = RTK_RG_IPV4MC_DIS_ROUTING; #else //CONFIG_RTL9602C_SERIES & others new platform mapping_entry->routingMode = RTK_RG_IPV4MC_EN_ROUTING; #endif } else { mapping_entry->routingMode = RTK_RG_IPV4MC_EN_ROUTING; DEBUG("the client is RTK_RG_IPV4MC_DONT_CARE_SRC"); } #endif mapping_entry->ipVersion = param->ipVersion; mapping_entry->vlanId = param->vlanId; if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) { #if 0 #if defined(CONFIG_RTL9602C_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0xf); #elif defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0x7f); #else #error unknown platform platform yet! #endif #endif #if defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & ((1<<RTK_RG_MAC_PORT_MAX) - 1); #else mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; #endif } else { mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; } //mapping_entry->srcFilterMode = param->srcFilterMode; //// mapping_entry->srcFilterMode = multicastFwdInfo.srcFilterMode; //// /* add it into hw */ if (mapping_entry->fwdmembr!=0) //have member port in this entry { int r=_rtl_handle_igmpgroup_addhw(mapping_entry); /* if(param->ipVersion==IP_VERSION4) { DEBUG("IGMP SNOOPING ADD:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMP SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),multicastFwdInfo.fwdPortMask ,mapping_entry->hwflow_index); } */ if (r!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL, return\n"); return FAIL; } mapping_entry->refCnt=1; }else{ #if 0 if(RTK_RG_IPV4MC_EXCLUDE == multicastFwdInfo.srcFilterMode) { } else { } #endif DEBUG("IGMP SNOOPING Add nothing\n"); } #if 1 //if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE && multicastFwdInfo.l2PortMask!=0) { int hw_ent_idx; mapping_entry->ipVersion = param->ipVersion; mapping_entry->vlanId = param->vlanId; mapping_entry->fwdmembr = multicastFwdInfo.l2PortMask; mapping_entry->l2membr = multicastFwdInfo.l2PortMask; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_INCLUDE; if (mapping_entry->fwdmembr!=0) { int r=_rtl_handle_igmpgroup_addhw(mapping_entry); if (r!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL, return\n"); return FAIL; } } else { DEBUG("IGMP SNOOPING Add nothing\n"); } hw_ent_idx = mapping_entry->hwflow_index; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; /* mapping_entry->ipVersion = param->ipVersion; mapping_entry->vlanId = param->vlanId; mapping_entry->fwdmembr = multicastFwdInfo.grpPortMask; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; */ } #endif if(param->ipVersion==IP_VERSION4) { DEBUG("(GIP4: " IP4D ") pMask:0x%X LUT_IDX=%d\n" ,NIP4QUAD(param->groupAddr), multicastFwdInfo.fwdPortMask, mapping_entry->hwflow_index); } else { DEBUG("(GIP6: " IP6H ") pMask:0x%X LUT_IDX=%d\n" ,NIP6QUAD(param->groupAddr), multicastFwdInfo.fwdPortMask, mapping_entry->hwflow_index); } /*if(param->ipVersion==IP_VERSION4) { DEBUG("IGMP SNOOPING ADD:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMP SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); }*/ } else { int ret; /*if(param->ipVersion==IP_VERSION4) { DEBUG("IGMP SNOOPING CHANGE:IPv4(GIP:%d.%d.%d.%d) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); } else { DEBUG("IGMP SNOOPING CHANGE:IPv6(GIP:%X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X %X:%X:%X:%X) pMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(param->groupAddr[0]),NIPQUAD(param->groupAddr[1]),NIPQUAD(param->groupAddr[2]),NIPQUAD(param->groupAddr[3]),multicastFwdInfo.fwdPortMask ,mapping_entry->hwflow_index); }*/ if (mapping_entry->srcFilterMode==multicastFwdInfo.srcFilterMode) { #if 0 /* modify member port */ //mapping_entry->srcFilterMode = multicastFwdInfo.srcFilterMode; //// mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; /* update it into hw */ if (mapping_entry->fwdmembr!=0) //have member port in this entry { if (_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL\n"); return FAIL; } } else { /* no member ports, clean it in hw */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if (ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); return FAIL; } } #else if (mapping_entry->srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) { #if 0 #if defined(CONFIG_RTL9602C_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0xf); #elif defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0x7f); #else #error unknown platform platform yet! #endif #endif #if defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & ((1<<RTK_RG_MAC_PORT_MAX) - 1); #else mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; #endif } else { mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; } //if (mapping_entry->fwdmembr!=0) //have member port in this entry if (multicastFwdInfo.fwdPortMask!=0) //have member port in this entry { if (_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL\n"); return FAIL; } mapping_entry->refCnt=1; } else { /* no member ports, clean it in hw */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if (ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); return FAIL; } mapping_entry->refCnt=0; } //if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE && multicastFwdInfo.l2PortMask!=0) { mapping_entry->fwdmembr = multicastFwdInfo.l2PortMask; mapping_entry->l2membr = multicastFwdInfo.l2PortMask; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_INCLUDE; if (mapping_entry->fwdmembr!=0) //have member port in this entry { if (_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL, return\n"); return FAIL; } } mapping_entry->l2membr = multicastFwdInfo.fwdPortMask; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; //mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; //break; } #endif } else { DEBUG("old mode=%d\n", mapping_entry->srcFilterMode); DEBUG("new mode=%d\n", multicastFwdInfo.srcFilterMode); /* it is different from previous mode, delete entry first */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if( ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK ) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); return FAIL; } mapping_entry->srcFilterMode = multicastFwdInfo.srcFilterMode; //mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; if (mapping_entry->srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) { #if 0 #if defined(CONFIG_RTL9602C_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0xf); #elif defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & (0x7f); #else #error unknown platform platform yet! #endif #endif #if defined(CONFIG_RTL9600_SERIES) mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask & ((1<<RTK_RG_MAC_PORT_MAX) - 1); #else mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; #endif } else { mapping_entry->fwdmembr=multicastFwdInfo.fwdPortMask; } if (multicastFwdInfo.srcFilterMode != RTK_RG_IPV4MC_DONT_CARE_SRC) { mapping_entry->routingMode = RTK_RG_IPV4MC_DIS_ROUTING; } else { mapping_entry->routingMode = RTK_RG_IPV4MC_EN_ROUTING; } //if (mapping_entry->fwdmembr!=0) //have member port in this entry if (multicastFwdInfo.fwdPortMask!=0) //have member port in this entry { if(_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL\n"); return FAIL; } mapping_entry->refCnt=1; } else { /* no member ports, clean it in hw */ ret = _rtl_handle_igmpgroup_delhw(mapping_entry); if( ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK ) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); return FAIL; } mapping_entry->refCnt=0; } #if 1 //if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE) if (multicastFwdInfo.srcFilterMode==RTK_RG_IPV4MC_EXCLUDE && multicastFwdInfo.l2PortMask!=0) { mapping_entry->fwdmembr = multicastFwdInfo.l2PortMask; mapping_entry->l2membr = multicastFwdInfo.l2PortMask; mapping_entry->srcFilterMode = RTK_RG_IPV4MC_INCLUDE; if (mapping_entry->fwdmembr!=0) //have member port in this entry { if(_rtl_handle_igmpgroup_addhw(mapping_entry)!=SUCCESS) { DEBUG("IGMP SNOOPING ADD:FAIL, return\n"); return FAIL; } } mapping_entry->srcFilterMode = RTK_RG_IPV4MC_EXCLUDE; mapping_entry->fwdmembr = multicastFwdInfo.fwdPortMask; } #endif } } DEBUG("===Dump After-Start rtl_multicast_index_mapping_listhead====\n"); list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if(mapping_entry_temp->ipVersion==IP_VERSION4) { /* DEBUG("(GIP4: " IP4D ") pMask:0x%X LUT_IDX=%d\n" //,NIP4QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); ,NIPQUAD(mapping_entry_temp->groupIP), mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index);*/ DEBUG("IGMP HW Entry: GIP4:" IP4D " SIP4:" IP4D " l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIPQUAD(mapping_entry_temp->groupIP), NIPQUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } else { /* DEBUG("(GIP6: " IP6H ") pMask:0x%X LUT_IDX=%d\n" //,NIP6QUAD(param->groupAddr),multicastFwdInfo.fwdPortMask,mapping_entry->hwflow_index); ,NIP6QUAD(mapping_entry_temp->groupIP), mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index);*/ DEBUG("IGMP HW Entry: GIP6:" IP6H " SIP6:" IP6H " l2Mask:0x%X fwdMask:0x%X LUT_IDX=%d\n" ,NIP6QUAD(mapping_entry_temp->groupIP), NIP6QUAD(mapping_entry_temp->sourceIP), mapping_entry_temp->l2membr, mapping_entry_temp->fwdmembr, mapping_entry_temp->hwflow_index); } } DEBUG("===Dump After-End rtl_multicast_index_mapping_listhead====\n"); DEBUG("(%s %d) SUCCESS!!\n",__func__,__LINE__); //DEBUG("return"); //return SUCCESS; #if 1 //per source considerate //sourceEntry=nextSourceEntry; if (sourceEntry!=NULL) sourceEntry=sourceEntry->next; } while (sourceEntry!=NULL); //do-while sourceEntry clientEntry=clientEntry->next; DEBUG("check nex client"); } //while client != NULL if (NULL==groupEntry->clientList) { int ret; DEBUG("GIP has no client => delete all GIP hw-entries"); list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if (mapping_entry_temp->groupIP[0] == param->groupAddr[0] && mapping_entry_temp->groupIP[1] == param->groupAddr[1] && mapping_entry_temp->groupIP[2] == param->groupAddr[2] && mapping_entry_temp->groupIP[3] == param->groupAddr[3] && mapping_entry_temp->ipVersion == param->ipVersion) { //ret = _rtl_handle_igmpgroup_delhw(mapping_entry); ret = _rtl_handle_igmpgroup_delhw(mapping_entry_temp); _rtk_hwMappingEntry_free(mapping_entry_temp); if (ret!=RT_ERR_RG_ENTRY_NOT_EXIST && ret!=RT_ERR_RG_OK) { DEBUG("IGMP SNOOPING DEL:FAIL\n"); //DEBUG("return"); //return FAIL; } else { DEBUG("IGMP SNOOPING DEL:SUCCESS\n"); //DEBUG("return"); //return FAIL; } continue; } } } else { int ret; DEBUG("GIP clear redundant hw-entries"); list_for_each_entry_safe(mapping_entry_temp,mapping_entry_rm,&rtl_multicast_index_mapping_listhead,entry) { if (mapping_entry_temp != NULL) { if (mapping_entry_temp->refCnt!=1) { ret = _rtl_handle_igmpgroup_delhw(mapping_entry_temp); _rtk_hwMappingEntry_free(mapping_entry_temp); } } } } }//group != NULL #endif } //else if (rg_db.systemGlobal.initParam.igmpSnoopingEnable==2) #if 0 /*case 2:this is multicast event from ethernet(eth*) module */ if(memcmp(param->devName,"eth*",4)==0) { struct rtl_multicastFwdInfo multicastFwdInfo; struct rtl_multicastDataInfo multicastDataInfo; struct rtl_multicastDeviceInfo_s igmp_snooping_module; int retVal; multicastDataInfo.ipVersion=IP_VERSION4; multicastDataInfo.sourceIp[0]= param->sourceAddr[0]; multicastDataInfo.groupAddr[0]= param->groupAddr[0]; retVal= rtl_getMulticastDataFwdInfo(param->moduleIndex, &multicastDataInfo, &multicastFwdInfo); if(retVal!=SUCCESS) { return FAIL; } retVal = rtl_getIgmpSnoopingModuleDevInfo(param->moduleIndex,&igmp_snooping_module); if(retVal!=SUCCESS) { return FAIL; } rtl865x_resetMulticastEntry(param->groupAddr[0],multicastFwdInfo.fwdPortMask); return SUCCESS; } #endif DEBUG("return"); return FAIL; } #endif //EXPORT_SYMBOL(igmp_show); //EXPORT_SYMBOL(rtl_setIgmpSnoopingModuleDevInfo); //EXPORT_SYMBOL(rtl_initMulticastSnooping); //EXPORT_SYMBOL(rtl_registerIgmpSnoopingModule); #endif