aboutsummaryrefslogtreecommitdiff
path: root/sys/ofed/drivers
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2016-04-22 18:16:12 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2016-04-22 18:16:12 +0000
commit0bab509b948e13c9c3635c352455087adf09cc55 (patch)
treeb326a81bdf27d26194c053e15454e497dc477f5a /sys/ofed/drivers
parentfb0e1892d9e31cdba013c27b24c47c86838924a8 (diff)
downloadsrc-0bab509b948e13c9c3635c352455087adf09cc55.tar.gz
src-0bab509b948e13c9c3635c352455087adf09cc55.zip
More fixes for using IPv6 addresses with RDMA:
- Added check that the SCOPE ID is only restored for IPv6 linklocal addresses. - Changes made by r237263 in the "cma_bind_addr()" function did not check if the socket address was of type IPv6 and used the IPv4 socket address for IPv6 addresses. This caused the function to fail. Fixed this. - In the "rdma_gid2ip()" function and some other places the "sin6_len" and "sin6_scope_id" fields were not set for IPv6 socket addresses. Fixed this. - The scope ID is not stored as part of the GID entries and must be passed as an argument to "rdma_gid2ip()". - Added new method to "struct ib_device" which returns a pointer to the network interface which belongs to the given infiniband device. This is needed to be able to get the scope ID for IPv6 addresses via the associated ethernet interface. - Added convenience function, "rdma_get_ipv6_scope_id()", to get the scope ID for IPv6 addresses. - Implemented new "get_netdev" method for mlx4ib. Other IB controller drivers which want to support IPv6 addresses needs to implement this aswell. - Bumped the FreeBSD version due to changing "struct ib_device". Sponsored by: Mellanox Technologies MFC after: 1 week
Notes
Notes: svn path=/head/; revision=298486
Diffstat (limited to 'sys/ofed/drivers')
-rw-r--r--sys/ofed/drivers/infiniband/core/addr.c31
-rw-r--r--sys/ofed/drivers/infiniband/core/cma.c59
-rw-r--r--sys/ofed/drivers/infiniband/core/uverbs_cmd.c4
-rw-r--r--sys/ofed/drivers/infiniband/core/verbs.c4
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/main.c7
5 files changed, 84 insertions, 21 deletions
diff --git a/sys/ofed/drivers/infiniband/core/addr.c b/sys/ofed/drivers/infiniband/core/addr.c
index f2525cab00c6..577ccc0cadb6 100644
--- a/sys/ofed/drivers/infiniband/core/addr.c
+++ b/sys/ofed/drivers/infiniband/core/addr.c
@@ -43,6 +43,7 @@
#include <net/netevent.h>
#include <rdma/ib_addr.h>
#include <netinet/if_ether.h>
+#include <netinet6/scope6_var.h>
MODULE_AUTHOR("Sean Hefty");
@@ -417,7 +418,8 @@ done:
#ifdef INET6
if (scope_id < 256) {
sin6 = (struct sockaddr_in6 *)src_in;
- SCOPE_ID_RESTORE(scope_id, sin6);
+ if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
+ SCOPE_ID_RESTORE(scope_id, sin6);
sin6 = (struct sockaddr_in6 *)dst_in;
SCOPE_ID_RESTORE(scope_id, sin6);
}
@@ -554,7 +556,7 @@ static void resolve_cb(int status, struct sockaddr *src_addr,
}
int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac,
- u16 *vlan_id)
+ u16 *vlan_id, u32 scope_id)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
@@ -568,11 +570,11 @@ int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac,
} sgid_addr, dgid_addr;
- ret = rdma_gid2ip(&sgid_addr._sockaddr, sgid);
+ ret = rdma_gid2ip(&sgid_addr._sockaddr, sgid, scope_id);
if (ret)
return ret;
- ret = rdma_gid2ip(&dgid_addr._sockaddr, dgid);
+ ret = rdma_gid2ip(&dgid_addr._sockaddr, dgid, scope_id);
if (ret)
return ret;
@@ -598,7 +600,23 @@ int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac,
}
EXPORT_SYMBOL(rdma_addr_find_dmac_by_grh);
-int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
+u32 rdma_get_ipv6_scope_id(struct ib_device *ib, u8 port_num)
+{
+#ifdef INET6
+ struct ifnet *ifp;
+ if (ib->get_netdev == NULL)
+ return (-1U);
+ ifp = ib->get_netdev(ib, port_num);
+ if (ifp == NULL)
+ return (-1U);
+ return (in6_getscopezone(ifp, IPV6_ADDR_SCOPE_LINKLOCAL));
+#else
+ return (-1U);
+#endif
+}
+
+int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id,
+ u32 scope_id)
{
int ret = 0;
struct rdma_dev_addr dev_addr;
@@ -608,8 +626,7 @@ int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
struct sockaddr_in6 _sockaddr_in6;
} gid_addr;
- ret = rdma_gid2ip(&gid_addr._sockaddr, sgid);
-
+ ret = rdma_gid2ip(&gid_addr._sockaddr, sgid, scope_id);
if (ret)
return ret;
memset(&dev_addr, 0, sizeof(dev_addr));
diff --git a/sys/ofed/drivers/infiniband/core/cma.c b/sys/ofed/drivers/infiniband/core/cma.c
index 1cafced985af..3aa3f1716ccc 100644
--- a/sys/ofed/drivers/infiniband/core/cma.c
+++ b/sys/ofed/drivers/infiniband/core/cma.c
@@ -689,8 +689,11 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
== RDMA_TRANSPORT_IB &&
rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)
== IB_LINK_LAYER_ETHERNET) {
- ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL);
+ u32 scope_id = rdma_get_ipv6_scope_id(id_priv->id.device,
+ id_priv->id.port_num);
+ ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL,
+ scope_id);
if (ret)
goto out;
}
@@ -931,11 +934,13 @@ static void cma_save_net_info(struct rdma_addr *addr,
ip4->sin_family = listen4->sin_family;
ip4->sin_addr.s_addr = dst->ip4.addr;
ip4->sin_port = listen4->sin_port;
+ ip4->sin_len = sizeof(struct sockaddr_in);
ip4 = (struct sockaddr_in *) &addr->dst_addr;
ip4->sin_family = listen4->sin_family;
ip4->sin_addr.s_addr = src->ip4.addr;
ip4->sin_port = port;
+ ip4->sin_len = sizeof(struct sockaddr_in);
break;
case 6:
listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
@@ -943,11 +948,15 @@ static void cma_save_net_info(struct rdma_addr *addr,
ip6->sin6_family = listen6->sin6_family;
ip6->sin6_addr = dst->ip6;
ip6->sin6_port = listen6->sin6_port;
+ ip6->sin6_len = sizeof(struct sockaddr_in6);
+ ip6->sin6_scope_id = listen6->sin6_scope_id;
ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
ip6->sin6_family = listen6->sin6_family;
ip6->sin6_addr = src->ip6;
ip6->sin6_port = port;
+ ip6->sin6_len = sizeof(struct sockaddr_in6);
+ ip6->sin6_scope_id = listen6->sin6_scope_id;
break;
default:
break;
@@ -1431,16 +1440,19 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
goto err3;
if (is_iboe && !is_sidr) {
+ u32 scope_id = rdma_get_ipv6_scope_id(cm_id->device,
+ ib_event->param.req_rcvd.port);
+
if (ib_event->param.req_rcvd.primary_path != NULL)
rdma_addr_find_smac_by_sgid(
&ib_event->param.req_rcvd.primary_path->sgid,
- psmac, NULL);
+ psmac, NULL, scope_id);
else
psmac = NULL;
if (ib_event->param.req_rcvd.alternate_path != NULL)
rdma_addr_find_smac_by_sgid(
&ib_event->param.req_rcvd.alternate_path->sgid,
- palt_smac, NULL);
+ palt_smac, NULL, scope_id);
else
palt_smac = NULL;
}
@@ -2296,22 +2308,47 @@ static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
{
if (!src_addr || !src_addr->sa_family) {
src_addr = (struct sockaddr *) &id->route.addr.src_addr;
- if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
+ src_addr->sa_family = dst_addr->sa_family;
+#ifdef INET6
+ if (dst_addr->sa_family == AF_INET6) {
((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
}
+#endif
}
if (!cma_any_addr(src_addr))
return rdma_bind_addr(id, src_addr);
else {
- struct sockaddr_in addr_in;
-
- memset(&addr_in, 0, sizeof addr_in);
- addr_in.sin_family = dst_addr->sa_family;
- addr_in.sin_len = sizeof addr_in;
- return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
+ union {
+#ifdef INET
+ struct sockaddr_in in;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 in6;
+#endif
+ } addr;
+
+ switch(dst_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ memset(&addr.in, 0, sizeof(addr.in));
+ addr.in.sin_family = dst_addr->sa_family;
+ addr.in.sin_len = sizeof(addr.in);
+ return rdma_bind_addr(id, (struct sockaddr *)&addr.in);
+#endif
+#ifdef INET6
+ case AF_INET6:
+ memset(&addr.in6, 0, sizeof(addr.in6));
+ addr.in6.sin6_family = dst_addr->sa_family;
+ addr.in6.sin6_len = sizeof(addr.in6);
+ addr.in6.sin6_scope_id =
+ ((struct sockaddr_in6 *)dst_addr)->sin6_scope_id;
+ return rdma_bind_addr(id, (struct sockaddr *)&addr.in6);
+#endif
+ default:
+ return -EINVAL;
+ }
}
-
}
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
diff --git a/sys/ofed/drivers/infiniband/core/uverbs_cmd.c b/sys/ofed/drivers/infiniband/core/uverbs_cmd.c
index 92c934d62754..2e726aeec614 100644
--- a/sys/ofed/drivers/infiniband/core/uverbs_cmd.c
+++ b/sys/ofed/drivers/infiniband/core/uverbs_cmd.c
@@ -2094,11 +2094,11 @@ static ssize_t __uverbs_modify_qp(struct ib_uverbs_file *file,
} else {
ret = rdma_addr_find_dmac_by_grh(&sgid, dgid,
attr->ah_attr.dmac,
- &attr->vlan_id);
+ &attr->vlan_id, -1U);
if (ret)
goto out;
ret = rdma_addr_find_smac_by_sgid(&sgid, attr->smac,
- NULL);
+ NULL, -1U);
if (ret)
goto out;
}
diff --git a/sys/ofed/drivers/infiniband/core/verbs.c b/sys/ofed/drivers/infiniband/core/verbs.c
index 51a0ed50b7b4..7756b882896c 100644
--- a/sys/ofed/drivers/infiniband/core/verbs.c
+++ b/sys/ofed/drivers/infiniband/core/verbs.c
@@ -207,8 +207,10 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
ah_attr->vlan_id = wc->vlan_id;
} else {
+ u32 scope_id = rdma_get_ipv6_scope_id(device, port_num);
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
- ah_attr->dmac, &ah_attr->vlan_id);
+ ah_attr->dmac, &ah_attr->vlan_id,
+ scope_id);
if (ret)
return ret;
}
diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/main.c b/sys/ofed/drivers/infiniband/hw/mlx4/main.c
index 5be92a221286..41705ad0fb10 100644
--- a/sys/ofed/drivers/infiniband/hw/mlx4/main.c
+++ b/sys/ofed/drivers/infiniband/hw/mlx4/main.c
@@ -1620,6 +1620,12 @@ free:
kfree(gw);
}
+static struct net_device *mlx4_ib_get_netdev(struct ib_device *device, u8 port_num)
+{
+ struct mlx4_ib_dev *ibdev = to_mdev(device);
+ return mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port_num);
+}
+
static void reset_gids_task(struct work_struct *work)
{
struct update_gid_work *gw =
@@ -2353,6 +2359,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach;
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
+ ibdev->ib_dev.get_netdev = mlx4_ib_get_netdev;
ibdev->ib_dev.ioctl = mlx4_ib_ioctl;
ibdev->ib_dev.query_values = mlx4_ib_query_values;