<!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>