diff options
author | Matthew Finlay <Matt@Mellanox.com> | 2015-05-19 03:11:48 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2015-05-20 16:15:56 -0400 |
commit | c07678bb01374c510b0f6d4a3832c28ba33e9613 (patch) | |
tree | 213bcd1de0eb4cf96fabbd15b95d6c2b662a2da4 | |
parent | c29ed5a4566fc7e0c5d06324d62974c6163d1e06 (diff) |
IB/cma: Fix broken AF_IB UD support
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>
-rw-r--r-- | drivers/infiniband/core/cma.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 06441a43c3aa..38ffe0981503 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -845,18 +845,26 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id | |||
845 | listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr; | 845 | listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr; |
846 | ib = (struct sockaddr_ib *) &id->route.addr.src_addr; | 846 | ib = (struct sockaddr_ib *) &id->route.addr.src_addr; |
847 | ib->sib_family = listen_ib->sib_family; | 847 | ib->sib_family = listen_ib->sib_family; |
848 | ib->sib_pkey = path->pkey; | 848 | if (path) { |
849 | ib->sib_flowinfo = path->flow_label; | 849 | ib->sib_pkey = path->pkey; |
850 | memcpy(&ib->sib_addr, &path->sgid, 16); | 850 | ib->sib_flowinfo = path->flow_label; |
851 | memcpy(&ib->sib_addr, &path->sgid, 16); | ||
852 | } else { | ||
853 | ib->sib_pkey = listen_ib->sib_pkey; | ||
854 | ib->sib_flowinfo = listen_ib->sib_flowinfo; | ||
855 | ib->sib_addr = listen_ib->sib_addr; | ||
856 | } | ||
851 | ib->sib_sid = listen_ib->sib_sid; | 857 | ib->sib_sid = listen_ib->sib_sid; |
852 | ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL); | 858 | ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL); |
853 | ib->sib_scope_id = listen_ib->sib_scope_id; | 859 | ib->sib_scope_id = listen_ib->sib_scope_id; |
854 | 860 | ||
855 | ib = (struct sockaddr_ib *) &id->route.addr.dst_addr; | 861 | if (path) { |
856 | ib->sib_family = listen_ib->sib_family; | 862 | ib = (struct sockaddr_ib *) &id->route.addr.dst_addr; |
857 | ib->sib_pkey = path->pkey; | 863 | ib->sib_family = listen_ib->sib_family; |
858 | ib->sib_flowinfo = path->flow_label; | 864 | ib->sib_pkey = path->pkey; |
859 | memcpy(&ib->sib_addr, &path->dgid, 16); | 865 | ib->sib_flowinfo = path->flow_label; |
866 | memcpy(&ib->sib_addr, &path->dgid, 16); | ||
867 | } | ||
860 | } | 868 | } |
861 | 869 | ||
862 | static __be16 ss_get_port(const struct sockaddr_storage *ss) | 870 | 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 | |||
905 | { | 913 | { |
906 | struct cma_hdr *hdr; | 914 | struct cma_hdr *hdr; |
907 | 915 | ||
908 | if ((listen_id->route.addr.src_addr.ss_family == AF_IB) && | 916 | if (listen_id->route.addr.src_addr.ss_family == AF_IB) { |
909 | (ib_event->event == IB_CM_REQ_RECEIVED)) { | 917 | if (ib_event->event == IB_CM_REQ_RECEIVED) |
910 | cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path); | 918 | cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path); |
919 | else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) | ||
920 | cma_save_ib_info(id, listen_id, NULL); | ||
911 | return 0; | 921 | return 0; |
912 | } | 922 | } |
913 | 923 | ||