IB/cma: Fix broken AF_IB UD support
authorMatthew Finlay <Matt@Mellanox.com>
Tue, 19 May 2015 07:11:48 +0000 (00:11 -0700)
committerDoug Ledford <dledford@redhat.com>
Wed, 20 May 2015 20:15:56 +0000 (16:15 -0400)
Support for using UD and AF_IB is currently broken.  The
IB_CM_SIDR_REQ_RECEIVED message is not handled properly in
cma_save_net_info() and we end up falling into code that will try and
process the request as ipv4/ipv6, which will end up failing.

The resolution is to add a check for the SIDR_REQ and call
cma_save_ib_info() with a NULL path record.  Change cma_save_ib_info()
to copy the src sib info from the listen_id when the path record is NULL.

Reported-by: Hari Shankar <Hari.Shankar@netapp.com>
Signed-off-by: Matt Finlay <matt@mellanox.com>
Acked-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/core/cma.c

index 06441a43c3aacd1c6aecb22e15a17529b4a890a8..38ffe098150351aef9ff2ac650726ae7926f6856 100644 (file)
@@ -845,18 +845,26 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id
        listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr;
        ib = (struct sockaddr_ib *) &id->route.addr.src_addr;
        ib->sib_family = listen_ib->sib_family;
-       ib->sib_pkey = path->pkey;
-       ib->sib_flowinfo = path->flow_label;
-       memcpy(&ib->sib_addr, &path->sgid, 16);
+       if (path) {
+               ib->sib_pkey = path->pkey;
+               ib->sib_flowinfo = path->flow_label;
+               memcpy(&ib->sib_addr, &path->sgid, 16);
+       } else {
+               ib->sib_pkey = listen_ib->sib_pkey;
+               ib->sib_flowinfo = listen_ib->sib_flowinfo;
+               ib->sib_addr = listen_ib->sib_addr;
+       }
        ib->sib_sid = listen_ib->sib_sid;
        ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL);
        ib->sib_scope_id = listen_ib->sib_scope_id;
 
-       ib = (struct sockaddr_ib *) &id->route.addr.dst_addr;
-       ib->sib_family = listen_ib->sib_family;
-       ib->sib_pkey = path->pkey;
-       ib->sib_flowinfo = path->flow_label;
-       memcpy(&ib->sib_addr, &path->dgid, 16);
+       if (path) {
+               ib = (struct sockaddr_ib *) &id->route.addr.dst_addr;
+               ib->sib_family = listen_ib->sib_family;
+               ib->sib_pkey = path->pkey;
+               ib->sib_flowinfo = path->flow_label;
+               memcpy(&ib->sib_addr, &path->dgid, 16);
+       }
 }
 
 static __be16 ss_get_port(const struct sockaddr_storage *ss)
@@ -905,9 +913,11 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id
 {
        struct cma_hdr *hdr;
 
-       if ((listen_id->route.addr.src_addr.ss_family == AF_IB) &&
-           (ib_event->event == IB_CM_REQ_RECEIVED)) {
-               cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path);
+       if (listen_id->route.addr.src_addr.ss_family == AF_IB) {
+               if (ib_event->event == IB_CM_REQ_RECEIVED)
+                       cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path);
+               else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED)
+                       cma_save_ib_info(id, listen_id, NULL);
                return 0;
        }