[ofw] [Patch][IPoIB_NDIS6_CM] IPv6 support - initial commit
Alex Naslednikov
xalex at mellanox.co.il
Sun Nov 7 07:27:19 PST 2010
IPv6 initial commit, DHCP flow is not supported yet
Signed-off by: Alexander Naslednikov (xalex at mellanox.co.il)
Index: inc/kernel/ip_packet.h
===================================================================
--- inc/kernel/ip_packet.h (revision 2982)
+++ inc/kernel/ip_packet.h (working copy)
@@ -200,6 +200,7 @@
#define IP_PROT_UDP 17
#define IP_PROT_IGMP 2
#define IP_PROT_ICMP 1
+#define IP_PROT_ICMPV6 58
#include <complib/cl_packon.h>
@@ -263,7 +264,73 @@
*********/
#include <complib/cl_packoff.h>
+#include <complib/cl_packon.h>
+/****s* IB Network Drivers/ipv6_hdr_t
+* NAME
+* ipv6_hdr_t
+*
+* DESCRIPTION
+* Defines the IPV6 header for IPV6 packets.
+*
+* SYNOPSIS
+*/
+typedef struct _ipv6_hdr
+{
+ uint32_t ver_tc_fl;
+ uint16_t payload_length;
+ uint8_t next_header;
+ uint8_t hop_limit;
+ uint8_t src_addr[16];
+ uint8_t dest_addr[16];
+} PACK_SUFFIX ipv6_hdr_t;
+/*
+* FIELDS
+* ver_tc_fl
+* This field contains of 3 subfields:
+* 1.Version (4 bits)
+* The constant 6 (bit sequence 0110).
+* 2.Traffic Class (8 bits)
+* The bits of this field hold two values. The 6 most-significant bits are used
+* for DSCP, which is used to classify packets. The remaining two bits
+* are used for ECN; priority values subdivide into ranges: traffic where
+* the source provides congestion control and non-congestion control traffic.
+* 3.Flow Label (20 bits)
+* Originally created for giving real-time applications special service.
+* Flow Label specifications and minimum requirements are described,
+* and first uses of this field are emerging.
+*
+*
+* payload_length;
+* The size of the payload in octets, including any extension headers.
+* The length is set to zero when a Hop-by-Hop extension header carries
+* a Jumbo Payload option.
+*
+* next_header
+* Specifies the type of the next header. This field usually specifies the
+* transport layer protocol used by a packet's payload. When extension headers
+* are present in the packet this field indicates which extension header follows.
+* The values are shared with those used for the IPv4 protocol field,
+* as both fields have the same function
+*
+* hop_limit
+* Replaces the time to live field of IPv4. This value is decremented by
+* one at each intermediate node the packet visits. When the counter reaches
+* 0 the packet is discarded
+*
+* src_addr
+* The IPv6 address of the sending node.
+*
+* dest_addr
+* The IPv6 address of the destination node(s).
+*
+*
+* SEE ALSO
+* IB Network Drivers, eth_hdr_t, arp_pkt_t, tcp_hdr_t, udp_hdr_t
+*********/
+#include <complib/cl_packoff.h>
+
+
#include <complib/cl_packon.h>
/****s* IB Network Drivers/tcp_hdr_t
* NAME
@@ -432,8 +499,11 @@
*********/
#include <complib/cl_packoff.h>
-#define DHCP_PORT_SERVER CL_HTON16(67)
-#define DHCP_PORT_CLIENT CL_HTON16(68)
+#define DHCP_PORT_SERVER CL_HTON16(67)
+#define DHCP_PORT_CLIENT CL_HTON16(68)
+#define DHCP_IPV6_PORT_SERVER_OR_AGENT CL_HTON16(547)
+#define DHCP_IPV6_PORT_CLIENT CL_HTON16(546)
+
#define DHCP_PORT_PROXY_SERVER CL_HTON16(4011)
#define DHCP_REQUEST 1
@@ -534,7 +604,11 @@
typedef struct _ip_pkt
{
- ip_hdr_t hdr;
+ union
+ {
+ ip_hdr_t hdr;
+ ipv6_hdr_t hdr_ipv6;
+ } PACK_SUFFIX ;
union _ip_payload
{
tcp_hdr_t tcp;
Index: ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h
===================================================================
--- ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h (revision 2982)
+++ ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h (working copy)
@@ -205,6 +205,7 @@
BuildSendDesc,
SendMgrFilter,
FilterIp,
+ FilterIpV6,
QueryIp,
SendTcp,
FilterUdp,
Index: ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp
===================================================================
--- ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp (revision 2982)
+++ ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp (working copy)
@@ -3303,7 +3303,6 @@
shutter_shut( &p_adapter->recv_shutter );
// Notify that shutter was already shut
p_adapter->ipoib_state |= IPOIB_RESET_OR_DOWN;
- ASSERT( p_adapter->ipoib_state == IPOIB_RUNNING );
IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SHUTTER,
("ipoib_state was IPOIB_RUNNING and IPOIB_RESET_OR_DOWN flag was set\n") );
}
Index: ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp
===================================================================
--- ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp (revision 2982)
+++ ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp (working copy)
@@ -349,9 +349,10 @@
static NDIS_STATUS
__send_mgr_filter_udp(
- IN const ip_hdr_t* const p_ip_hdr,
+ IN const void* const p_ip_hdr,
IN MDL* p_mdl,
IN size_t buf_len,
+ IN uint8_t prot,
IN OUT ipoib_send_NB_SG* const s_buf);
static NDIS_STATUS
@@ -609,11 +610,17 @@
/* 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)
+static inline void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr)
{
return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));
}
+static inline void* GetIpv6PayloadPtr(const ipv6_hdr_t* const p_ipv6_hdr)
+{
+ return (void*)((uint8_t*)p_ipv6_hdr + p_ipv6_hdr->payload_length);
+}
+
+
/******************************************************************************
*
* Implementation
@@ -2522,6 +2529,67 @@
switch( p_ipoib->hdr.type )
{
+ case ETH_PROT_TYPE_IPV6:
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ipv6_hdr_t)) )
+ {
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+ ("Received IP packet < min size\n") );
+ status = IB_INVALID_SETTING;
+ break;
+ }
+
+ if( p_ipoib->type.ip.hdr_ipv6.next_header != IP_PROT_UDP )
+ {
+ /* Unfiltered. Setup the ethernet header and report. */
+ cl_perf_start( RecvTcp );
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );
+ cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );
+ break;
+ }
+ //ASSERT( p_ipoib->type.ip.hdr_ipv6.payload_length == sizeof(ipv6_hdr_t) );
+
+ /* First packet of a UDP transfer. */
+ if( len <
+ (sizeof(ipoib_hdr_t) + sizeof(ipv6_hdr_t) + sizeof(udp_hdr_t)) )
+ {
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+ ("Received UDP packet < min size\n") );
+ status = IB_INVALID_SETTING;
+ break;
+ }
+
+ /* Check if DHCP conversion is required. */
+ if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_IPV6_PORT_SERVER_OR_AGENT&&
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_IPV6_PORT_CLIENT) ||
+ (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_IPV6_PORT_CLIENT &&
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_IPV6_PORT_SERVER_OR_AGENT))
+ {
+ //TODO should be DHCP IPv6
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ipv6_hdr_t) +
+ sizeof(udp_hdr_t) /*+ DHCP_MIN_SIZE*/) )
+ {
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+ ("Received DHCP < min size\n") );
+ status = IB_INVALID_SETTING;
+ break;
+ }
+
+ /* UDP packet with BOOTP ports in src/dst port numbers. */
+ cl_perf_start( RecvDhcp );
+ //TODO implement this function
+ //status = __recv_dhcp_ipv6( p_port, p_ipoib, p_eth, p_src, p_dst );
+ status = IB_INVALID_SETTING;
+ cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );
+ }
+ else
+ {
+ /* Unfiltered. Setup the ethernet header and report. */
+ cl_perf_start( RecvUdp );
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );
+ cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );
+ }
+ break;
+
case ETH_PROT_TYPE_IP:
if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )
{
@@ -3479,6 +3547,11 @@
switch( p_eth_hdr->type )
{
+ case ETH_PROT_TYPE_IPV6:
+ cl_perf_start( FilterIpV6 );
+ status = __send_mgr_filter_ip( p_eth_hdr, p_mdl, buf_len, s_buf );
+ cl_perf_stop( &p_port->p_adapter->perf, FilterIpV6 );
+ break;
case ETH_PROT_TYPE_IP:
cl_perf_start( FilterIp );
status = __send_mgr_filter_ip( p_eth_hdr, p_mdl, buf_len, s_buf );
@@ -4294,10 +4367,12 @@
IN ipoib_send_NB_SG *s_buf )
{
NDIS_STATUS status;
- ip_hdr_t *p_ip_hdr;
+ PVOID p_ip_hdr;
uint32_t ip_packet_len;
size_t iph_size_in_bytes;
size_t iph_options_size;
+ uint8_t prot;
+ size_t hdr_size;
PERF_DECLARE( QueryIp );
PERF_DECLARE( SendTcp );
@@ -4328,23 +4403,33 @@
}
else
{
- p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);
+ p_ip_hdr = (PVOID) (p_eth_hdr + 1);
}
-
- if( buf_len < sizeof(ip_hdr_t) )
+
+ if ( p_eth_hdr->type == ETH_PROT_TYPE_IPV6 )
{
+ prot = ((ipv6_hdr_t *) p_ip_hdr)->next_header;
+ hdr_size = sizeof(ipv6_hdr_t);
+ }
+ else //IPv4
+ {
+ prot = ((ip_hdr_t *) p_ip_hdr)->prot;
+ hdr_size = sizeof(ip_hdr_t);
+ }
+ if( buf_len < hdr_size )
+ {
/* 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") );
return NDIS_STATUS_BUFFER_TOO_SHORT;
}
- switch( p_ip_hdr->prot )
+ switch( prot )
{
case IP_PROT_UDP:
cl_perf_start( FilterUdp );
status = __send_mgr_filter_udp( p_ip_hdr, p_mdl,
- (buf_len - sizeof(ip_hdr_t)), s_buf );
+ (buf_len - hdr_size), prot, s_buf );
cl_perf_stop( &p_port->p_adapter->perf, FilterUdp );
if( status == NDIS_STATUS_PENDING )
{ /* not DHCP packet, keep going */
@@ -4366,7 +4451,7 @@
2. ip options
So to get the IGMP packet we need to skip the ip options NDIS_BUFFER
*/
- iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;
+ iph_size_in_bytes = (((ip_hdr_t*)p_ip_hdr)->ver_hl & 0xf) * 4;
iph_options_size = iph_size_in_bytes - buf_len;
buf_len -= sizeof(ip_hdr_t);//without ipheader
@@ -4376,7 +4461,7 @@
We anyway pass it to __send_mgr_filter_igmp_v2().
*/
status = __send_mgr_filter_igmp_v2( s_buf->p_port,
- p_ip_hdr,
+ (ip_hdr_t*) p_ip_hdr,
iph_options_size,
p_mdl,
buf_len );
@@ -4384,6 +4469,7 @@
return status;
case IP_PROT_ICMP:
+ case IP_PROT_ICMPV6:
p_desc->send_dir = SEND_UD_QP;
default:
break;
@@ -4400,7 +4486,7 @@
}
if( p_desc->send_dir == SEND_UD_QP )
{
- ip_packet_len = cl_ntoh16( p_ip_hdr->length );
+ ip_packet_len = cl_ntoh16( ((ip_hdr_t*)p_ip_hdr)->length ); //TODO add IPv6 support for CM flow
if( ip_packet_len > s_buf->p_port->p_adapter->params.payload_mtu )
{
//TODO: NDIS60
@@ -4565,10 +4651,11 @@
static NDIS_STATUS
__send_mgr_filter_udp(
- IN const ip_hdr_t* const p_ip_hdr,
- IN MDL* p_mdl,
- IN size_t buf_len,
- IN OUT ipoib_send_NB_SG* s_buf )
+ IN const void* const p_ip_hdr,
+ IN MDL* p_mdl,
+ IN size_t buf_len,
+ IN uint8_t prot,
+ IN OUT ipoib_send_NB_SG* s_buf )
{
NDIS_STATUS status;
udp_hdr_t *p_udp_hdr;
@@ -4598,17 +4685,25 @@
}
else
{
- p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);
+ if ( prot == ETH_PROT_TYPE_IPV6 )
+ {
+ p_udp_hdr = (udp_hdr_t*)GetIpv6PayloadPtr((ipv6_hdr_t*)p_ip_hdr);
+ }
+ else //IPv4
+ {
+ p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr((ip_hdr_t*)p_ip_hdr);
+ if (((ip_hdr_t*)p_ip_hdr)->offset > 0) {
+ /* This is a fragmented part of UDP packet
+ * Only first packet will contain UDP header in such case
+ * So, return if offset > 0
+ */
+ return NDIS_STATUS_PENDING;
+ }
+ }
}
/* Get the UDP header and check the destination port numbers. */
- if (p_ip_hdr->offset > 0) {
- /* This is a fragmented part of UDP packet
- * Only first packet will contain UDP header in such case
- * So, return if offset > 0
- */
- return NDIS_STATUS_PENDING;
- }
+
if( buf_len < sizeof(udp_hdr_t) )
{
@@ -4617,13 +4712,26 @@
return NDIS_STATUS_BUFFER_TOO_SHORT;
}
- if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||
- p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&
- (p_udp_hdr->src_port != DHCP_PORT_SERVER ||
- p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )
+ if ( prot == ETH_PROT_TYPE_IPV6 ) {
+ if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||
+ p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&
+ (p_udp_hdr->src_port != DHCP_PORT_SERVER ||
+ p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )
+ {
+ /* Not a DHCP packet. */
+ return NDIS_STATUS_PENDING;
+ }
+ }
+ else //IPv4
{
- /* Not a DHCP packet. */
- return NDIS_STATUS_PENDING;
+ if( (p_udp_hdr->src_port != DHCP_IPV6_PORT_CLIENT||
+ p_udp_hdr->dst_port != DHCP_IPV6_PORT_SERVER_OR_AGENT) &&
+ (p_udp_hdr->src_port != DHCP_IPV6_PORT_SERVER_OR_AGENT ||
+ p_udp_hdr->dst_port != DHCP_IPV6_PORT_CLIENT) )
+ {
+ /* Not a DHCP packet. */
+ return NDIS_STATUS_PENDING;
+ }
}
buf_len -= sizeof(udp_hdr_t);
@@ -4638,7 +4746,16 @@
return NDIS_STATUS_RESOURCES;
}
/* Copy the IP and UDP headers. */
- cl_memcpy( &s_buf->p_send_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );
+ //TODO: in this case we limited IP size to 20, but it can be bigger, according to GetIpPayloadPtr
+ if ( prot == ETH_PROT_TYPE_IPV6 )
+ {
+ cl_memcpy( &s_buf->p_send_buf->ip.hdr_ipv6, p_ip_hdr , sizeof(ipv6_hdr_t) );
+ }
+ else
+ {
+ cl_memcpy( &s_buf->p_send_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );
+ }
+
cl_memcpy(
&s_buf->p_send_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) );
Alexander (XaleX) Naslednikov
SW Networking Team
Mellanox Technologies
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20101107/baddad1e/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ipv6_initial.patch
Type: application/octet-stream
Size: 13651 bytes
Desc: ipv6_initial.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20101107/baddad1e/attachment.obj>
More information about the ofw
mailing list