[ofw] [patch][IPoIB_NDIS6_CM] Network discovery support for IPv6

Alex Naslednikov xalex at mellanox.co.il
Wed Jan 26 06:15:41 PST 2011


Network discovery support for IPv6
 Signed-off by: Galina Tcharny (galina at mellanox.co.il)
Index: inc/kernel/ip_packet.h
===================================================================
--- inc/kernel/ip_packet.h           (revision 3080)
+++ inc/kernel/ip_packet.h        (working copy)
@@ -49,6 +49,7 @@
 #define ETH_PROT_TYPE_RARP               CL_HTON16(0x8035)
 #define ETH_PROT_VLAN_TAG               CL_HTON16(0x8100)

+#define IPV6_ADDR_LENGTH  16

 #define ETH_IS_LOCALLY_ADMINISTERED(addr) \
                (BOOLEAN)(((PUCHAR)(addr))[0] & ((UCHAR)0x02))
@@ -637,7 +638,70 @@
                }              PACK_SUFFIX type;

 }             PACK_SUFFIX eth_pkt_t;
+
 #include <complib/cl_packoff.h>

+#include <complib/cl_packon.h>

+#define ICMPV6_MSG_TYPE_NBR_SOL 135
+#define ICMPV6_MSG_TYPE_NBR_ADV 136
+
+typedef struct _icmpv6_hdr
+{
+             uint8_t type;
+             uint8_t code;
+             net16_t                checksum;
+} icmpv6_hdr_t;
+
+typedef struct _icmpv6_pkt
+{
+             icmpv6_hdr_t hdr;
+
+             union
+             {
+                             struct _icmpv6_neighbor_sol
+                             {
+                                             net32_t                 reserved;
+                                             uint8_t                  target_addr[IPV6_ADDR_LENGTH];
+                             } sol;
+
+                             struct _icmpv6_neighbor_adv
+                             {
+                                             net32_t                 flags;
+                                             uint8_t                  target_addr[IPV6_ADDR_LENGTH];
+                             } adv;
+             } u;
+} icmpv6_pkt_t;
+
+#define ICMPV6_OPTION_SRC_LINK_ADDR                    1
+#define ICMPV6_OPTION_TARGET_LINK_ADDR            2
+
+#define ICMPV6_IPOIB_LINK_ADDR_OPTION_LENGTH                              24
+#define ICMPV6_IPOIB_LINK_ADDR_OPTION_ADDR_LENGTH               (ICMPV6_IPOIB_LINK_ADDR_OPTION_LENGTH - 2)
+
+#define ICMPV6_ETH_LINK_ADDR_OPTION_LENGTH                 8
+#define ICMPV6_ETH_LINK_ADDR_OPTION_ADDR_LENGTH   (ICMPV6_ETH_LINK_ADDR_OPTION_LENGTH - 2)
+
+typedef struct _icmpv6_option
+{
+    uint8_t     option_type;
+    uint8_t     option_length;  // length of the entire option in 8-byte blocks == 1(MAC Option)
+
+             union
+             {
+                             struct _icmpv6_src_link_addr
+                             {
+                             uint8_t     mac_addr[ICMPV6_IPOIB_LINK_ADDR_OPTION_ADDR_LENGTH];
+                             } saddr;
+
+                             struct _icmpv6_target_link_addr
+                             {
+                             uint8_t     mac_addr[ICMPV6_IPOIB_LINK_ADDR_OPTION_ADDR_LENGTH];
+                             } taddr;
+             } u;
+} icmpv6_option_t;
+
+
+#include <complib/cl_packoff.h>
+
 #endif  /* _IP_PACKET_H_ */
Index: ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp
===================================================================
--- ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp                (revision 3080)
+++ ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp             (working copy)
@@ -305,6 +305,15 @@
                IN                                                           ipoib_endpt_t* const                    p_dst );

 static ib_api_status_t
+__recv_icmpv6(
+             IN                                                           ipoib_port_t* const                                        p_port,
+             IN                                                           ib_wc_t* const                                                 p_wc,
+             IN                                                           ipoib_pkt_t* const                                          p_ipoib,
+             OUT                                                       eth_pkt_t* const                                             p_eth,
+             IN                                                           ipoib_endpt_t** const                 pp_src,
+             IN                                                           ipoib_endpt_t* const                    p_dst );
+
+static ib_api_status_t
 __recv_mgr_prepare_NBL(
                IN                                                           ipoib_port_t* const                                        p_port,
                IN                                                           ipoib_recv_desc_t* const            p_desc,
@@ -377,6 +386,13 @@
                IN                                                           size_t                                                                                    buf_len,
                IN           OUT                                       ipoib_send_NB_SG* const                          s_buf );

+static NDIS_STATUS
+__send_mgr_filter_icmpv6(
+             IN                           const     ipv6_hdr_t* const                                           p_ipv6_hdr,
+             IN                                                           MDL*                                                                                    p_mdl,
+             IN                                                           size_t                                                                                    buf_len,
+             IN           OUT                                       ipoib_send_NB_SG*                                      s_buf);
+
 static inline void
 __send_complete_net_buffer(
                IN           ipoib_send_NB_SG        *s_buf,
@@ -419,6 +435,8 @@
                IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info,
                IN                                                           NET_BUFFER                                                                      *p_netbuf);

+unsigned short ipchksum(unsigned short *ip, int len);
+
 static inline void
                ipoib_print_ip_hdr(
                IN                                                           ip_hdr_t*            const                                     p_ip_hdr )
@@ -647,6 +665,13 @@
 __leave_error_mcast_cb(
                IN                                                           void                                                                                       *context );

+static ib_api_status_t
+__endpt_update(
+             IN                                                           ipoib_port_t* const                                        p_port,
+             IN                                                           ipoib_endpt_t** const                 pp_src,
+             IN                                                           const ipoib_hw_addr_t*                              p_new_hw_addr,
+             IN                                                           ib_wc_t* const                                                 p_wc
+);

 #if DBG
 char *ref_cnt_str(int type);
@@ -2877,6 +2902,12 @@
                                                                status = IB_INVALID_SETTING;
                                                                break;
                                                }
+
+                                             if( p_ipoib->type.ipv6.hdr.next_header == IP_PROT_ICMPV6 )
+                                             {
+                                                             status = __recv_icmpv6( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );
+                                                             break;
+                                             }

                                                if( p_ipoib->type.ipv6.hdr.next_header != IP_PROT_UDP )
                                                {
@@ -3328,8 +3359,6 @@
                ib_api_status_t                                                status;
                arp_pkt_t                                                            *p_arp;
                const ipoib_arp_pkt_t   *p_ib_arp;
-              ib_gid_t                                                               gid;
-              mac_addr_t                                                       mac;
                ipoib_hw_addr_t                                             null_hw = {0};
                uint8_t                                                                 cm_capable = 0;
                boolean_t                                                           queue_rc_conn = FALSE;
@@ -3375,110 +3404,13 @@
                if( !*pp_src )
                                *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );

-              /*
-              * If the endpoint exists for the GID, make sure
-              * the dlid and qpn match the arp.
-              */
-              if( *pp_src )
-              {
-                              if( memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) )
-                              {
-                                              /*
-                                              * GIDs for the endpoint are different.  The ARP must
-                                              * have been proxied.  Dereference it.
-                                              */
-                                              *pp_src = NULL;
-                              }
-                              else if( (*pp_src)->dlid && (*pp_src)->dlid != p_wc->recv.ud.remote_lid )
-                              {
-                                              /* Out of date!  Destroy the endpoint and replace it. */
-                                              __endpt_mgr_remove( p_port, *pp_src );
-                                              *pp_src = NULL;
-                              }
-                              else if ( ! ((*pp_src)->dlid))
-                              {
-                                              /* Out of date!  Destroy the endpoint and replace it. */
-                                              __endpt_mgr_remove( p_port, *pp_src );
-                                              *pp_src = NULL;
-                              }
-                              else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )
-                              {
-                                              if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&
-                                                              p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )
-                                              {
-                                                              /* Out of date!  Destroy the endpoint and replace it. */
-                                                              __endpt_mgr_remove( p_port, *pp_src );
-                                                              *pp_src = NULL;
-                                              }
-                              }
-                              else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )
-                              {
-                                              /* Out of date!  Destroy the endpoint and replace it. */
-                                              __endpt_mgr_remove( p_port, *pp_src );
-                                              *pp_src = NULL;
-                              }
-              }
+             status = __endpt_update(p_port, pp_src, &p_ib_arp->src_hw, p_wc);

-              /* Do we need to create an endpoint for this GID? */
-              if( !*pp_src )
+             if(status != IB_SUCCESS)
                {
-                              /* Copy the src GID to allow aligned access */
-                              memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );
-                              status = ipoib_mac_from_guid( gid.unicast.interface_id,
-                                                                                                                                                p_port->p_adapter->params.guid_mask,
-                                                                                                                                                &mac );
-                              if (status == IB_INVALID_GUID_MASK)
-                              {
-                                              IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,
-                                                              ("Invalid GUID mask received, rejecting it") );
-                                              ipoib_create_log( p_port->p_adapter->h_adapter,
-                                                                                                                GUID_MASK_LOG_INDEX,
-                                                                                                                EVENT_IPOIB_WRONG_PARAMETER_WRN );
-                                              return status;
-                              }
-                              else if( status != IB_SUCCESS )
-                              {
-                                              IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
-                                                              ("ipoib_mac_from_guid returned %s\n",
-                                                                              p_port->p_adapter->p_ifc->get_err_str( status )) );
-                                              return status;
-                              }
-
-                              /*
-                              * Create the endpoint.
-                              */
-                              *pp_src = ipoib_endpt_create( p_port,
-                                                                                                                                                &p_ib_arp->src_hw.gid,
-                                                                                                                                                p_wc->recv.ud.remote_lid,                                                                                                                                                                                                                                        ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );
-
-                              if( !*pp_src )
-                              {
-                                              IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
-                                                              ("ipoib_endpt_create failed\n") );
-                                              return status;
-                              }
-#if DBG
-                              ipoib_port_ref( p_port, ref_endpt_track );
-#endif
-                              cl_obj_lock( &p_port->obj );
-                              status = __endpt_mgr_insert( p_port, mac, *pp_src );
-                              cl_obj_unlock( &p_port->obj );
-                              if( status != IB_SUCCESS )
-                              {
-                                              IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
-                                                              ("__endpt_mgr_insert return %s \n",
-                                                              p_port->p_adapter->p_ifc->get_err_str( status )) );
-                                              return status;
-                              }
-                              IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ARP,
-                                              ("Created EP %p %s CM_cap %s cstate[%s] %s\n",
-                                                              (*pp_src),
-                                                              (*pp_src)->tag,
-                                                              (cm_capable == IPOIB_CM_FLAG_RC ? "1" : "0"),
-                                                              cm_get_state_str(endpt_cm_get_state((*pp_src))),
-                                                              mk_mac_str(&(*pp_src)->mac)) );
+                             return status;
                }
-
+
                (*pp_src)->cm_flag = cm_capable;

                CL_ASSERT( !memcmp(
@@ -3642,7 +3574,90 @@
                return IB_SUCCESS;
 }

+static ib_api_status_t
+__recv_icmpv6(
+             IN                                                           ipoib_port_t* const                                        p_port,
+             IN                                                           ib_wc_t* const                                                 p_wc,
+             IN                                                           ipoib_pkt_t* const                                          p_ipoib,
+             OUT                                                       eth_pkt_t* const                                             p_eth,
+             IN                                                           ipoib_endpt_t** const                 pp_src,
+             IN                                                           ipoib_endpt_t* const                    p_dst )
+{
+             ib_api_status_t                                                status;
+             ipv6_hdr_t                                                          *p_ipv6_hdr;
+             icmpv6_pkt_t            *p_icmpv6_pkt;
+             icmpv6_option_t                                             *p_icmpv6_opt;
+             IPOIB_ENTER( IPOIB_DBG_RECV );

+             if( !p_dst )
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Unknown destination endpoint\n") );
+                             return IB_INVALID_SETTING;
+             }
+
+             p_icmpv6_pkt = (icmpv6_pkt_t *) (&p_ipoib->type.ipv6.hdr + 1);
+
+             if(p_icmpv6_pkt->hdr.type != ICMPV6_MSG_TYPE_NBR_ADV &&
+                p_icmpv6_pkt->hdr.type != ICMPV6_MSG_TYPE_NBR_SOL)
+             {
+                             goto recv_gen;
+             }
+
+             p_ipv6_hdr = &p_ipoib->type.ipv6.hdr;
+
+             if(CL_NTOH16(p_ipv6_hdr->payload_length) != sizeof(icmpv6_pkt_t) +
+                             sizeof(icmpv6_option_t))
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Malformed ICMPv6 neighbor discovery packet\n") );
+                             return IB_INVALID_SETTING;
+             }
+
+             p_icmpv6_opt = (icmpv6_option_t *) (p_icmpv6_pkt + 1);
+
+             if(p_icmpv6_opt->option_type != ICMPV6_OPTION_SRC_LINK_ADDR &&
+                p_icmpv6_opt->option_type != ICMPV6_OPTION_TARGET_LINK_ADDR)
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Invalid ICMPv6 option type\n") );
+                             return IB_INVALID_SETTING;
+             }
+
+             if(p_icmpv6_opt->option_length != ICMPV6_IPOIB_LINK_ADDR_OPTION_LENGTH / 8)
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Invalid ICMPv6 option length\n") );
+                             return IB_INVALID_SETTING;
+             }
+
+             status = __endpt_update(p_port, pp_src, (ipoib_hw_addr_t *) p_icmpv6_opt->u.saddr.mac_addr, p_wc);
+
+             if(status != IB_SUCCESS)
+             {
+                             return status;
+             }
+
+             p_ipv6_hdr->payload_length = cl_hton16(CL_NTOH16(p_ipv6_hdr->payload_length) +
+                             ICMPV6_ETH_LINK_ADDR_OPTION_LENGTH - ICMPV6_IPOIB_LINK_ADDR_OPTION_LENGTH);
+             p_icmpv6_opt->option_length = ICMPV6_ETH_LINK_ADDR_OPTION_LENGTH / 8;
+             cl_memcpy(p_icmpv6_opt->u.saddr.mac_addr, &(*pp_src)->mac, sizeof(mac_addr_t));
+
+recv_gen:
+             status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst );
+
+             if( status != IB_SUCCESS )
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("__recv_gen returned %s.\n",
+                                             p_port->p_adapter->p_ifc->get_err_str( status )) );
+                             return status;
+             }
+
+             IPOIB_EXIT( IPOIB_DBG_RECV );
+             return IB_SUCCESS;
+}
+
 static ib_api_status_t
 __recv_mgr_prepare_NBL(
                IN                                                           ipoib_port_t* const                                        p_port,
@@ -5193,15 +5208,24 @@
                                                                                                                                                                                buf_len );
                                if( status != NDIS_STATUS_SUCCESS )
                                                return status;
-                              break;   // required if ICMP/ICMPV6 can go RC?
-
+                             p_desc->send_dir = SEND_UD_QP;
+                             break;
+
                case IP_PROT_ICMP:
+                             p_desc->send_dir = SEND_UD_QP;
+                             break;
+
                case IP_PROT_ICMPV6:
+                             status = __send_mgr_filter_icmpv6( (ipv6_hdr_t*) p_ip_hdr,
+                                                                                                                                                                             p_mdl,
+                                                                                                                                                                             (buf_len - hdr_size), s_buf);
+
+                             if( status != NDIS_STATUS_PENDING ) {
+                                             return status;
+                             }
+                             p_desc->send_dir = SEND_UD_QP;
                                break;
-
-              case IPPROTO_HOPOPTS:
-                              break;
-
+
                default:
                                break;
                }
@@ -5256,6 +5280,100 @@
 }

 static NDIS_STATUS
+__send_mgr_filter_icmpv6(
+             IN                           const     ipv6_hdr_t* const                                           p_ipv6_hdr,
+             IN                                                           MDL*                                                                                    p_mdl,
+             IN                                                           size_t                                                                                    buf_len,
+             IN           OUT                                       ipoib_send_NB_SG*                                      s_buf)
+{
+             icmpv6_pkt_t    *p_icmpv6_orig_pkt;
+             icmpv6_pkt_t    *p_icmpv6_new_pkt;
+
+             ipoib_send_desc_t *p_desc = s_buf->p_port->p_desc;
+
+             IPOIB_ENTER( IPOIB_DBG_SEND );
+             if( !buf_len )
+             {
+                             NdisGetNextMdl( p_mdl, &p_mdl );
+                             if( !p_mdl )
+                             {
+                                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                                             ("Failed to get DHCP buffer.\n") );
+                                             return NDIS_STATUS_FAILURE;
+                             }
+                             NdisQueryMdl( p_mdl, &p_icmpv6_orig_pkt, &buf_len, NormalPagePriority );
+                             if( !p_icmpv6_orig_pkt )
+                             {
+                                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                                             ("Failed to query DHCP buffer.\n") );
+                                             return NDIS_STATUS_FAILURE;
+                             }
+             }
+             else
+             {
+                             p_icmpv6_orig_pkt = (icmpv6_pkt_t*)(p_ipv6_hdr + 1);
+             }
+
+             if( buf_len < sizeof(icmpv6_hdr_t) )
+             {
+                             /* This buffer is done for.  Get the next buffer. */
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Buffer too small for ICMPv6 packet.\n") );
+                             return NDIS_STATUS_BUFFER_TOO_SHORT;
+             }
+
+             if(p_icmpv6_orig_pkt->hdr.type != ICMPV6_MSG_TYPE_NBR_ADV &&
+                p_icmpv6_orig_pkt->hdr.type != ICMPV6_MSG_TYPE_NBR_SOL)
+             {
+                             return NDIS_STATUS_PENDING;
+             }
+
+             /* Allocate our scratch buffer. */
+             ASSERT(s_buf->p_send_buf == NULL);
+             s_buf->p_send_buf = (send_buf_t*)
+                                                                                                             NdisAllocateFromNPagedLookasideList(
+                                                                                                                                                             &s_buf->p_port->buf_mgr.send_buf_list );
+             if( !s_buf->p_send_buf )
+             {
+                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                             ("Failed to query ARP packet buffer.\n") );
+                             return NDIS_STATUS_RESOURCES;
+             }
+
+             ipv6_hdr_t *p_new_ipv6 = &s_buf->p_send_buf->ipv6.hdr;
+
+             cl_memcpy(p_new_ipv6, p_ipv6_hdr, sizeof(ipv6_hdr_t));
+
+             p_icmpv6_new_pkt = (icmpv6_pkt_t *) (p_new_ipv6 + 1);
+
+             cl_memcpy(p_icmpv6_new_pkt, p_icmpv6_orig_pkt, buf_len);
+
+             icmpv6_option_t *p_new_option = (icmpv6_option_t *) (p_icmpv6_new_pkt + 1);
+             p_new_option->option_type = (p_icmpv6_orig_pkt->hdr.type == ICMPV6_MSG_TYPE_NBR_SOL) ?
+                                                                                                                             ICMPV6_OPTION_SRC_LINK_ADDR : ICMPV6_OPTION_TARGET_LINK_ADDR;
+             p_new_option->option_length = ICMPV6_IPOIB_LINK_ADDR_OPTION_LENGTH / 8;
+
+             ipoib_hw_addr_t* link_addr = (ipoib_hw_addr_t *) p_new_option->u.saddr.mac_addr;
+
+             ipoib_addr_set_qpn( link_addr, s_buf->p_port->ib_mgr.qpn );
+
+             ib_gid_set_default( &link_addr->gid,
+                                                                                             s_buf->p_port->p_adapter->guids.port_guid.guid );
+
+             p_new_ipv6->payload_length = cl_hton16(sizeof(icmpv6_pkt_t) + sizeof(icmpv6_option_t));
+
+             p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( s_buf->p_send_buf );
+             p_desc->send_wr[0].local_ds[1].length = sizeof(ipv6_hdr_t) + sizeof(icmpv6_pkt_t) + sizeof(icmpv6_option_t);
+             p_desc->send_wr[0].local_ds[1].lkey = s_buf->p_port->ib_mgr.lkey;
+             p_desc->send_wr[0].wr.num_ds = 2;
+             p_desc->send_wr[0].wr.p_next = NULL;
+             p_desc->send_dir = SEND_UD_QP;
+
+             IPOIB_EXIT( IPOIB_DBG_SEND );
+             return STATUS_SUCCESS;
+}
+
+static NDIS_STATUS
 __send_mgr_filter_igmp_v2(
                IN                                                           ipoib_port_t* const                                        p_port,
                IN                           const     ip_hdr_t* const                                                                p_ip_hdr,
@@ -9289,6 +9407,118 @@
 }


+static ib_api_status_t
+__endpt_update(
+             IN                                                           ipoib_port_t* const                                        p_port,
+             IN                                                           ipoib_endpt_t** const                 pp_src,
+             IN                                                           const ipoib_hw_addr_t*                              p_new_hw_addr,
+             IN                                                           ib_wc_t* const                                                 p_wc
+)
+{
+             ib_api_status_t status = IB_ERROR;
+             ib_gid_t gid;
+             mac_addr_t mac;
+
+             /*
+             * If the endpoint exists for the GID, make sure
+             * the dlid and qpn match the arp.
+             */
+             if( *pp_src )
+             {
+                             if( cl_memcmp( &(*pp_src)->dgid, &p_new_hw_addr->gid, sizeof(ib_gid_t) ) )
+                             {
+                                             /*
+                                             * GIDs for the endpoint are different.  The ARP must
+                                             * have been proxied.  Dereference it.
+                                             */
+                                             *pp_src = NULL;
+                             }
+                             else if( (*pp_src)->dlid && (*pp_src)->dlid != p_wc->recv.ud.remote_lid )
+                             {
+                                             /* Out of date!  Destroy the endpoint and replace it. */
+                                             __endpt_mgr_remove( p_port, *pp_src );
+                                             *pp_src = NULL;
+                             }
+                             else if ( ! ((*pp_src)->dlid))
+                             {
+                                             /* Out of date!  Destroy the endpoint and replace it. */
+                                             __endpt_mgr_remove( p_port, *pp_src );
+                                             *pp_src = NULL;
+                             }
+                             else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )
+                             {
+                                             if( (*pp_src)->qpn != ipoib_addr_get_qpn( p_new_hw_addr ) &&
+                                                             p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( p_new_hw_addr ) )
+                                             {
+                                                             /* Out of date!  Destroy the endpoint and replace it. */
+                                                             __endpt_mgr_remove( p_port, *pp_src );
+                                                             *pp_src = NULL;
+                                             }
+                             }
+                             else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )
+                             {
+                                             /* Out of date!  Destroy the endpoint and replace it. */
+                                             __endpt_mgr_remove( p_port, *pp_src );
+                                             *pp_src = NULL;
+                             }
+             }
+
+             /* Do we need to create an endpoint for this GID? */
+             if( !*pp_src )
+             {
+                             /* Copy the src GID to allow aligned access */
+                             cl_memcpy( &gid, &p_new_hw_addr->gid, sizeof(ib_gid_t) );
+                             status = ipoib_mac_from_guid( gid.unicast.interface_id,
+                                                                                                                                               p_port->p_adapter->params.guid_mask,
+                                                                                                                                               &mac );
+                             if (status == IB_INVALID_GUID_MASK)
+                             {
+                                             IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,
+                                                             ("Invalid GUID mask received, rejecting it") );
+                                             ipoib_create_log( p_port->p_adapter->h_adapter,
+                                                                                                               GUID_MASK_LOG_INDEX,
+                                                                                                               EVENT_IPOIB_WRONG_PARAMETER_WRN );
+                                             return status;
+                             }
+                             else if( status != IB_SUCCESS )
+                             {
+                                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                                             ("ipoib_mac_from_guid returned %s\n",
+                                                                             p_port->p_adapter->p_ifc->get_err_str( status )) );
+                                             return status;
+                             }
+
+                             /*
+                             * Create the endpoint.
+                             */
+                             *pp_src = ipoib_endpt_create( &p_new_hw_addr->gid,
+                                                                                                                                               p_wc->recv.ud.remote_lid,
+                                                                                                                                               ipoib_addr_get_qpn( p_new_hw_addr ) );
+
+                             if( !*pp_src )
+                             {
+                                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                                             ("ipoib_endpt_create failed\n") );
+                                             status = IB_INSUFFICIENT_MEMORY;
+                                             return status;
+                             }
+
+                             cl_obj_lock( &p_port->obj );
+                             status = __endpt_mgr_insert( p_port, mac, *pp_src );
+                             if( status != IB_SUCCESS )
+                             {
+                                             cl_obj_unlock( &p_port->obj );
+                                             IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
+                                                             ("__endpt_mgr_insert return %s \n",
+                                                             p_port->p_adapter->p_ifc->get_err_str( status )) );
+                                             return status;
+                             }
+                             cl_obj_unlock( &p_port->obj );
+             }
+
+             return IB_SUCCESS;
+}
+
 /*
  *  Put all IP fragments into separate WRs and chain together.
  *  The last WR will be set to generate CQ Event.
Alexander (XaleX) Naslednikov
SW Networking Team
Mellanox Technologies

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20110126/1946f80c/attachment.html>


More information about the ofw mailing list