<!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><SPAN class=757474807-27072008><FONT face=Arial color=#0000ff 
size=2>applied in 1450.</FONT></SPAN></DIV>
<DIV><SPAN class=757474807-27072008><FONT face=Arial color=#0000ff 
size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=757474807-27072008><FONT face=Arial color=#0000ff 
size=2>Thanks</FONT></SPAN></DIV>
<DIV><SPAN class=757474807-27072008><FONT face=Arial color=#0000ff 
size=2>Tzachi</FONT></SPAN></DIV><BR>
<BLOCKQUOTE dir=ltr 
style="PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #0000ff 2px solid; MARGIN-RIGHT: 0px">
  <DIV class=OutlookMessageHeader lang=en-us dir=ltr align=left>
  <HR tabIndex=-1>
  <FONT face=Tahoma size=2><B>From:</B> ofw-bounces@lists.openfabrics.org 
  [mailto:ofw-bounces@lists.openfabrics.org] <B>On Behalf Of </B>Tzachi 
  Dar<BR><B>Sent:</B> Thursday, July 24, 2008 4:21 PM<BR><B>To:</B> 
  ofw@lists.openfabrics.org<BR><B>Subject:</B> [ofw] patch: mcast garbage 
  collector and IGMP V2 support.<BR></FONT><BR></DIV>
  <DIV></DIV>
  <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></BLOCKQUOTE></FONT></BODY></HTML>