<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.6000.16587" name=GENERATOR></HEAD>
<BODY>
<DIV><FONT face=Arial size=2><SPAN class=684521713-24072008>In the past there 
have been some patches that were sent by <A 
href="mailto:slavas@voltaire.com">slavas@voltaire.com</A> regarding this 
issues.</SPAN></FONT></DIV>
<DIV><FONT face=Arial size=2><SPAN 
class=684521713-24072008></SPAN></FONT> </DIV>
<DIV><FONT face=Arial size=2><SPAN class=684521713-24072008>After some work with 
him, here is the final patch that we have came through.</SPAN></FONT></DIV>
<DIV><FONT face=Arial size=2><SPAN 
class=684521713-24072008></SPAN></FONT> </DIV>
<DIV><FONT face=Arial size=2><SPAN class=684521713-24072008>Any comments are 
welcomed.</SPAN></FONT></DIV>
<DIV><FONT face=Arial size=2><SPAN 
class=684521713-24072008></SPAN></FONT> </DIV>
<DIV><FONT face=Arial size=2><SPAN 
class=684521713-24072008>Thanks</SPAN></FONT></DIV>
<DIV><FONT face=Arial size=2><SPAN 
class=684521713-24072008>Tzachi</SPAN></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c (revision 2846)<BR>@@ 
-762,8 +762,13 @@<BR> <BR>    if( j != 
p_adapter->mcast_array_size 
)<BR>     continue;<BR>-<BR>-   ipoib_port_join_mcast( 
p_port, p_mac_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);<BR>+   if ( 
( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && 
p_mac_array[i].addr[2] == 0x5e 
&&<BR>+       p_mac_array[i].addr[3] == 0 
&& p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) 
||<BR>+      !( p_mac_array[i].addr[0] == 1 && 
p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e 
)<BR>+    )<BR>+   {<BR>+    ipoib_port_join_mcast( 
p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER 
);<BR>+   }<BR>   }<BR>  }<BR> <BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c (revision 2846)<BR>@@ -67,7 
+67,8 
@@<BR> ipoib_port_t *gp_ipoib_port;<BR> #endif<BR> <BR>-<BR>+static 
void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void 
*s_arg2);<BR>+static void __port_do_mcast_garbage(ipoib_port_t* 
const p_port 
);<BR> /******************************************************************************<BR> *<BR> * 
Declarations<BR>@@ -291,6 +292,14 
@@<BR>  IN OUT   ipoib_send_desc_t* 
const p_desc );<BR> <BR> static 
NDIS_STATUS<BR>+__send_mgr_filter_igmp_v2(<BR>+ IN    ipoib_port_t* 
const   p_port,<BR>+    
IN  const ip_hdr_t* 
const    p_ip_hdr,<BR>+ IN    size_t      iph_options_size,<BR>+ IN    NDIS_BUFFER*    p_buf,<BR>+ IN    size_t      buf_len 
);<BR>+<BR>+static 
NDIS_STATUS<BR> __send_mgr_filter_udp(<BR>  IN    ipoib_port_t* 
const   p_port,<BR>  IN  const ip_hdr_t* 
const    p_ip_hdr,<BR>@@ -490,6 +499,13 
@@<BR> #endif<BR> }<BR> <BR>+/* function returns pointer to 
payload that is going after IP header.<BR>+*  asssuming that payload and IP 
header are in the same buffer<BR>+*/<BR>+static void* 
GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr)<BR>+{<BR>+ return 
(void*)((uint8_t*)p_ip_hdr + 4*(p_ip_hdr->ver_hl & 
0xf));<BR>+}<BR> <BR> /******************************************************************************<BR> *<BR>@@ 
-653,6 +669,9 @@<BR>    p_adapter->p_ifc->get_err_str( 
status )) );<BR>   return status;<BR>  }<BR>+  /* 
Initialize multicast garbage collector timer and DPC object */<BR>+  
KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);<BR>+  
KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);<BR> <BR>  /* 
We only ever destroy from the PnP callback thread. */<BR>  cl_status = 
cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,<BR>@@ -748,6 +767,8 
@@<BR> <BR>  p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj 
);<BR> <BR>+ KeCancelTimer(&p_port->gc_timer);<BR>+ KeFlushQueuedDpcs();<BR>  __endpt_mgr_destroy( 
p_port );<BR>  __recv_mgr_destroy( p_port 
);<BR>  __send_mgr_destroy( p_port );<BR>@@ -2133,6 +2154,9 
@@<BR>  p_eth->hdr.src = 
p_src->mac;<BR>  p_eth->hdr.dst = 
p_dst->mac;<BR> <BR>+ if (p_dst->h_mcast) 
{<BR>+  p_dst->is_in_use = 
TRUE;<BR>+ }<BR>  IPOIB_EXIT( IPOIB_DBG_RECV 
);<BR>  return IB_SUCCESS;<BR> }<BR>@@ -3106,6 +3130,26 
@@<BR>  if( p_ip_hdr->offset 
||<BR>   p_ip_hdr->prot != IP_PROT_UDP 
)<BR>  {<BR>+  /* Check if this packet is IGMP 
*/<BR>+  if ( p_ip_hdr->prot == IP_PROT_IGMP ) 
<BR>+  {<BR>+   /*<BR>+       
In igmp packet I saw that iph arrive in 2 
NDIS_BUFFERs:<BR>+    1. iph<BR>+    2. 
ip options<BR>+    So to get the IGMP packet we need to skip 
the ip options NDIS_BUFFER<BR>+   */<BR>+   size_t 
iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 
4;<BR>+   size_t iph_options_size = iph_size_in_bytes - 
buf_len;<BR>+   buf_len -= sizeof(ip_hdr_t);//without 
ipheader<BR>+<BR>+   /*<BR>+       
Could be a case that arrived igmp packet not from type IGMPv2 
,<BR>+    but IGMPv1 or 
IGMPv3.<BR>+    We anyway pass it to 
__send_mgr_filter_igmp_v2().<BR>+   */<BR>+   __send_mgr_filter_igmp_v2(p_port, 
p_ip_hdr, iph_options_size, p_buf, 
buf_len);<BR>+  }<BR>   /* Not a UDP packet. 
*/<BR>   cl_perf_start( SendTcp );<BR>   status = 
__send_gen( p_port, p_desc );<BR>@@ -3125,7 +3169,134 @@<BR>  return 
status;<BR> }<BR> <BR>+static 
NDIS_STATUS<BR>+__send_mgr_filter_igmp_v2(<BR>+ IN    ipoib_port_t* 
const   p_port,<BR>+ IN  const ip_hdr_t* 
const    p_ip_hdr,<BR>+ IN    size_t      iph_options_size,<BR>+ IN    NDIS_BUFFER*    p_buf,<BR>+ IN    size_t      buf_len 
)<BR>+{<BR>+ igmp_v2_hdr_t  *p_igmp_v2_hdr = 
NULL;<BR>+ NDIS_STATUS   endpt_status;<BR>+ ipoib_endpt_t* 
  p_endpt = 
NULL;<BR>+ mac_addr_t   fake_mcast_mac;<BR> <BR>+ IPOIB_ENTER( 
IPOIB_DBG_SEND );<BR>+<BR>+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, 
IPOIB_DBG_MCAST,<BR>+    ("buf_len = %d,iph_options_size = 
%d\n",(int)buf_len,(int)iph_options_size ) );<BR>+<BR>+ if( !buf_len 
)<BR>+ {<BR>+  // To get the IGMP packet we need to skip the ip 
options NDIS_BUFFER (if exists)<BR>+  while ( iph_options_size 
)<BR>+  {<BR>+   NdisGetNextBuffer( p_buf, &p_buf 
);<BR>+   if( !p_buf 
)<BR>+   {<BR>+    IPOIB_PRINT_EXIT( 
TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,<BR>+     ("Failed 
to get IGMPv2 header buffer.\n") );<BR>+    return 
NDIS_STATUS_FAILURE;<BR>+   }<BR>+   NdisQueryBufferSafe( 
p_buf, &p_igmp_v2_hdr, &buf_len, NormalPagePriority 
);<BR>+   if( !p_igmp_v2_hdr 
)<BR>+   {<BR>+    IPOIB_PRINT_EXIT( 
TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,<BR>+     ("Failed 
to query IGMPv2 header buffer.\n") );<BR>+    return 
NDIS_STATUS_FAILURE;<BR>+   }<BR>+   iph_options_size-=buf_len;<BR>+  }<BR>+        
<BR>+  NdisGetNextBuffer( p_buf, &p_buf );<BR>+  if( 
!p_buf )<BR>+  {<BR>+   IPOIB_PRINT_EXIT( 
TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,<BR>+    ("Failed to get 
IGMPv2 header buffer.\n") );<BR>+   return 
NDIS_STATUS_FAILURE;<BR>+  }<BR>+  NdisQueryBufferSafe( 
p_buf, &p_igmp_v2_hdr, &buf_len, NormalPagePriority 
);<BR>+  if( !p_igmp_v2_hdr 
)<BR>+  {<BR>+   IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, 
IPOIB_DBG_ERROR,<BR>+    ("Failed to query IGMPv2 header 
buffer.\n") );<BR>+   return 
NDIS_STATUS_FAILURE;<BR>+  }<BR>+ }<BR>+ else<BR>+ {<BR>+  /* 
assuming ip header and options are in the same packet 
*/<BR>+  p_igmp_v2_hdr = 
GetIpPayloadPtr(p_ip_hdr);<BR>+ }<BR>+ /* Get the IGMP header length. 
*/<BR>+ if( buf_len < sizeof(igmp_v2_hdr_t) 
)<BR>+ {<BR>+  IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, 
IPOIB_DBG_ERROR,<BR>+   ("Buffer not large enough for IGMPv2 
packet.\n") );<BR>+  return 
NDIS_STATUS_BUFFER_TOO_SHORT;<BR>+ }<BR>+<BR>+ // build fake mac from 
igmp packet group address<BR>+ fake_mcast_mac.addr[0] = 
1;<BR>+ fake_mcast_mac.addr[1] = ((unsigned 
char*)&p_igmp_v2_hdr->group_address)[0] & 
0x0f;<BR>+ fake_mcast_mac.addr[2] = 0x5E;<BR>+ fake_mcast_mac.addr[3] 
= ((unsigned 
char*)&p_igmp_v2_hdr->group_address)[1];<BR>+ fake_mcast_mac.addr[4] 
= ((unsigned 
char*)&p_igmp_v2_hdr->group_address)[2];<BR>+ fake_mcast_mac.addr[5] 
= ((unsigned 
char*)&p_igmp_v2_hdr->group_address)[3];<BR>+<BR>+ switch ( 
p_igmp_v2_hdr->type )<BR>+ {<BR>+ case 
IGMP_V2_MEMBERSHIP_REPORT:<BR>+  /* <BR>+   This mean 
that some body open listener on this group <BR>+   Change type of 
mcast endpt to SEND_RECV endpt. So mcast garbage collector 
<BR>+   will not delete this mcast 
endpt.<BR>+  */<BR>+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, 
IPOIB_DBG_MCAST,<BR>+   ("Catched IGMP_V2_MEMBERSHIP_REPORT 
message\n") );<BR>+  endpt_status = __endpt_mgr_ref( p_port, 
fake_mcast_mac, &p_endpt );<BR>+  if ( p_endpt 
)<BR>+  {<BR>+   cl_obj_lock( &p_port->obj 
);<BR>+   p_endpt->is_mcast_listener = 
TRUE;<BR>+   cl_obj_unlock( &p_port->obj 
);<BR>+            
ipoib_endpt_deref( p_endpt 
);<BR>+  }<BR>+  break;<BR>+<BR>+ case 
IGMP_V2_LEAVE_GROUP:<BR>+  /* <BR>+   This mean that 
somebody CLOSE listener on this group .<BR>+      
Change type of mcast endpt to SEND_ONLY endpt. So mcast 
<BR>+   garbage collector will delete this mcast endpt next 
time.<BR>+  */<BR>+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, 
IPOIB_DBG_MCAST,<BR>+        ("Catched 
IGMP_V2_LEAVE_GROUP message\n") );<BR>+  endpt_status = 
__endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );<BR>+  if ( 
p_endpt )<BR>+  {<BR>+   cl_obj_lock( 
&p_port->obj );<BR>+   p_endpt->is_mcast_listener = 
FALSE;<BR>+   p_endpt->is_in_use = 
FALSE;<BR>+   cl_obj_unlock( &p_port->obj 
);<BR>+   ipoib_endpt_deref( p_endpt 
);<BR>+  }<BR>+<BR>+  __port_do_mcast_garbage(p_port);<BR>+<BR>+  break;<BR>+<BR>+ default:<BR>+  IPOIB_PRINT( 
TRACE_LEVEL_INFORMATION, 
IPOIB_DBG_MCAST,<BR>+        ("Send Unknown 
IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) 
);<BR>+  break;<BR>+ }<BR>+<BR>+ IPOIB_EXIT( IPOIB_DBG_SEND 
);<BR>+ return NDIS_STATUS_SUCCESS;<BR>+}<BR>+<BR> static 
NDIS_STATUS<BR> __send_mgr_filter_udp(<BR>  IN    ipoib_port_t* 
const   p_port,<BR>@@ -3163,7 +3334,7 
@@<BR>  }<BR>  else<BR>  {<BR>-  p_udp_hdr 
= (udp_hdr_t*)(p_ip_hdr + 1);<BR>+  p_udp_hdr = 
(udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);<BR>  }<BR>  /* Get 
the UDP header and check the destination port numbers. */<BR>  if( 
buf_len < sizeof(udp_hdr_t) )<BR>@@ -3211,7 +3382,6 @@<BR>  return 
status;<BR> }<BR> <BR>-<BR> unsigned short ipchksum(unsigned 
short *ip, int len)<BR> {<BR>     unsigned long sum = 
0;<BR>@@ -3597,6 +3767,14 @@<BR>    return 
NDIS_STATUS_PENDING;<BR>   }<BR>  }<BR>+ else if ( 
status == NDIS_STATUS_SUCCESS && <BR>+     
ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) &&  
<BR>+     !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) 
)<BR>+ {<BR>+  CL_ASSERT( (*pp_endpt) 
);<BR>+  CL_ASSERT((*pp_endpt)->h_mcast != 
NULL);<BR>+  (*pp_endpt)->is_in_use = 
TRUE;<BR>+ }<BR> <BR>  IPOIB_EXIT( IPOIB_DBG_SEND 
);<BR>  return status;<BR>@@ -3775,6 +3953,44 
@@<BR>   }<BR> <BR>   cl_perf_start( 
SendMgrQueue );<BR>+<BR>+  if ( ETH_IS_MULTICAST( 
p_eth_hdr->dst.addr ) && <BR>+    p_eth_hdr->type 
== ETH_PROT_TYPE_IP &&<BR>+    !ETH_IS_BROADCAST( 
p_eth_hdr->dst.addr ) ) 
<BR>+  {<BR>+   ip_hdr_t   *p_ip_hdr;<BR>+   NDIS_BUFFER   *p_ip_hdr_buf;<BR>+   UINT    ip_hdr_buf_len;<BR>+<BR>+   // 
Extract the ip hdr <BR>+   NdisGetNextBuffer( p_buf, 
&p_ip_hdr_buf );<BR>+   if( !p_ip_hdr_buf 
)<BR>+   {<BR>+    IPOIB_PRINT_EXIT( 
TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,<BR>+     ("Failed 
to get IP header buffer.\n") );<BR>+    goto 
h_end;<BR>+   }<BR>+ <BR>+   NdisQueryBufferSafe( 
p_ip_hdr_buf, &p_ip_hdr, &ip_hdr_buf_len, NormalPagePriority 
);<BR>+   if( !p_ip_hdr 
)<BR>+   {<BR>+    IPOIB_PRINT_EXIT( 
TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,<BR>+     ("Failed 
to query IP header buffer.\n") );<BR>+    goto 
h_end;<BR>+   }<BR>+<BR>+   if( ip_hdr_buf_len 
< sizeof(ip_hdr_t) )<BR>+   {<BR>+    /* 
This buffer is done for.  Get the next buffer. 
*/<BR>+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, 
IPOIB_DBG_ERROR,<BR>+     ("Buffer too small for IP 
packet.\n") );<BR>+    goto 
h_end;<BR>+   }<BR>+  <BR>+   p_eth_hdr->dst.addr[1] 
= ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 
0x0f;<BR>+   p_eth_hdr->dst.addr[3] = ((unsigned 
char*)&p_ip_hdr->dst_ip)[1];<BR>+  }<BR>+h_end:<BR>   status 
= __send_mgr_queue( p_port, p_eth_hdr, &desc.p_endpt 
);<BR>   cl_perf_stop( &p_port->p_adapter->perf, 
SendMgrQueue );<BR>   if( status == NDIS_STATUS_PENDING )<BR>@@ 
-4600,6 +4816,7 @@<BR>   return 
IB_INSUFFICIENT_RESOURCES;<BR>  }<BR>  /* set reference to 
transport to be used while is not attached to the port 
*/<BR>+ p_endpt->is_mcast_listener = 
TRUE;<BR>  p_endpt->p_ifc = 
p_port->p_adapter->p_ifc;<BR>  status = ipoib_endpt_set_mcast( 
p_endpt, p_port->ib_mgr.h_pd,<BR>   p_port->port_num, 
p_mcast_rec );<BR>@@ -5251,6 +5468,10 
@@<BR>  KeWaitForSingleObject(<BR>   &p_port->sa_event, 
Executive, KernelMode, FALSE, NULL );<BR> <BR>+ /* garbage collector 
timer is not needed when link is down 
*/<BR>+ KeCancelTimer(&p_port->gc_timer);<BR>+ KeFlushQueuedDpcs();<BR>+<BR>  /*<BR>   
* Put the QP in the error state.  This removes the need to<BR>   
* synchronize with send/receive callbacks.<BR>@@ -5292,6 +5513,7 
@@<BR> {<BR>  ipoib_port_t *p_port;<BR>  ib_api_status_t status;<BR>+ LARGE_INTEGER  
 gc_due_time;<BR> <BR>  IPOIB_ENTER( IPOIB_DBG_INIT 
);<BR> <BR>@@ -5403,6 +5625,11 @@<BR>  /* Notify the adapter that 
we now have an active connection. */<BR>  ipoib_set_active( 
p_port->p_adapter );<BR> <BR>+ /* garbage collector timer is needed 
when link is active */<BR>+ gc_due_time.QuadPart = 
-(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) 

10);<BR>+ KeSetTimerEx(&p_port->gc_timer,gc_due_time,<BR>+       
(LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);<BR>+<BR>  KeSetEvent( 
&p_port->sa_event, EVENT_INCREMENT, FALSE 
);<BR>  ipoib_port_deref( p_port, ref_join_bcast 
);<BR>  IPOIB_EXIT( IPOIB_DBG_INIT );<BR>@@ -5529,15 +5756,15 
@@<BR>  mcast_req.member_rec.mlid = 
0;<BR>  ib_member_set_state( 
&mcast_req.member_rec.scope_state,state);<BR> <BR>- if( 
mac.addr[0] == 1 && mac.addr[1] == 0 && mac.addr[2] == 0x5E 
)<BR>+ if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E 
))<BR>  {<BR>   /*<BR>    * Update the 
address portion of the MGID with the 28 lower bits of the<BR>-   * IP 
address.  Since we're given a MAC address, we end up using 
only<BR>-   * the 24 lower bits of that network-byte-ordered value 
(assuming MSb<BR>-   * is zero).<BR>+   * IP address.  
Since we're given a MAC address, we are using <BR>+   * 24 lower bits 
of that network-byte-ordered value (assuming MSb<BR>+   * is zero) and 
4 lsb bits of the first byte of IP address.<BR>    
*/<BR>-  mcast_req.member_rec.mgid.raw[12] = 
0;<BR>+  mcast_req.member_rec.mgid.raw[12] = 
mac.addr[1];<BR>   mcast_req.member_rec.mgid.raw[13] = 
mac.addr[3];<BR>   mcast_req.member_rec.mgid.raw[14] = 
mac.addr[4];<BR>   mcast_req.member_rec.mgid.raw[15] = 
mac.addr[5];<BR>@@ -5695,6 +5922,8 
@@<BR>    &p_port->endpt_mgr.lid_endpts, 
p_endpt->dlid, &p_endpt->lid_item );<BR>   CL_ASSERT( 
p_qitem == &p_endpt->lid_item );<BR>  }<BR>+ /* set flag 
that endpoint is use */<BR>+ p_endpt->is_in_use = 
TRUE;<BR>  cl_obj_unlock( &p_port->obj 
);<BR>  <BR>  /* Try to send all pending sends. */<BR>@@ 
-5751,6 +5980,82 @@<BR>  IPOIB_EXIT( IPOIB_DBG_MCAST 
);<BR> }<BR> <BR>+static void __port_do_mcast_garbage(ipoib_port_t* 
const p_port)<BR>+{<BR>+    const mac_addr_t 
DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01};<BR>+ /* Do 
garbage collecting... 
*/<BR> <BR>+ cl_map_item_t *p_item;<BR>+ ipoib_endpt_t *p_endpt;<BR>+ cl_qlist_t  destroy_mc_list;<BR>+ uint8_t   cnt;<BR>+ const 
static GC_MAX_LEAVE_NUM = 80;<BR> <BR>+ cl_qlist_init( 
&destroy_mc_list );<BR> <BR>+ cl_obj_lock( &p_port->obj 
);<BR>+ cnt = 0;<BR>+ p_item = cl_qmap_head( 
&p_port->endpt_mgr.mac_endpts );<BR>+ while( (p_item != cl_qmap_end( 
&p_port->endpt_mgr.mac_endpts )) && (cnt < 
GC_MAX_LEAVE_NUM))<BR>+ {<BR>+  p_endpt = PARENT_STRUCT( p_item, 
ipoib_endpt_t, mac_item );<BR>+  p_item = cl_qmap_next( p_item 
);<BR>+<BR>+  /* Check if the current endpoint is not a multicast 
listener */<BR>+<BR>+  if( p_endpt->h_mcast && 
<BR>+   (!p_endpt->is_mcast_listener) 
&&<BR>+   ( cl_memcmp( &p_endpt->mac, 
&DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) &&<BR>+    
(!p_endpt->is_in_use) 
))<BR>+  {<BR>+   cl_qmap_remove_item( 
&p_port->endpt_mgr.mac_endpts,<BR>+    &p_endpt->mac_item 
);<BR>+   cl_fmap_remove_item( 
&p_port->endpt_mgr.gid_endpts,<BR>+    &p_endpt->gid_item 
);<BR>+<BR>+   if( p_endpt->dlid 
)<BR>+   {<BR>+    cl_qmap_remove_item( 
&p_port->endpt_mgr.lid_endpts,<BR>+     &p_endpt->lid_item 
);<BR>+    p_endpt->dlid = 
0;<BR>+   }<BR>+<BR>+   cl_qlist_insert_tail(<BR>+    &destroy_mc_list, 
&p_endpt->mac_item.pool_item.list_item 
);<BR>+   cnt++;<BR>+  }<BR>+  else<BR>+   p_endpt->is_in_use 
= FALSE;<BR>+ }<BR>+ cl_obj_unlock( &p_port->obj 
);<BR>+<BR>+ /* Destroy all multicast endpoints now that we have released 
the lock. */<BR>+ while( cl_qlist_count( &destroy_mc_list ) 
)<BR>+ {<BR>+  p_endpt = PARENT_STRUCT( cl_qlist_head( 
&destroy_mc_list ),<BR>+         
ipoib_endpt_t, mac_item.pool_item.list_item );<BR>+  IPOIB_PRINT( 
TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,<BR>+   ("mcast garbage 
collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", 
<BR>+     
p_endpt->mac.addr[0],<BR>+     
p_endpt->mac.addr[1],<BR>+     
p_endpt->mac.addr[2],<BR>+     
p_endpt->mac.addr[3],<BR>+     
p_endpt->mac.addr[4],<BR>+     p_endpt->mac.addr[5]) 
);<BR>+<BR>+  cl_obj_destroy( &PARENT_STRUCT( 
cl_qlist_remove_head( &destroy_mc_list 
),<BR>+   ipoib_endpt_t, mac_item.pool_item.list_item )->obj 
);<BR>+ }<BR>+}<BR>+<BR>+static void __port_mcast_garbage_dpc(KDPC 
*p_gc_dpc,void *context,void *s_arg1, void *s_arg2)<BR>+{<BR>+ ipoib_port_t 
*p_port = 
context;<BR>+<BR>+ UNREFERENCED_PARAMETER(p_gc_dpc);<BR>+ UNREFERENCED_PARAMETER(s_arg1);<BR>+ UNREFERENCED_PARAMETER(s_arg2);<BR>+<BR>+ __port_do_mcast_garbage(p_port);<BR>+}<BR>+<BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h (revision 2846)<BR>@@ 
-62,7 +62,8 
@@<BR>  ib_av_handle_t   h_av;<BR>  boolean_t    expired;<BR>  ib_al_ifc_t    *p_ifc;<BR>-<BR>+ boolean_t    
   is_in_use;<BR>+ boolean_t    is_mcast_listener;<BR> } ipoib_endpt_t;<BR> /*<BR> * 
FIELDS<BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h (revision 2846)<BR>@@ 
-75,7 +75,7 
@@<BR>  uint32_t payload_mtu;<BR>  uint32_t xfer_block_size;<BR>  mac_addr_t conf_mac;<BR>-<BR>+ uint32_t mc_leave_rescan;<BR> } ipoib_params_t;<BR> /*<BR> * 
FIELDS<BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h (revision 2846)<BR>@@ 
-509,6 +509,8 
@@<BR> <BR>  atomic32_t    hdr_idx;<BR>  uint16_t    pkey_index;<BR>+ KDPC     gc_dpc;<BR>+ KTIMER     gc_timer;<BR>  ipoib_hdr_t    hdr[1]; /* 
Must be last! */<BR> <BR> } ipoib_port_t;<BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c (revision 2846)<BR>@@ 
-153,7 +153,8 
@@<BR>  {NDIS_STRING_CONST("SaTimeout"),        
1, 
IPOIB_OFFSET(sa_timeout),            
IPOIB_SIZE(sa_timeout),         
1000,       250,    
UINT_MAX},<BR>  {NDIS_STRING_CONST("SaRetries"),        
1, 
IPOIB_OFFSET(sa_retry_cnt),          
IPOIB_SIZE(sa_retry_cnt),       
10,         
1,      
UINT_MAX},<BR>  {NDIS_STRING_CONST("RecvRatio"),        
1, IPOIB_OFFSET(recv_pool_ratio),       
IPOIB_SIZE(recv_pool_ratio),    
1,          
1,      
10},<BR>- {NDIS_STRING_CONST("PayloadMtu"),       
1, 
IPOIB_OFFSET(payload_mtu),           
IPOIB_SIZE(payload_mtu),        
2044,         60,   
4092}<BR>+ {NDIS_STRING_CONST("PayloadMtu"),       
1, 
IPOIB_OFFSET(payload_mtu),           
IPOIB_SIZE(payload_mtu),        
2044,       60,   
4092},<BR>+ {NDIS_STRING_CONST("MCLeaveRescan"),    1, 
IPOIB_OFFSET(mc_leave_rescan),       
IPOIB_SIZE(mc_leave_rescan),    
260,        1,    
3600}<BR> };  <BR> <BR> #define IPOIB_NUM_REG_PARAMS (sizeof 
(HCARegTable) / sizeof(IPOIB_REG_ENTRY))<BR>Index: 
Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx (revision 2845)<BR>+++ 
Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx (revision 2846)<BR>@@ 
-126,6 +126,12 @@<BR> HKR, 
Ndi\Params\PayloadMtu,  Min,  0, "60"<BR> HKR, 
Ndi\Params\PayloadMtu,  Max,  0, "4092"<BR> <BR>+HKR, 
Ndi\Params\MCLeaveRescan,  ParamDesc, 0, "MC leave rescan 
(sec)"<BR>+HKR, Ndi\Params\MCLeaveRescan,  Type,  0, 
"dword"<BR>+HKR, Ndi\Params\MCLeaveRescan,  Default, 0, 
"260"<BR>+HKR, Ndi\Params\MCLeaveRescan,  Optional, 0, 
"0"<BR>+HKR, Ndi\Params\MCLeaveRescan,  Min,  0, 
"1"<BR>+HKR, Ndi\Params\MCLeaveRescan,  Max,  0, 
"3600"<BR> [IpoibService]<BR> DisplayName     = 
%IpoibServiceDispName%<BR> ServiceType     = 1 
;%SERVICE_KERNEL_DRIVER%<BR>Index: 
Q:/projinf4/trunk/inc/kernel/ip_packet.h<BR>===================================================================<BR>--- 
Q:/projinf4/trunk/inc/kernel/ip_packet.h (revision 2845)<BR>+++ 
Q:/projinf4/trunk/inc/kernel/ip_packet.h (revision 2846)<BR>@@ -196,6 
+196,7 @@<BR> #define IP_PROT_IP   4<BR> #define 
IP_PROT_TCP   6<BR> #define 
IP_PROT_UDP   17<BR>+#define 
IP_PROT_IGMP  2<BR> <BR> <BR> #include 
<complib/cl_packon.h><BR>@@ -355,6 +356,55 
@@<BR> *********/<BR> #include 
<complib/cl_packoff.h><BR> <BR>+#define 
IGMP_V2_MEMBERSHIP_QUERY 0x11<BR>+#define 
IGMP_V2_MEMBERSHIP_REPORT 0x16<BR>+#define 
IGMP_V1_MEMBERSHIP_REPORT 0x12 // for backward compatibility with 
IGMPv1<BR>+#define IGMP_V2_LEAVE_GROUP   0x17<BR>+#include 
<complib/cl_packon.h><BR>+/****s* IB Network Drivers/igmp__v2_hdr_t<BR>+* 
NAME<BR>+* igmp_v2_hdr_t<BR>+*<BR>+* DESCRIPTION<BR>+* Defines the 
IGMPv2 header for IP packets.<BR>+*<BR>+* SYNOPSIS<BR>+*/<BR>+typedef struct 
_igmp_v2_hdr<BR>+{<BR>+ uint8_t  type;<BR>+ uint8_t  max_resp_time;<BR>+ net16_t  chksum;<BR>+ net32_t  group_address;<BR>+} PACK_SUFFIX 
igmp_v2_hdr_t;<BR>+/*<BR>+* FIELDS<BR>+* type<BR>+*  type of 
IGMPv2 message: 
query/report/leave<BR>+*<BR>+* max_resp_time<BR>+*  The Max 
Response Time field is meaningful only in Membership 
Query<BR>+*  messages, and specifies the maximum allowed time before 
sending a<BR>+*  responding report in units of 1/10 second.  In 
all other messages, it<BR>+*  is set to zero by the sender and ignored 
by receivers.<BR>+*<BR>+* checksum<BR>+*  The checksum is the 
16-bit one's complement of the one's complement<BR>+*    sum of 
the whole IGMP message (the entire IP payload).  
<BR>+*<BR>+* group_address<BR>+*  In a Membership Query message, 
the group address field is set to zero<BR>+*       
when sending a General Query, and set to the group address 
being<BR>+*       queried when sending a 
Group-Specific Query.<BR>+*<BR>+*       In a 
Membership Report or Leave Group message, the group 
address<BR>+*       field holds the IP multicast 
group address of the group being<BR>+*       
reported or left.<BR>+*<BR>+* SEE ALSO<BR>+* IB Network Drivers, eth_hdr_t, 
arp_pkt_t, ip_hdr_t, tcp_hdr_t<BR>+*********/<BR>+#include 
<complib/cl_packoff.h><BR> <BR> #define 
DHCP_PORT_SERVER  CL_HTON16(67)<BR> #define 
DHCP_PORT_CLIENT  CL_HTON16(68)<BR></DIV></FONT></BODY></HTML>