[ofw] patch: mcast garbage collector and IGMP V2 support.
Tzachi Dar
tzachid at mellanox.co.il
Sun Jul 27 00:49:19 PDT 2008
applied in 1450.
Thanks
Tzachi
________________________________
From: ofw-bounces at lists.openfabrics.org
[mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Tzachi Dar
Sent: Thursday, July 24, 2008 4:21 PM
To: ofw at lists.openfabrics.org
Subject: [ofw] patch: mcast garbage collector and IGMP V2
support.
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/20080727/d76959c2/attachment.html>
More information about the ofw
mailing list