2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
29 #ifdef IGMP_SNOOP_SUPPORT
31 #include "../rt_config.h"
33 #include "../igmp_snoop.h"
36 static inline void initFreeEntryList(
37 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
38 IN PLIST_HEADER pList)
42 for (i = 0; i < FREE_MEMBER_POOL_SIZE; i++)
43 insertTailList(pList, (PLIST_ENTRY)&(pMulticastFilterTable->freeMemberPool[i]));
48 static inline PMEMBER_ENTRY AllocaGrpMemberEntry(
49 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable)
51 PMEMBER_ENTRY pMemberEntry;
53 RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
55 pMemberEntry = (PMEMBER_ENTRY)removeHeadList(&pMulticastFilterTable->freeEntryList);
57 RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
59 return (PMEMBER_ENTRY)pMemberEntry;
62 static inline VOID FreeGrpMemberEntry(
63 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
64 IN PMEMBER_ENTRY pEntry)
66 RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
68 insertTailList(&pMulticastFilterTable->freeEntryList, (PLIST_ENTRY)pEntry);
70 RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
73 static VOID IGMPTableDisplay(
74 IN PRTMP_ADAPTER pAd);
76 static BOOLEAN isIgmpMacAddr(
79 static VOID InsertIgmpMember(
80 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
81 IN PLIST_HEADER pList,
82 IN PUCHAR pMemberAddr);
84 static VOID DeleteIgmpMember(
85 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
86 IN PLIST_HEADER pList,
87 IN PUCHAR pMemberAddr);
89 static VOID DeleteIgmpMemberList(
90 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
91 IN PLIST_HEADER pList);
95 ==========================================================================
97 This routine init the entire IGMP table.
98 ==========================================================================
100 VOID MulticastFilterTableInit(
101 IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable)
103 // Initialize MAC table and allocate spin lock
104 *ppMulticastFilterTable = kmalloc(sizeof(MULTICAST_FILTER_TABLE), MEM_ALLOC_FLAG);
105 if (*ppMulticastFilterTable == NULL)
107 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for Multicase filter table, size=%d\n",
108 __FUNCTION__, sizeof(MULTICAST_FILTER_TABLE)));
112 NdisZeroMemory(*ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE));
113 NdisAllocateSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock));
115 NdisAllocateSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock));
116 initList(&((*ppMulticastFilterTable)->freeEntryList));
117 initFreeEntryList(*ppMulticastFilterTable, &((*ppMulticastFilterTable)->freeEntryList));
122 ==========================================================================
124 This routine reset the entire IGMP table.
125 ==========================================================================
127 VOID MultiCastFilterTableReset(
128 IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable)
130 if(*ppMulticastFilterTable == NULL)
132 DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
136 NdisFreeSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock));
137 NdisFreeSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock));
138 kfree(*ppMulticastFilterTable);
139 *ppMulticastFilterTable = NULL;
143 ==========================================================================
145 Display all entrys in IGMP table
146 ==========================================================================
148 static VOID IGMPTableDisplay(
149 IN PRTMP_ADAPTER pAd)
152 MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL;
153 PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
155 if (pMulticastFilterTable == NULL)
157 DBGPRINT(RT_DEBUG_OFF, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
162 if (pMulticastFilterTable->Size == 0)
164 DBGPRINT(RT_DEBUG_ERROR, ("Table empty.\n"));
168 // allocate one MAC entry
169 RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
171 for (i = 0; i< MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
173 // pick up the first available vacancy
174 if (pMulticastFilterTable->Content[i].Valid == TRUE)
176 PMEMBER_ENTRY pMemberEntry = NULL;
177 pEntry = &pMulticastFilterTable->Content[i];
179 DBGPRINT(RT_DEBUG_OFF, ("IF(%s) entry #%d, type=%s, GrpId=(%02x:%02x:%02x:%02x:%02x:%02x) memberCnt=%d\n",
180 RTMP_OS_NETDEV_GET_DEVNAME(pEntry->net_dev), i, (pEntry->type==0 ? "static":"dynamic"),
181 PRINT_MAC(pEntry->Addr), IgmpMemberCnt(&pEntry->MemberList)));
183 pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead;
186 DBGPRINT(RT_DEBUG_OFF, ("member mac=(%02x:%02x:%02x:%02x:%02x:%02x)\n",
187 PRINT_MAC(pMemberEntry->Addr)));
189 pMemberEntry = pMemberEntry->pNext;
194 RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
200 ==========================================================================
202 Add and new entry into MAC table
203 ==========================================================================
205 BOOLEAN MulticastFilterTableInsertEntry(
206 IN PRTMP_ADAPTER pAd,
208 IN PUCHAR pMemberAddr,
210 IN MulticastFilterEntryType type)
214 MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL, *pCurrEntry, *pPrevEntry;
215 PMEMBER_ENTRY pMemberEntry;
216 PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
218 if (pMulticastFilterTable == NULL)
220 DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
225 if (pMulticastFilterTable->Size >= MAX_LEN_OF_MULTICAST_FILTER_TABLE)
227 DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table full. max-entries = %d\n",
228 __FUNCTION__, MAX_LEN_OF_MULTICAST_FILTER_TABLE));
232 // check the rule is in table already or not.
233 if ((pEntry = MulticastFilterTableLookup(pMulticastFilterTable, pGrpId, dev)))
235 // doesn't indicate member mac address.
236 if(pMemberAddr == NULL)
241 pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead;
245 if (MAC_ADDR_EQUAL(pMemberAddr, pMemberEntry->Addr))
247 DBGPRINT(RT_DEBUG_ERROR, ("%s: already in Members list.\n", __FUNCTION__));
251 pMemberEntry = pMemberEntry->pNext;
255 RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
259 // the multicast entry already exist but doesn't include the member yet.
260 if (pEntry != NULL && pMemberAddr != NULL)
262 InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
266 // allocate one MAC entry
267 for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
269 // pick up the first available vacancy
270 pEntry = &pMulticastFilterTable->Content[i];
271 NdisGetSystemUpTime(&Now);
272 if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC)
273 && ((Now - pEntry->lastTime) > IGMPMAC_TB_ENTRY_AGEOUT_TIME))
275 PMULTICAST_FILTER_TABLE_ENTRY pHashEntry;
277 HashIdx = MULTICAST_ADDR_HASH_INDEX(pEntry->Addr);
278 pHashEntry = pMulticastFilterTable->Hash[HashIdx];
280 if ((pEntry->net_dev == pHashEntry->net_dev)
281 && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr))
283 pMulticastFilterTable->Hash[HashIdx] = pHashEntry->pNext;
284 pMulticastFilterTable->Size --;
285 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size));
288 while (pHashEntry->pNext)
290 pPrevEntry = pHashEntry;
291 pHashEntry = pHashEntry->pNext;
292 if ((pEntry->net_dev == pHashEntry->net_dev)
293 && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr))
295 pPrevEntry->pNext = pHashEntry->pNext;
296 pMulticastFilterTable->Size --;
297 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
302 pEntry->Valid = FALSE;
303 DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
306 if (pEntry->Valid == FALSE)
308 NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
309 pEntry->Valid = TRUE;
311 COPY_MAC_ADDR(pEntry->Addr, pGrpId);
312 pEntry->net_dev = dev;
313 NdisGetSystemUpTime(&Now);
314 pEntry->lastTime = Now;
316 initList(&pEntry->MemberList);
317 if (pMemberAddr != NULL)
318 InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
320 pMulticastFilterTable->Size ++;
322 DBGPRINT(RT_DEBUG_TRACE, ("MulticastFilterTableInsertEntry -IF(%s) allocate entry #%d, Total= %d\n", RTMP_OS_NETDEV_GET_DEVNAME(dev), i, pMulticastFilterTable->Size));
327 // add this MAC entry into HASH table
330 HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId);
331 if (pMulticastFilterTable->Hash[HashIdx] == NULL)
333 pMulticastFilterTable->Hash[HashIdx] = pEntry;
336 pCurrEntry = pMulticastFilterTable->Hash[HashIdx];
337 while (pCurrEntry->pNext != NULL)
338 pCurrEntry = pCurrEntry->pNext;
339 pCurrEntry->pNext = pEntry;
344 RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
350 ==========================================================================
352 Delete a specified client from MAC table
353 ==========================================================================
355 BOOLEAN MulticastFilterTableDeleteEntry(
356 IN PRTMP_ADAPTER pAd,
358 IN PUCHAR pMemberAddr,
362 MULTICAST_FILTER_TABLE_ENTRY *pEntry, *pPrevEntry;
363 PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
364 USHORT Aid = MCAST_WCID;
366 UCHAR PsMode = PWR_ACTIVE, Rate;
368 if (pMulticastFilterTable == NULL)
370 DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
374 RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
378 HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId);
379 pPrevEntry = pEntry = pMulticastFilterTable->Hash[HashIdx];
381 while (pEntry && pEntry->Valid)
383 if ((pEntry->net_dev == dev)
384 && MAC_ADDR_EQUAL(pEntry->Addr, pGrpId))
389 pEntry = pEntry->pNext;
393 // check the rule is in table already or not.
394 if (pEntry && (pMemberAddr != NULL))
396 if(APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate))
397 DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
398 if (IgmpMemberCnt(&pEntry->MemberList) > 0)
404 if (pEntry == pMulticastFilterTable->Hash[HashIdx])
406 pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext;
407 DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
408 NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
409 pMulticastFilterTable->Size --;
410 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size));
414 pPrevEntry->pNext = pEntry->pNext;
415 DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
416 NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
417 pMulticastFilterTable->Size --;
418 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
423 DBGPRINT(RT_DEBUG_ERROR, ("%s: the Group doesn't exist.\n", __FUNCTION__));
427 RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
433 ==========================================================================
435 Look up the MAC address in the IGMP table. Return NULL if not found.
437 pEntry - pointer to the MAC entry; NULL is not found
438 ==========================================================================
440 PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup(
441 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
446 PMULTICAST_FILTER_TABLE_ENTRY pEntry = NULL, pPrev = NULL;
448 if (pMulticastFilterTable == NULL)
450 DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
454 RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
456 HashIdx = MULTICAST_ADDR_HASH_INDEX(pAddr);
457 pEntry = pPrev = pMulticastFilterTable->Hash[HashIdx];
459 while (pEntry && pEntry->Valid)
461 if ((pEntry->net_dev == dev)
462 && MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
464 NdisGetSystemUpTime(&Now);
465 pEntry->lastTime = Now;
470 NdisGetSystemUpTime(&Now);
471 if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC)
472 && RTMP_TIME_AFTER(Now, pEntry->lastTime+IGMPMAC_TB_ENTRY_AGEOUT_TIME))
474 // Remove the aged entry
475 if (pEntry == pMulticastFilterTable->Hash[HashIdx])
477 pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext;
478 pPrev = pMulticastFilterTable->Hash[HashIdx];
479 DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
480 NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
481 pMulticastFilterTable->Size --;
483 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
487 pPrev->pNext = pEntry->pNext;
488 DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
489 NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
490 pMulticastFilterTable->Size --;
491 pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
492 DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
498 pEntry = pEntry->pNext;
503 RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
509 IN PRTMP_ADAPTER pAd,
510 IN PUCHAR pDstMacAddr,
511 IN PUCHAR pSrcMacAddr,
525 UCHAR GroupMacAddr[6];
526 PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
528 if(isIgmpPkt(pDstMacAddr, pIpHeader))
530 IpHeaderLen = (*(pIpHeader + 2) & 0x0f) * 4;
531 pIgmpHeader = pIpHeader + 2 + IpHeaderLen;
532 IgmpVerType = (UCHAR)(*(pIgmpHeader));
534 DBGPRINT(RT_DEBUG_TRACE, ("IGMP type=%0x\n", IgmpVerType));
538 case IGMP_V1_MEMBERSHIP_REPORT: // IGMP version 1 membership report.
539 case IGMP_V2_MEMBERSHIP_REPORT: // IGMP version 2 membership report.
540 pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4);
541 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
542 DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
543 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
544 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
547 case IGMP_LEAVE_GROUP: // IGMP version 1 and version 2 leave group.
548 pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4);
549 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
550 DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
551 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
552 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
555 case IGMP_V3_MEMBERSHIP_REPORT: // IGMP version 3 membership report.
556 numOfGroup = ntohs(*((UINT16 *)(pIgmpHeader + 6)));
557 pGroup = (PUCHAR)(pIgmpHeader + 8);
558 for (i=0; i < numOfGroup; i++)
560 GroupType = (UCHAR)(*pGroup);
561 AuxDataLen = (UCHAR)(*(pGroup + 1));
562 numOfSources = ntohs(*((UINT16 *)(pGroup + 2)));
563 pGroupIpAddr = (PUCHAR)(pGroup + 4);
564 DBGPRINT(RT_DEBUG_TRACE, ("IGMPv3 Type=%d, ADL=%d, numOfSource=%d\n", GroupType, AuxDataLen, numOfSources));
565 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
566 DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
567 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
571 if((GroupType == MODE_IS_EXCLUDE) || (GroupType == CHANGE_TO_EXCLUDE_MODE) || (GroupType == ALLOW_NEW_SOURCES))
573 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
577 if((GroupType == MODE_IS_INCLUDE) || (GroupType == BLOCK_OLD_SOURCES))
579 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
583 if((GroupType == CHANGE_TO_INCLUDE_MODE))
585 if(numOfSources == 0)
586 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
588 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
592 pGroup += (8 + (numOfSources * 4) + AuxDataLen);
597 DBGPRINT(RT_DEBUG_TRACE, ("unknow IGMP Type=%d\n", IgmpVerType));
606 static BOOLEAN isIgmpMacAddr(
609 if((pMacAddr[0] == 0x01)
610 && (pMacAddr[1] == 0x00)
611 && (pMacAddr[2] == 0x5e))
617 IN PUCHAR pDstMacAddr,
620 UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader)));
623 if(!isIgmpMacAddr(pDstMacAddr))
626 if(IpProtocol == ETH_P_IP)
628 IgmpProtocol = (UCHAR)*(pIpHeader + 11);
629 if(IgmpProtocol == IGMP_PROTOCOL_DESCRIPTOR)
636 static VOID InsertIgmpMember(
637 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
638 IN PLIST_HEADER pList,
639 IN PUCHAR pMemberAddr)
641 PMEMBER_ENTRY pMemberEntry;
645 DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
649 if (pMemberAddr == NULL)
651 DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__));
655 if((pMemberEntry = (PMEMBER_ENTRY)AllocaGrpMemberEntry(pMulticastFilterTable)) != NULL)
657 NdisZeroMemory(pMemberEntry, sizeof(MEMBER_ENTRY));
658 COPY_MAC_ADDR(pMemberEntry->Addr, pMemberAddr);
659 insertTailList(pList, (PLIST_ENTRY)pMemberEntry);
661 DBGPRINT(RT_DEBUG_TRACE, ("%s Member Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
662 pMemberEntry->Addr[0], pMemberEntry->Addr[1], pMemberEntry->Addr[2],
663 pMemberEntry->Addr[3], pMemberEntry->Addr[4], pMemberEntry->Addr[5]));
668 static VOID DeleteIgmpMember(
669 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
670 IN PLIST_HEADER pList,
671 IN PUCHAR pMemberAddr)
673 PMEMBER_ENTRY pCurEntry;
675 if((pList == NULL) || (pList->pHead == NULL))
677 DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
681 if (pMemberAddr == NULL)
683 DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__));
687 pCurEntry = (PMEMBER_ENTRY)pList->pHead;
690 if(MAC_ADDR_EQUAL(pMemberAddr, pCurEntry->Addr))
692 delEntryList(pList, (PLIST_ENTRY)pCurEntry);
693 FreeGrpMemberEntry(pMulticastFilterTable, pCurEntry);
696 pCurEntry = pCurEntry->pNext;
702 static VOID DeleteIgmpMemberList(
703 IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
704 IN PLIST_HEADER pList)
706 PMEMBER_ENTRY pCurEntry, pPrvEntry;
708 if((pList == NULL) || (pList->pHead == NULL))
710 DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
714 pPrvEntry = pCurEntry = (PMEMBER_ENTRY)pList->pHead;
717 delEntryList(pList, (PLIST_ENTRY)pCurEntry);
718 pPrvEntry = pCurEntry;
719 pCurEntry = pCurEntry->pNext;
720 FreeGrpMemberEntry(pMulticastFilterTable, pPrvEntry);
729 IN PLIST_HEADER pList)
733 DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
737 return getListSize(pList);
740 VOID IgmpGroupDelMembers(
741 IN PRTMP_ADAPTER pAd,
742 IN PUCHAR pMemberAddr,
746 MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL;
747 PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
749 for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
751 // pick up the first available vacancy
752 pEntry = &pMulticastFilterTable->Content[i];
753 if (pEntry->Valid == TRUE)
755 if(pMemberAddr != NULL)
757 RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
758 DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
759 RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
762 if((pEntry->type == MCAT_FILTER_DYNAMIC)
763 && (IgmpMemberCnt(&pEntry->MemberList) == 0))
764 MulticastFilterTableDeleteEntry(pAd, pEntry->Addr, pMemberAddr, pDev);
769 INT Set_IgmpSn_Enable_Proc(
770 IN PRTMP_ADAPTER pAd,
778 pObj = (POS_COOKIE) pAd->OS_Cookie;
779 ifIndex = pObj->ioctl_if;
781 pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev);
782 Enable = (UINT) simple_strtol(arg, 0, 10);
784 pAd->ApCfg.MBSSID[ifIndex].IgmpSnoopEnable = (BOOLEAN)(Enable == 0 ? 0 : 1);
785 DBGPRINT(RT_DEBUG_TRACE, ("%s::(%s) %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(pDev), Enable == TRUE ? "Enable IGMP Snooping":"Disable IGMP Snooping"));
790 INT Set_IgmpSn_AddEntry_Proc(
791 IN PRTMP_ADAPTER pAd,
795 BOOLEAN bGroupId = 1;
799 UCHAR Addr[ETH_LENGTH_OF_ADDRESS];
800 UCHAR GroupId[ETH_LENGTH_OF_ADDRESS];
801 PUCHAR *pAddr = (PUCHAR *)&Addr;
806 pObj = (POS_COOKIE) pAd->OS_Cookie;
807 ifIndex = pObj->ioctl_if;
809 pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev);
811 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
813 // refuse the Member if it's not a MAC address.
814 if((bGroupId == 0) && (strlen(thisChar) != 17))
817 if(strlen(thisChar) == 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
819 for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":"))
821 if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
822 return FALSE; //Invalid
824 AtoH(value, &Addr[i++], 1);
828 return FALSE; //Invalid
832 for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,"."))
834 if((strlen(value) > 0) && (strlen(value) <= 3))
837 for(ii=0; ii<strlen(value); ii++)
838 if (!isxdigit(*(value + ii)))
842 return FALSE; //Invalid
844 IpAddr[i] = (UCHAR)simple_strtol(value, NULL, 10);
849 return FALSE; //Invalid
851 ConvertMulticastIP2MAC(IpAddr, (PUCHAR *)&pAddr, ETH_P_IP);
855 COPY_MAC_ADDR(GroupId, Addr);
857 // Group-Id must be a MCAST address.
858 if((bGroupId == 1) && IS_MULTICAST_MAC_ADDR(Addr))
859 MulticastFilterTableInsertEntry(pAd, GroupId, NULL, pDev, MCAT_FILTER_STATIC);
860 // Group-Member must be a UCAST address.
861 else if ((bGroupId == 0) && !IS_MULTICAST_MAC_ADDR(Addr))
862 MulticastFilterTableInsertEntry(pAd, GroupId, Addr, pDev, MCAT_FILTER_STATIC);
865 DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X) is not a acceptable address.\n",
866 __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
871 DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n",
872 __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
879 INT Set_IgmpSn_DelEntry_Proc(
880 IN PRTMP_ADAPTER pAd,
883 INT i, memberCnt = 0;
884 BOOLEAN bGroupId = 1;
888 UCHAR Addr[ETH_LENGTH_OF_ADDRESS];
889 UCHAR GroupId[ETH_LENGTH_OF_ADDRESS];
890 PUCHAR *pAddr = (PUCHAR *)&Addr;
895 pObj = (POS_COOKIE) pAd->OS_Cookie;
896 ifIndex = pObj->ioctl_if;
898 pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev);
900 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
902 // refuse the Member if it's not a MAC address.
903 if((bGroupId == 0) && (strlen(thisChar) != 17))
906 if(strlen(thisChar) == 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
908 for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":"))
910 if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
911 return FALSE; //Invalid
913 AtoH(value, &Addr[i++], 1);
917 return FALSE; //Invalid
921 for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,"."))
923 if((strlen(value) > 0) && (strlen(value) <= 3))
926 for(ii=0; ii<strlen(value); ii++)
927 if (!isxdigit(*(value + ii)))
931 return FALSE; //Invalid
933 IpAddr[i] = (UCHAR)simple_strtol(value, NULL, 10);
938 return FALSE; //Invalid
940 ConvertMulticastIP2MAC(IpAddr, (PUCHAR *)&pAddr, ETH_P_IP);
944 COPY_MAC_ADDR(GroupId, Addr);
949 MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, Addr, pDev);
955 MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, NULL, pDev);
957 DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n",
958 __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
963 INT Set_IgmpSn_TabDisplay_Proc(
964 IN PRTMP_ADAPTER pAd,
967 IGMPTableDisplay(pAd);
971 void rtmp_read_igmp_snoop_from_file(
972 IN PRTMP_ADAPTER pAd,
980 if(RTMPGetKeyParameter("IgmpSnEnable", tmpbuf, 128, buffer, TRUE))
982 for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), i++)
984 if ((strncmp(macptr, "0", 1) == 0))
985 pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = FALSE;
986 else if ((strncmp(macptr, "1", 1) == 0))
987 pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = TRUE;
989 pAd->ApCfg.MBSSID[i].IgmpSnoopEnable = FALSE;
991 DBGPRINT(RT_DEBUG_TRACE, ("MBSSID[%d].Enable=%d\n", i, pAd->ApCfg.MBSSID[i].IgmpSnoopEnable));
996 NDIS_STATUS IgmpPktInfoQuery(
997 IN PRTMP_ADAPTER pAd,
999 IN PNDIS_PACKET pPacket,
1001 OUT BOOLEAN *pInIgmpGroup,
1002 OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry)
1004 if(IS_MULTICAST_MAC_ADDR(pSrcBufVA))
1006 BOOLEAN IgmpMldPkt = FALSE;
1007 PUCHAR pIpHeader = pSrcBufVA + 12;
1009 if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6)
1010 IgmpMldPkt = isMldPkt(pSrcBufVA, pIpHeader, NULL, NULL);
1012 IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader);
1016 *ppGroupEntry = NULL;
1018 else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA,
1019 pAd->ApCfg.MBSSID[apidx].MSSIDDev)) == NULL)
1021 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1022 return NDIS_STATUS_FAILURE;
1024 *pInIgmpGroup = TRUE;
1026 else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA))
1028 PUCHAR pDstIpAddr = pSrcBufVA + 30; // point to Destination of Ip address of IP header.
1029 UCHAR GroupMacAddr[6];
1030 PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
1032 ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
1033 if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr,
1034 pAd->ApCfg.MBSSID[apidx].MSSIDDev)) != NULL)
1036 *pInIgmpGroup = TRUE;
1039 return NDIS_STATUS_SUCCESS;
1042 NDIS_STATUS IgmpPktClone(
1043 IN PRTMP_ADAPTER pAd,
1044 IN PNDIS_PACKET pPacket,
1046 IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry)
1048 PNDIS_PACKET pSkbClone = NULL;
1049 PMEMBER_ENTRY pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead;
1050 MAC_TABLE_ENTRY *pMacEntry = NULL;
1052 SST Sst = SST_ASSOC;
1053 UCHAR PsMode = PWR_ACTIVE;
1055 unsigned long IrqFlags;
1057 // check all members of the IGMP group.
1058 while(pMemberEntry != NULL)
1060 pMacEntry = APSsPsInquiry(pAd, pMemberEntry->Addr, &Sst, &Aid, &PsMode, &Rate);
1062 if (pMacEntry && (Sst == SST_ASSOC) && (PsMode != PWR_SAVE))
1064 pSkbClone = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
1067 RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)Aid);
1068 // Pkt type must set to PKTSRC_NDIS.
1069 // It cause of the deason that APHardTransmit()
1070 // doesn't handle PKTSRC_DRIVER pkt type in version 1.3.0.0.
1071 RTMP_SET_PACKET_SOURCE(pSkbClone, PKTSRC_NDIS);
1075 pMemberEntry = pMemberEntry->pNext;
1079 // insert the pkt to TxSwQueue.
1080 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1083 StopNetIfQueue(pAd, QueIdx, pSkbClone);
1084 #endif // BLOCK_NET_IF //
1085 RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE);
1086 return NDIS_STATUS_FAILURE;
1090 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1091 InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pSkbClone));
1092 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1095 pMemberEntry = pMemberEntry->pNext;
1097 return NDIS_STATUS_SUCCESS;
1100 static inline BOOLEAN isMldMacAddr(
1103 return ((pMacAddr[0] == 0x33) && (pMacAddr[1] == 0x33)) ? TRUE : FALSE;
1106 static inline BOOLEAN IsSupportedMldMsg(
1109 BOOLEAN result = FALSE;
1112 case MLD_V1_LISTENER_REPORT:
1113 case MLD_V1_LISTENER_DONE:
1114 case MLD_V2_LISTERNER_REPORT:
1126 IN PUCHAR pDstMacAddr,
1127 IN PUCHAR pIpHeader,
1128 OUT UINT8 *pProtoType,
1129 OUT PUCHAR *pMldHeader)
1131 BOOLEAN result = FALSE;
1132 UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader)));
1134 if(!isMldMacAddr(pDstMacAddr))
1137 if(IpProtocol != ETH_P_IPV6)
1140 // skip protocol (2 Bytes).
1144 PRT_IPV6_HDR pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader);
1145 UINT8 nextProtocol = pIpv6Hdr->nextHdr;
1146 UINT32 offset = IPV6_HDR_LEN;
1148 while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6)
1150 if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE)
1154 if(nextProtocol == IPV6_NEXT_HEADER_ICMPV6)
1156 PRT_ICMPV6_HDR pICMPv6Hdr = (PRT_ICMPV6_HDR)(pIpHeader + offset);
1157 if (IsSupportedMldMsg(pICMPv6Hdr->type) == TRUE)
1159 if (pProtoType != NULL)
1160 *pProtoType = pICMPv6Hdr->type;
1161 if (pMldHeader != NULL)
1162 *pMldHeader = (PUCHAR)pICMPv6Hdr;
1171 /* MLD v1 messages have the following format:
1173 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1174 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1175 | Type | Code | Checksum |
1176 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1177 | Maximum Response Delay | Reserved |
1178 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1182 + Multicast Address +
1186 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1189 /* Version 3 Membership Report Message
1191 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1192 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1193 | Type = 143 | Reserved | Checksum |
1194 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1195 | Reserved | Number of Group Records (M) |
1196 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1199 . Multicast Address Record [1] .
1202 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1205 . Multicast Address Record [2] .
1208 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1212 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1215 . Multicast Address Record [M] .
1218 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1221 where each Group Record has the following internal format:
1222 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1223 | Record Type | Aux Data Len | Number of Sources (N) |
1224 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1228 * Multicast Address *
1232 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1236 * Source Address [1] *
1244 * Source Address [2] *
1256 * Source Address [N] *
1260 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1266 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1270 IN PRTMP_ADAPTER pAd,
1271 IN PUCHAR pDstMacAddr,
1272 IN PUCHAR pSrcMacAddr,
1273 IN PUCHAR pIpHeader,
1281 UINT16 numOfSources;
1282 PUCHAR pGroupIpAddr;
1283 UCHAR GroupMacAddr[6];
1284 PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
1289 if(isMldPkt(pDstMacAddr, pIpHeader, &MldType, &pMldHeader) == TRUE)
1291 DBGPRINT(RT_DEBUG_TRACE, ("MLD type=%0x\n", MldType));
1295 case MLD_V1_LISTENER_REPORT:
1296 // skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes).
1297 pGroupIpAddr = (PUCHAR)(pMldHeader + 8);
1298 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
1299 DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n",
1300 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
1301 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
1304 case MLD_V1_LISTENER_DONE:
1305 // skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes).
1306 pGroupIpAddr = (PUCHAR)(pMldHeader + 8);
1307 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
1308 DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n",
1309 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
1310 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
1313 case MLD_V2_LISTERNER_REPORT: // IGMP version 3 membership report.
1314 numOfGroup = ntohs(*((UINT16 *)(pMldHeader + 6)));
1315 pGroup = (PUCHAR)(pMldHeader + 8);
1316 for (i=0; i < numOfGroup; i++)
1318 GroupType = (UCHAR)(*pGroup);
1319 AuxDataLen = (UCHAR)(*(pGroup + 1));
1320 numOfSources = ntohs(*((UINT16 *)(pGroup + 2)));
1321 pGroupIpAddr = (PUCHAR)(pGroup + 4);
1322 DBGPRINT(RT_DEBUG_TRACE, ("MLDv2 Type=%d, ADL=%d, numOfSource=%d\n", GroupType, AuxDataLen, numOfSources));
1323 ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
1324 DBGPRINT(RT_DEBUG_TRACE, ("MLD Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
1325 GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
1329 if((GroupType == MODE_IS_EXCLUDE) || (GroupType == CHANGE_TO_EXCLUDE_MODE) || (GroupType == ALLOW_NEW_SOURCES))
1331 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
1335 if((GroupType == MODE_IS_INCLUDE) || (GroupType == BLOCK_OLD_SOURCES))
1337 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
1341 if((GroupType == CHANGE_TO_INCLUDE_MODE))
1343 if(numOfSources == 0)
1344 MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
1346 MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
1350 // skip 4 Bytes (Record Type, Aux Data Len, Number of Sources) + a IPv6 address.
1351 pGroup += (4 + IPV6_ADDR_LEN + (numOfSources * 16) + AuxDataLen);
1356 DBGPRINT(RT_DEBUG_TRACE, ("unknow MLD Type=%d\n", MldType));
1365 #endif // IGMP_SNOOP_SUPPORT //