[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