[ofw] patch: mcast garbage collector and IGMP V2 support.

Tzachi Dar tzachid at mellanox.co.il
Thu Jul 24 06:20:53 PDT 2008


In the past there have been some patches that were sent by 
slavas at voltaire.com regarding this issues.
 
After some work with him, here is the final patch that we have came
through.
 
Any comments are welcomed.
 
Thanks
Tzachi
 
 
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.c (revision 2846)
@@ -762,8 +762,13 @@
 
    if( j != p_adapter->mcast_array_size )
     continue;
-
-   ipoib_port_join_mcast( p_port, p_mac_array[i]
,IB_MC_REC_STATE_FULL_MEMBER);
+   if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 &&
p_mac_array[i].addr[2] == 0x5e &&
+       p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 &&
p_mac_array[i].addr[5] == 1 ) ||
+      !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 &&
p_mac_array[i].addr[2] == 0x5e )
+    )
+   {
+    ipoib_port_join_mcast( p_port, p_mac_array[i],
IB_MC_REC_STATE_FULL_MEMBER );
+   }
   }
  }
 
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.c (revision 2846)
@@ -67,7 +67,8 @@
 ipoib_port_t *gp_ipoib_port;
 #endif
 
-
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void
*s_arg1, void *s_arg2);
+static void __port_do_mcast_garbage(ipoib_port_t* const p_port );
 
/***********************************************************************
*******
 *
 * Declarations
@@ -291,6 +292,14 @@
  IN OUT   ipoib_send_desc_t* const p_desc );
 
 static NDIS_STATUS
+__send_mgr_filter_igmp_v2(
+ IN    ipoib_port_t* const   p_port,
+    IN  const ip_hdr_t* const    p_ip_hdr,
+ IN    size_t      iph_options_size,
+ IN    NDIS_BUFFER*    p_buf,
+ IN    size_t      buf_len );
+
+static NDIS_STATUS
 __send_mgr_filter_udp(
  IN    ipoib_port_t* const   p_port,
  IN  const ip_hdr_t* const    p_ip_hdr,
@@ -490,6 +499,13 @@
 #endif
 }
 
+/* function returns pointer to payload that is going after IP header.
+*  asssuming that payload and IP header are in the same buffer
+*/
+static void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr)
+{
+ return (void*)((uint8_t*)p_ip_hdr + 4*(p_ip_hdr->ver_hl & 0xf));
+}
 
 
/***********************************************************************
*******
 *
@@ -653,6 +669,9 @@
    p_adapter->p_ifc->get_err_str( status )) );
   return status;
  }
+  /* Initialize multicast garbage collector timer and DPC object */
+
KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage
_dpc,p_port);
+  KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);
 
  /* We only ever destroy from the PnP callback thread. */
  cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,
@@ -748,6 +767,8 @@
 
  p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );
 
+ KeCancelTimer(&p_port->gc_timer);
+ KeFlushQueuedDpcs();
  __endpt_mgr_destroy( p_port );
  __recv_mgr_destroy( p_port );
  __send_mgr_destroy( p_port );
@@ -2133,6 +2154,9 @@
  p_eth->hdr.src = p_src->mac;
  p_eth->hdr.dst = p_dst->mac;
 
+ if (p_dst->h_mcast) {
+  p_dst->is_in_use = TRUE;
+ }
  IPOIB_EXIT( IPOIB_DBG_RECV );
  return IB_SUCCESS;
 }
@@ -3106,6 +3130,26 @@
  if( p_ip_hdr->offset ||
   p_ip_hdr->prot != IP_PROT_UDP )
  {
+  /* Check if this packet is IGMP */
+  if ( p_ip_hdr->prot == IP_PROT_IGMP ) 
+  {
+   /*
+       In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs:
+    1. iph
+    2. ip options
+    So to get the IGMP packet we need to skip the ip options
NDIS_BUFFER
+   */
+   size_t iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;
+   size_t iph_options_size = iph_size_in_bytes - buf_len;
+   buf_len -= sizeof(ip_hdr_t);//without ipheader
+
+   /*
+       Could be a case that arrived igmp packet not from type IGMPv2 ,
+    but IGMPv1 or IGMPv3.
+    We anyway pass it to __send_mgr_filter_igmp_v2().
+   */
+   __send_mgr_filter_igmp_v2(p_port, p_ip_hdr, iph_options_size, p_buf,
buf_len);
+  }
   /* Not a UDP packet. */
   cl_perf_start( SendTcp );
   status = __send_gen( p_port, p_desc );
@@ -3125,7 +3169,134 @@
  return status;
 }
 
+static NDIS_STATUS
+__send_mgr_filter_igmp_v2(
+ IN    ipoib_port_t* const   p_port,
+ IN  const ip_hdr_t* const    p_ip_hdr,
+ IN    size_t      iph_options_size,
+ IN    NDIS_BUFFER*    p_buf,
+ IN    size_t      buf_len )
+{
+ igmp_v2_hdr_t  *p_igmp_v2_hdr = NULL;
+ NDIS_STATUS   endpt_status;
+ ipoib_endpt_t*   p_endpt = NULL;
+ mac_addr_t   fake_mcast_mac;
 
+ IPOIB_ENTER( IPOIB_DBG_SEND );
+
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,
+    ("buf_len = %d,iph_options_size =
%d\n",(int)buf_len,(int)iph_options_size ) );
+
+ if( !buf_len )
+ {
+  // To get the IGMP packet we need to skip the ip options NDIS_BUFFER
(if exists)
+  while ( iph_options_size )
+  {
+   NdisGetNextBuffer( p_buf, &p_buf );
+   if( !p_buf )
+   {
+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+     ("Failed to get IGMPv2 header buffer.\n") );
+    return NDIS_STATUS_FAILURE;
+   }
+   NdisQueryBufferSafe( p_buf, &p_igmp_v2_hdr, &buf_len,
NormalPagePriority );
+   if( !p_igmp_v2_hdr )
+   {
+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+     ("Failed to query IGMPv2 header buffer.\n") );
+    return NDIS_STATUS_FAILURE;
+   }
+   iph_options_size-=buf_len;
+  }
+        
+  NdisGetNextBuffer( p_buf, &p_buf );
+  if( !p_buf )
+  {
+   IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+    ("Failed to get IGMPv2 header buffer.\n") );
+   return NDIS_STATUS_FAILURE;
+  }
+  NdisQueryBufferSafe( p_buf, &p_igmp_v2_hdr, &buf_len,
NormalPagePriority );
+  if( !p_igmp_v2_hdr )
+  {
+   IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+    ("Failed to query IGMPv2 header buffer.\n") );
+   return NDIS_STATUS_FAILURE;
+  }
+ }
+ else
+ {
+  /* assuming ip header and options are in the same packet */
+  p_igmp_v2_hdr = GetIpPayloadPtr(p_ip_hdr);
+ }
+ /* Get the IGMP header length. */
+ if( buf_len < sizeof(igmp_v2_hdr_t) )
+ {
+  IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+   ("Buffer not large enough for IGMPv2 packet.\n") );
+  return NDIS_STATUS_BUFFER_TOO_SHORT;
+ }
+
+ // build fake mac from igmp packet group address
+ fake_mcast_mac.addr[0] = 1;
+ fake_mcast_mac.addr[1] = ((unsigned
char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f;
+ fake_mcast_mac.addr[2] = 0x5E;
+ fake_mcast_mac.addr[3] = ((unsigned
char*)&p_igmp_v2_hdr->group_address)[1];
+ fake_mcast_mac.addr[4] = ((unsigned
char*)&p_igmp_v2_hdr->group_address)[2];
+ fake_mcast_mac.addr[5] = ((unsigned
char*)&p_igmp_v2_hdr->group_address)[3];
+
+ switch ( p_igmp_v2_hdr->type )
+ {
+ case IGMP_V2_MEMBERSHIP_REPORT:
+  /* 
+   This mean that some body open listener on this group 
+   Change type of mcast endpt to SEND_RECV endpt. So mcast garbage
collector 
+   will not delete this mcast endpt.
+  */
+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,
+   ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") );
+  endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );
+  if ( p_endpt )
+  {
+   cl_obj_lock( &p_port->obj );
+   p_endpt->is_mcast_listener = TRUE;
+   cl_obj_unlock( &p_port->obj );
+            ipoib_endpt_deref( p_endpt );
+  }
+  break;
+
+ case IGMP_V2_LEAVE_GROUP:
+  /* 
+   This mean that somebody CLOSE listener on this group .
+      Change type of mcast endpt to SEND_ONLY endpt. So mcast 
+   garbage collector will delete this mcast endpt next time.
+  */
+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,
+        ("Catched IGMP_V2_LEAVE_GROUP message\n") );
+  endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );
+  if ( p_endpt )
+  {
+   cl_obj_lock( &p_port->obj );
+   p_endpt->is_mcast_listener = FALSE;
+   p_endpt->is_in_use = FALSE;
+   cl_obj_unlock( &p_port->obj );
+   ipoib_endpt_deref( p_endpt );
+  }
+
+  __port_do_mcast_garbage(p_port);
+
+  break;
+
+ default:
+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,
+        ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) );
+  break;
+ }
+
+ IPOIB_EXIT( IPOIB_DBG_SEND );
+ return NDIS_STATUS_SUCCESS;
+}
+
 static NDIS_STATUS
 __send_mgr_filter_udp(
  IN    ipoib_port_t* const   p_port,
@@ -3163,7 +3334,7 @@
  }
  else
  {
-  p_udp_hdr = (udp_hdr_t*)(p_ip_hdr + 1);
+  p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);
  }
  /* Get the UDP header and check the destination port numbers. */
  if( buf_len < sizeof(udp_hdr_t) )
@@ -3211,7 +3382,6 @@
  return status;
 }
 
-
 unsigned short ipchksum(unsigned short *ip, int len)
 {
     unsigned long sum = 0;
@@ -3597,6 +3767,14 @@
    return NDIS_STATUS_PENDING;
   }
  }
+ else if ( status == NDIS_STATUS_SUCCESS && 
+     ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) &&  
+     !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) )
+ {
+  CL_ASSERT( (*pp_endpt) );
+  CL_ASSERT((*pp_endpt)->h_mcast != NULL);
+  (*pp_endpt)->is_in_use = TRUE;
+ }
 
  IPOIB_EXIT( IPOIB_DBG_SEND );
  return status;
@@ -3775,6 +3953,44 @@
   }
 
   cl_perf_start( SendMgrQueue );
+
+  if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && 
+    p_eth_hdr->type == ETH_PROT_TYPE_IP &&
+    !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) 
+  {
+   ip_hdr_t   *p_ip_hdr;
+   NDIS_BUFFER   *p_ip_hdr_buf;
+   UINT    ip_hdr_buf_len;
+
+   // Extract the ip hdr 
+   NdisGetNextBuffer( p_buf, &p_ip_hdr_buf );
+   if( !p_ip_hdr_buf )
+   {
+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+     ("Failed to get IP header buffer.\n") );
+    goto h_end;
+   }
+ 
+   NdisQueryBufferSafe( p_ip_hdr_buf, &p_ip_hdr, &ip_hdr_buf_len,
NormalPagePriority );
+   if( !p_ip_hdr )
+   {
+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+     ("Failed to query IP header buffer.\n") );
+    goto h_end;
+   }
+
+   if( ip_hdr_buf_len < sizeof(ip_hdr_t) )
+   {
+    /* This buffer is done for.  Get the next buffer. */
+    IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+     ("Buffer too small for IP packet.\n") );
+    goto h_end;
+   }
+  
+   p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] &
0x0f;
+   p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1];
+  }
+h_end:
   status = __send_mgr_queue( p_port, p_eth_hdr, &desc.p_endpt );
   cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue );
   if( status == NDIS_STATUS_PENDING )
@@ -4600,6 +4816,7 @@
   return IB_INSUFFICIENT_RESOURCES;
  }
  /* set reference to transport to be used while is not attached to the
port */
+ p_endpt->is_mcast_listener = TRUE;
  p_endpt->p_ifc = p_port->p_adapter->p_ifc;
  status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd,
   p_port->port_num, p_mcast_rec );
@@ -5251,6 +5468,10 @@
  KeWaitForSingleObject(
   &p_port->sa_event, Executive, KernelMode, FALSE, NULL );
 
+ /* garbage collector timer is not needed when link is down */
+ KeCancelTimer(&p_port->gc_timer);
+ KeFlushQueuedDpcs();
+
  /*
   * Put the QP in the error state.  This removes the need to
   * synchronize with send/receive callbacks.
@@ -5292,6 +5513,7 @@
 {
  ipoib_port_t *p_port;
  ib_api_status_t status;
+ LARGE_INTEGER   gc_due_time;
 
  IPOIB_ENTER( IPOIB_DBG_INIT );
 
@@ -5403,6 +5625,11 @@
  /* Notify the adapter that we now have an active connection. */
  ipoib_set_active( p_port->p_adapter );
 
+ /* garbage collector timer is needed when link is active */
+ gc_due_time.QuadPart =
-(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan *
2000000) * 10);
+ KeSetTimerEx(&p_port->gc_timer,gc_due_time,
+
(LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);
+
  KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );
  ipoib_port_deref( p_port, ref_join_bcast );
  IPOIB_EXIT( IPOIB_DBG_INIT );
@@ -5529,15 +5756,15 @@
  mcast_req.member_rec.mlid = 0;
  ib_member_set_state( &mcast_req.member_rec.scope_state,state);
 
- if( mac.addr[0] == 1 && mac.addr[1] == 0 && mac.addr[2] == 0x5E )
+ if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E ))
  {
   /*
    * Update the address portion of the MGID with the 28 lower bits of
the
-   * IP address.  Since we're given a MAC address, we end up using only
-   * the 24 lower bits of that network-byte-ordered value (assuming MSb
-   * is zero).
+   * IP address.  Since we're given a MAC address, we are using 
+   * 24 lower bits of that network-byte-ordered value (assuming MSb
+   * is zero) and 4 lsb bits of the first byte of IP address.
    */
-  mcast_req.member_rec.mgid.raw[12] = 0;
+  mcast_req.member_rec.mgid.raw[12] = mac.addr[1];
   mcast_req.member_rec.mgid.raw[13] = mac.addr[3];
   mcast_req.member_rec.mgid.raw[14] = mac.addr[4];
   mcast_req.member_rec.mgid.raw[15] = mac.addr[5];
@@ -5695,6 +5922,8 @@
    &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item );
   CL_ASSERT( p_qitem == &p_endpt->lid_item );
  }
+ /* set flag that endpoint is use */
+ p_endpt->is_in_use = TRUE;
  cl_obj_unlock( &p_port->obj );
  
  /* Try to send all pending sends. */
@@ -5751,6 +5980,82 @@
  IPOIB_EXIT( IPOIB_DBG_MCAST );
 }
 
+static void __port_do_mcast_garbage(ipoib_port_t* const p_port)
+{
+    const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5e, 0x00,
0x00, 0x01};
+ /* Do garbage collecting... */
 
+ cl_map_item_t *p_item;
+ ipoib_endpt_t *p_endpt;
+ cl_qlist_t  destroy_mc_list;
+ uint8_t   cnt;
+ const static GC_MAX_LEAVE_NUM = 80;
 
+ cl_qlist_init( &destroy_mc_list );
 
+ cl_obj_lock( &p_port->obj );
+ cnt = 0;
+ p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );
+ while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) &&
(cnt < GC_MAX_LEAVE_NUM))
+ {
+  p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );
+  p_item = cl_qmap_next( p_item );
+
+  /* Check if the current endpoint is not a multicast listener */
+
+  if( p_endpt->h_mcast && 
+   (!p_endpt->is_mcast_listener) &&
+   ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t)
) &&
+    (!p_endpt->is_in_use) ))
+  {
+   cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,
+    &p_endpt->mac_item );
+   cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,
+    &p_endpt->gid_item );
+
+   if( p_endpt->dlid )
+   {
+    cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,
+     &p_endpt->lid_item );
+    p_endpt->dlid = 0;
+   }
+
+   cl_qlist_insert_tail(
+    &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item );
+   cnt++;
+  }
+  else
+   p_endpt->is_in_use = FALSE;
+ }
+ cl_obj_unlock( &p_port->obj );
+
+ /* Destroy all multicast endpoints now that we have released the lock.
*/
+ while( cl_qlist_count( &destroy_mc_list ) )
+ {
+  p_endpt = PARENT_STRUCT( cl_qlist_head( &destroy_mc_list ),
+         ipoib_endpt_t, mac_item.pool_item.list_item );
+  IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,
+   ("mcast garbage collector: destroying endpoint
%02x:%02x:%02x:%02x:%02x:%02x \n", 
+     p_endpt->mac.addr[0],
+     p_endpt->mac.addr[1],
+     p_endpt->mac.addr[2],
+     p_endpt->mac.addr[3],
+     p_endpt->mac.addr[4],
+     p_endpt->mac.addr[5]) );
+
+  cl_obj_destroy( &PARENT_STRUCT( cl_qlist_remove_head(
&destroy_mc_list ),
+   ipoib_endpt_t, mac_item.pool_item.list_item )->obj );
+ }
+}
+
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void
*s_arg1, void *s_arg2)
+{
+ ipoib_port_t *p_port = context;
+
+ UNREFERENCED_PARAMETER(p_gc_dpc);
+ UNREFERENCED_PARAMETER(s_arg1);
+ UNREFERENCED_PARAMETER(s_arg2);
+
+ __port_do_mcast_garbage(p_port);
+}
+
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_endpoint.h (revision 2846)
@@ -62,7 +62,8 @@
  ib_av_handle_t   h_av;
  boolean_t    expired;
  ib_al_ifc_t    *p_ifc;
-
+ boolean_t       is_in_use;
+ boolean_t    is_mcast_listener;
 } ipoib_endpt_t;
 /*
 * FIELDS
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_adapter.h (revision 2846)
@@ -75,7 +75,7 @@
  uint32_t payload_mtu;
  uint32_t xfer_block_size;
  mac_addr_t conf_mac;
-
+ uint32_t mc_leave_rescan;
 } ipoib_params_t;
 /*
 * FIELDS
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_port.h (revision 2846)
@@ -509,6 +509,8 @@
 
  atomic32_t    hdr_idx;
  uint16_t    pkey_index;
+ KDPC     gc_dpc;
+ KTIMER     gc_timer;
  ipoib_hdr_t    hdr[1]; /* Must be last! */
 
 } ipoib_port_t;
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/ipoib_driver.c (revision 2846)
@@ -153,7 +153,8 @@
  {NDIS_STRING_CONST("SaTimeout"),        1, IPOIB_OFFSET(sa_timeout),
IPOIB_SIZE(sa_timeout),         1000,       250,    UINT_MAX},
  {NDIS_STRING_CONST("SaRetries"),        1, IPOIB_OFFSET(sa_retry_cnt),
IPOIB_SIZE(sa_retry_cnt),       10,         1,      UINT_MAX},
  {NDIS_STRING_CONST("RecvRatio"),        1,
IPOIB_OFFSET(recv_pool_ratio),       IPOIB_SIZE(recv_pool_ratio),    1,
1,      10},
- {NDIS_STRING_CONST("PayloadMtu"),       1, IPOIB_OFFSET(payload_mtu),
IPOIB_SIZE(payload_mtu),        2044,         60,   4092}
+ {NDIS_STRING_CONST("PayloadMtu"),       1, IPOIB_OFFSET(payload_mtu),
IPOIB_SIZE(payload_mtu),        2044,       60,   4092},
+ {NDIS_STRING_CONST("MCLeaveRescan"),    1,
IPOIB_OFFSET(mc_leave_rescan),       IPOIB_SIZE(mc_leave_rescan),
260,        1,    3600}
 };  
 
 #define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) /
sizeof(IPOIB_REG_ENTRY))
Index: Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx
===================================================================
--- Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx (revision 2845)
+++ Q:/projinf4/trunk/ulp/ipoib/kernel/netipoib.inx (revision 2846)
@@ -126,6 +126,12 @@
 HKR, Ndi\Params\PayloadMtu,  Min,  0, "60"
 HKR, Ndi\Params\PayloadMtu,  Max,  0, "4092"
 
+HKR, Ndi\Params\MCLeaveRescan,  ParamDesc, 0, "MC leave rescan (sec)"
+HKR, Ndi\Params\MCLeaveRescan,  Type,  0, "dword"
+HKR, Ndi\Params\MCLeaveRescan,  Default, 0, "260"
+HKR, Ndi\Params\MCLeaveRescan,  Optional, 0, "0"
+HKR, Ndi\Params\MCLeaveRescan,  Min,  0, "1"
+HKR, Ndi\Params\MCLeaveRescan,  Max,  0, "3600"
 [IpoibService]
 DisplayName     = %IpoibServiceDispName%
 ServiceType     = 1 ;%SERVICE_KERNEL_DRIVER%
Index: Q:/projinf4/trunk/inc/kernel/ip_packet.h
===================================================================
--- Q:/projinf4/trunk/inc/kernel/ip_packet.h (revision 2845)
+++ Q:/projinf4/trunk/inc/kernel/ip_packet.h (revision 2846)
@@ -196,6 +196,7 @@
 #define IP_PROT_IP   4
 #define IP_PROT_TCP   6
 #define IP_PROT_UDP   17
+#define IP_PROT_IGMP  2
 
 
 #include <complib/cl_packon.h>
@@ -355,6 +356,55 @@
 *********/
 #include <complib/cl_packoff.h>
 
+#define IGMP_V2_MEMBERSHIP_QUERY 0x11
+#define IGMP_V2_MEMBERSHIP_REPORT 0x16
+#define IGMP_V1_MEMBERSHIP_REPORT 0x12 // for backward compatibility
with IGMPv1
+#define IGMP_V2_LEAVE_GROUP   0x17
+#include <complib/cl_packon.h>
+/****s* IB Network Drivers/igmp__v2_hdr_t
+* NAME
+* igmp_v2_hdr_t
+*
+* DESCRIPTION
+* Defines the IGMPv2 header for IP packets.
+*
+* SYNOPSIS
+*/
+typedef struct _igmp_v2_hdr
+{
+ uint8_t  type;
+ uint8_t  max_resp_time;
+ net16_t  chksum;
+ net32_t  group_address;
+} PACK_SUFFIX igmp_v2_hdr_t;
+/*
+* FIELDS
+* type
+*  type of IGMPv2 message: query/report/leave
+*
+* max_resp_time
+*  The Max Response Time field is meaningful only in Membership Query
+*  messages, and specifies the maximum allowed time before sending a
+*  responding report in units of 1/10 second.  In all other messages,
it
+*  is set to zero by the sender and ignored by receivers.
+*
+* checksum
+*  The checksum is the 16-bit one's complement of the one's complement
+*    sum of the whole IGMP message (the entire IP payload).  
+*
+* group_address
+*  In a Membership Query message, the group address field is set to
zero
+*       when sending a General Query, and set to the group address
being
+*       queried when sending a Group-Specific Query.
+*
+*       In a Membership Report or Leave Group message, the group
address
+*       field holds the IP multicast group address of the group being
+*       reported or left.
+*
+* SEE ALSO
+* IB Network Drivers, eth_hdr_t, arp_pkt_t, ip_hdr_t, tcp_hdr_t
+*********/
+#include <complib/cl_packoff.h>
 
 #define DHCP_PORT_SERVER  CL_HTON16(67)
 #define DHCP_PORT_CLIENT  CL_HTON16(68)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080724/b374181f/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: igmp_v2_support.diff
Type: application/octet-stream
Size: 21367 bytes
Desc: igmp_v2_support.diff
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080724/b374181f/attachment.obj>


More information about the ofw mailing list