Loading Documentation/infiniband/ipoib.txt +5 −5 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ Datagram vs Connected modes fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes. In connected mode, the IB RC (Reliable Connected) transport is used. Connected mode is to takes advantage of the connected nature of the IB transport and allows an MTU up to the maximal IP packet size of 64K, which reduces the number of IP packets needed for handling large UDP datagrams, TCP segments, etc and increases the performance for large messages. Connected mode takes advantage of the connected nature of the IB transport and allows an MTU up to the maximal IP packet size of 64K, which reduces the number of IP packets needed for handling large UDP datagrams, TCP segments, etc and increases the performance for large messages. In connected mode, the interface's UD QP is still used for multicast and communication with peers that don't support connected mode. In Loading drivers/infiniband/core/addr.c +98 −177 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ #include <linux/mutex.h> #include <linux/inetdevice.h> #include <linux/workqueue.h> #include <linux/if_arp.h> #include <net/arp.h> #include <net/neighbour.h> #include <net/route.h> Loading Loading @@ -92,22 +91,12 @@ EXPORT_SYMBOL(rdma_addr_unregister_client); int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, const unsigned char *dst_dev_addr) { switch (dev->type) { case ARPHRD_INFINIBAND: dev_addr->dev_type = RDMA_NODE_IB_CA; break; case ARPHRD_ETHER: dev_addr->dev_type = RDMA_NODE_RNIC; break; default: return -EADDRNOTAVAIL; } dev_addr->dev_type = dev->type; memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); if (dst_dev_addr) memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); dev_addr->src_dev = dev; dev_addr->bound_dev_if = dev->ifindex; return 0; } EXPORT_SYMBOL(rdma_copy_addr); Loading @@ -117,6 +106,15 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) struct net_device *dev; int ret = -EADDRNOTAVAIL; if (dev_addr->bound_dev_if) { dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); if (!dev) return -ENODEV; ret = rdma_copy_addr(dev_addr, dev, NULL); dev_put(dev); return ret; } switch (addr->sa_family) { case AF_INET: dev = ip_dev_find(&init_net, Loading @@ -131,6 +129,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: read_lock(&dev_base_lock); for_each_netdev(&init_net, dev) { if (ipv6_chk_addr(&init_net, &((struct sockaddr_in6 *) addr)->sin6_addr, Loading @@ -139,6 +138,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) break; } } read_unlock(&dev_base_lock); break; #endif } Loading Loading @@ -176,46 +176,7 @@ static void queue_req(struct addr_req *req) mutex_unlock(&lock); } static void addr_send_arp(struct sockaddr *dst_in) { struct rtable *rt; struct flowi fl; memset(&fl, 0, sizeof fl); switch (dst_in->sa_family) { case AF_INET: fl.nl_u.ip4_u.daddr = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; if (ip_route_output_key(&init_net, &rt, &fl)) return; neigh_event_send(rt->u.dst.neighbour, NULL); ip_rt_put(rt); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct dst_entry *dst; fl.nl_u.ip6_u.daddr = ((struct sockaddr_in6 *) dst_in)->sin6_addr; dst = ip6_route_output(&init_net, NULL, &fl); if (!dst) return; neigh_event_send(dst->neighbour, NULL); dst_release(dst); break; } #endif } } static int addr4_resolve_remote(struct sockaddr_in *src_in, static int addr4_resolve(struct sockaddr_in *src_in, struct sockaddr_in *dst_in, struct rdma_dev_addr *addr) { Loading @@ -229,10 +190,22 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, memset(&fl, 0, sizeof fl); fl.nl_u.ip4_u.daddr = dst_ip; fl.nl_u.ip4_u.saddr = src_ip; fl.oif = addr->bound_dev_if; ret = ip_route_output_key(&init_net, &rt, &fl); if (ret) goto out; src_in->sin_family = AF_INET; src_in->sin_addr.s_addr = rt->rt_src; if (rt->idev->dev->flags & IFF_LOOPBACK) { ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); goto put; } /* If the device does ARP internally, return 'done' */ if (rt->idev->dev->flags & IFF_NOARP) { rdma_copy_addr(addr, rt->idev->dev, NULL); Loading @@ -240,19 +213,12 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, } neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); if (!neigh) { ret = -ENODATA; goto put; } if (!(neigh->nud_state & NUD_VALID)) { if (!neigh || !(neigh->nud_state & NUD_VALID)) { neigh_event_send(rt->u.dst.neighbour, NULL); ret = -ENODATA; if (neigh) goto release; } if (!src_ip) { src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = rt->rt_src; goto put; } ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); Loading @@ -265,36 +231,61 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int addr6_resolve_remote(struct sockaddr_in6 *src_in, static int addr6_resolve(struct sockaddr_in6 *src_in, struct sockaddr_in6 *dst_in, struct rdma_dev_addr *addr) { struct flowi fl; struct neighbour *neigh; struct dst_entry *dst; int ret = -ENODATA; int ret; memset(&fl, 0, sizeof fl); fl.nl_u.ip6_u.daddr = dst_in->sin6_addr; fl.nl_u.ip6_u.saddr = src_in->sin6_addr; ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr); ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr); fl.oif = addr->bound_dev_if; dst = ip6_route_output(&init_net, NULL, &fl); if (!dst) return ret; if ((ret = dst->error)) goto put; if (ipv6_addr_any(&fl.fl6_src)) { ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev, &fl.fl6_dst, 0, &fl.fl6_src); if (ret) goto put; src_in->sin6_family = AF_INET6; ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src); } if (dst->dev->flags & IFF_LOOPBACK) { ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); goto put; } /* If the device does ARP internally, return 'done' */ if (dst->dev->flags & IFF_NOARP) { ret = rdma_copy_addr(addr, dst->dev, NULL); } else { goto put; } neigh = dst->neighbour; if (neigh && (neigh->nud_state & NUD_VALID)) ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); if (!neigh || !(neigh->nud_state & NUD_VALID)) { neigh_event_send(dst->neighbour, NULL); ret = -ENODATA; goto put; } ret = rdma_copy_addr(addr, dst->dev, neigh->ha); put: dst_release(dst); return ret; } #else static int addr6_resolve_remote(struct sockaddr_in6 *src_in, static int addr6_resolve(struct sockaddr_in6 *src_in, struct sockaddr_in6 *dst_in, struct rdma_dev_addr *addr) { Loading @@ -302,15 +293,15 @@ static int addr6_resolve_remote(struct sockaddr_in6 *src_in, } #endif static int addr_resolve_remote(struct sockaddr *src_in, static int addr_resolve(struct sockaddr *src_in, struct sockaddr *dst_in, struct rdma_dev_addr *addr) { if (src_in->sa_family == AF_INET) { return addr4_resolve_remote((struct sockaddr_in *) src_in, return addr4_resolve((struct sockaddr_in *) src_in, (struct sockaddr_in *) dst_in, addr); } else return addr6_resolve_remote((struct sockaddr_in6 *) src_in, return addr6_resolve((struct sockaddr_in6 *) src_in, (struct sockaddr_in6 *) dst_in, addr); } Loading @@ -327,8 +318,7 @@ static void process_req(struct work_struct *work) if (req->status == -ENODATA) { src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; req->status = addr_resolve_remote(src_in, dst_in, req->addr); req->status = addr_resolve(src_in, dst_in, req->addr); if (req->status && time_after_eq(jiffies, req->timeout)) req->status = -ETIMEDOUT; else if (req->status == -ENODATA) Loading @@ -352,82 +342,6 @@ static void process_req(struct work_struct *work) } } static int addr_resolve_local(struct sockaddr *src_in, struct sockaddr *dst_in, struct rdma_dev_addr *addr) { struct net_device *dev; int ret; switch (dst_in->sa_family) { case AF_INET: { __be32 src_ip = ((struct sockaddr_in *) src_in)->sin_addr.s_addr; __be32 dst_ip = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; dev = ip_dev_find(&init_net, dst_ip); if (!dev) return -EADDRNOTAVAIL; if (ipv4_is_zeronet(src_ip)) { src_in->sa_family = dst_in->sa_family; ((struct sockaddr_in *) src_in)->sin_addr.s_addr = dst_ip; ret = rdma_copy_addr(addr, dev, dev->dev_addr); } else if (ipv4_is_loopback(src_ip)) { ret = rdma_translate_ip(dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } else { ret = rdma_translate_ip(src_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } dev_put(dev); break; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct in6_addr *a; for_each_netdev(&init_net, dev) if (ipv6_chk_addr(&init_net, &((struct sockaddr_in6 *) dst_in)->sin6_addr, dev, 1)) break; if (!dev) return -EADDRNOTAVAIL; a = &((struct sockaddr_in6 *) src_in)->sin6_addr; if (ipv6_addr_any(a)) { src_in->sa_family = dst_in->sa_family; ((struct sockaddr_in6 *) src_in)->sin6_addr = ((struct sockaddr_in6 *) dst_in)->sin6_addr; ret = rdma_copy_addr(addr, dev, dev->dev_addr); } else if (ipv6_addr_loopback(a)) { ret = rdma_translate_ip(dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } else { ret = rdma_translate_ip(src_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } break; } #endif default: ret = -EADDRNOTAVAIL; break; } return ret; } int rdma_resolve_ip(struct rdma_addr_client *client, struct sockaddr *src_addr, struct sockaddr *dst_addr, struct rdma_dev_addr *addr, int timeout_ms, Loading @@ -443,22 +357,28 @@ int rdma_resolve_ip(struct rdma_addr_client *client, if (!req) return -ENOMEM; if (src_addr) memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr)); memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr)); src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; if (src_addr) { if (src_addr->sa_family != dst_addr->sa_family) { ret = -EINVAL; goto err; } memcpy(src_in, src_addr, ip_addr_size(src_addr)); } else { src_in->sa_family = dst_addr->sa_family; } memcpy(dst_in, dst_addr, ip_addr_size(dst_addr)); req->addr = addr; req->callback = callback; req->context = context; req->client = client; atomic_inc(&client->refcount); src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; req->status = addr_resolve_local(src_in, dst_in, addr); if (req->status == -EADDRNOTAVAIL) req->status = addr_resolve_remote(src_in, dst_in, addr); req->status = addr_resolve(src_in, dst_in, addr); switch (req->status) { case 0: req->timeout = jiffies; Loading @@ -467,15 +387,16 @@ int rdma_resolve_ip(struct rdma_addr_client *client, case -ENODATA: req->timeout = msecs_to_jiffies(timeout_ms) + jiffies; queue_req(req); addr_send_arp(dst_in); break; default: ret = req->status; atomic_dec(&client->refcount); kfree(req); break; goto err; } return ret; err: kfree(req); return ret; } EXPORT_SYMBOL(rdma_resolve_ip); Loading drivers/infiniband/core/cma.c +83 −50 Original line number Diff line number Diff line Loading @@ -330,17 +330,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) union ib_gid gid; int ret = -ENODEV; switch (rdma_node_get_transport(dev_addr->dev_type)) { case RDMA_TRANSPORT_IB: ib_addr_get_sgid(dev_addr, &gid); break; case RDMA_TRANSPORT_IWARP: iw_addr_get_sgid(dev_addr, &gid); break; default: return -ENODEV; } rdma_addr_get_sgid(dev_addr, &gid); list_for_each_entry(cma_dev, &dev_list, list) { ret = ib_find_cached_gid(cma_dev->device, &gid, &id_priv->id.port_num, NULL); Loading Loading @@ -1032,11 +1022,17 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, if (rt->num_paths == 2) rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, &id->route.addr.dev_addr); if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) { rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND; rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey); } else { ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr, &rt->addr.dev_addr); if (ret) goto destroy_id; } rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = CMA_CONNECT; Loading Loading @@ -1071,10 +1067,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, cma_save_net_info(&id->route.addr, &listen_id->route.addr, ip_ver, port, src, dst); if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, &id->route.addr.dev_addr); if (ret) goto err; } id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = CMA_CONNECT; Loading Loading @@ -1474,15 +1472,6 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv) mutex_unlock(&lock); } static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af) { struct sockaddr_storage addr_in; memset(&addr_in, 0, sizeof addr_in); addr_in.ss_family = af; return rdma_bind_addr(id, (struct sockaddr *) &addr_in); } int rdma_listen(struct rdma_cm_id *id, int backlog) { struct rdma_id_private *id_priv; Loading @@ -1490,7 +1479,8 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) id_priv = container_of(id, struct rdma_id_private, id); if (id_priv->state == CMA_IDLE) { ret = cma_bind_any(id, AF_INET); ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET; ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr); if (ret) return ret; } Loading Loading @@ -1565,8 +1555,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, struct sockaddr_in6 *sin6; memset(&path_rec, 0, sizeof path_rec); ib_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); ib_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr)); path_rec.numb_path = 1; path_rec.reversible = 1; Loading Loading @@ -1781,7 +1771,11 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) if (ret) goto out; ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); id_priv->id.route.addr.dev_addr.dev_type = (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ? ARPHRD_INFINIBAND : ARPHRD_ETHER; rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); id_priv->id.port_num = p; cma_attach_to_dev(id_priv, cma_dev); Loading Loading @@ -1839,7 +1833,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, static int cma_resolve_loopback(struct rdma_id_private *id_priv) { struct cma_work *work; struct sockaddr_in *src_in, *dst_in; struct sockaddr *src, *dst; union ib_gid gid; int ret; Loading @@ -1853,14 +1847,19 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) goto err; } ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); if (cma_zero_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) { src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr; src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr; src = (struct sockaddr *) &id_priv->id.route.addr.src_addr; if (cma_zero_addr(src)) { dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr; if ((src->sa_family = dst->sa_family) == AF_INET) { ((struct sockaddr_in *) src)->sin_addr.s_addr = ((struct sockaddr_in *) dst)->sin_addr.s_addr; } else { ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr, &((struct sockaddr_in6 *) dst)->sin6_addr); } } work->id = id_priv; Loading @@ -1878,10 +1877,14 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, struct sockaddr *dst_addr) { if (src_addr && src_addr->sa_family) 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) { ((struct sockaddr_in6 *) src_addr)->sin6_scope_id = ((struct sockaddr_in6 *) dst_addr)->sin6_scope_id; } } return rdma_bind_addr(id, src_addr); else return cma_bind_any(id, dst_addr->sa_family); } int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, Loading Loading @@ -2077,6 +2080,25 @@ static int cma_get_port(struct rdma_id_private *id_priv) return ret; } static int cma_check_linklocal(struct rdma_dev_addr *dev_addr, struct sockaddr *addr) { #if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; if (addr->sa_family != AF_INET6) return 0; sin6 = (struct sockaddr_in6 *) addr; if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) && !sin6->sin6_scope_id) return -EINVAL; dev_addr->bound_dev_if = sin6->sin6_scope_id; #endif return 0; } int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) { struct rdma_id_private *id_priv; Loading @@ -2089,7 +2111,13 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) return -EINVAL; if (!cma_any_addr(addr)) { ret = cma_check_linklocal(&id->route.addr.dev_addr, addr); if (ret) goto err1; if (cma_loopback_addr(addr)) { ret = cma_bind_loopback(id_priv); } else if (!cma_zero_addr(addr)) { ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); if (ret) goto err1; Loading @@ -2108,7 +2136,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) return 0; err2: if (!cma_any_addr(addr)) { if (id_priv->cma_dev) { mutex_lock(&lock); cma_detach_from_dev(id_priv); mutex_unlock(&lock); Loading Loading @@ -2687,10 +2715,15 @@ static void cma_set_mgid(struct rdma_id_private *id_priv, if (cma_any_addr(addr)) { memset(mgid, 0, sizeof *mgid); } else if ((addr->sa_family == AF_INET6) && ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) == ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFFF0FFFF) == 0xFF10A01B)) { /* IPv6 address is an SA assigned MGID. */ memcpy(mgid, &sin6->sin6_addr, sizeof *mgid); } else if ((addr->sa_family == AF_INET6)) { ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map); if (id_priv->id.ps == RDMA_PS_UDP) mc_map[7] = 0x01; /* Use RDMA CM signature */ *mgid = *(union ib_gid *) (mc_map + 4); } else { ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map); if (id_priv->id.ps == RDMA_PS_UDP) Loading @@ -2716,7 +2749,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv, cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid); if (id_priv->id.ps == RDMA_PS_UDP) rec.qkey = cpu_to_be32(RDMA_UDP_QKEY); ib_addr_get_sgid(dev_addr, &rec.port_gid); rdma_addr_get_sgid(dev_addr, &rec.port_gid); rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); rec.join_state = 1; Loading Loading @@ -2815,7 +2848,7 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id dev_addr = &id_priv->id.route.addr.dev_addr; if ((dev_addr->src_dev == ndev) && if ((dev_addr->bound_dev_if == ndev->ifindex) && memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) { printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n", ndev->name, &id_priv->id); Loading drivers/infiniband/core/sa_query.c +6 −0 Original line number Diff line number Diff line Loading @@ -604,6 +604,12 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) return ret ? ret : id; } void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec) { ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), attribute, rec); } EXPORT_SYMBOL(ib_sa_unpack_path); static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, int status, struct ib_sa_mad *mad) Loading drivers/infiniband/core/ucma.c +53 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <rdma/rdma_user_cm.h> #include <rdma/ib_marshall.h> #include <rdma/rdma_cm.h> #include <rdma/rdma_cm_ib.h> MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); Loading Loading @@ -562,9 +563,9 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp, switch (route->num_paths) { case 0: dev_addr = &route->addr.dev_addr; ib_addr_get_dgid(dev_addr, rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid); ib_addr_get_sgid(dev_addr, rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid); resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); break; Loading Loading @@ -812,6 +813,51 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname, return ret; } static int ucma_set_ib_path(struct ucma_context *ctx, struct ib_path_rec_data *path_data, size_t optlen) { struct ib_sa_path_rec sa_path; struct rdma_cm_event event; int ret; if (optlen % sizeof(*path_data)) return -EINVAL; for (; optlen; optlen -= sizeof(*path_data), path_data++) { if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY | IB_PATH_BIDIRECTIONAL)) break; } if (!optlen) return -EINVAL; ib_sa_unpack_path(path_data->path_rec, &sa_path); ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1); if (ret) return ret; memset(&event, 0, sizeof event); event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; return ucma_event_handler(ctx->cm_id, &event); } static int ucma_set_option_ib(struct ucma_context *ctx, int optname, void *optval, size_t optlen) { int ret; switch (optname) { case RDMA_OPTION_IB_PATH: ret = ucma_set_ib_path(ctx, optval, optlen); break; default: ret = -ENOSYS; } return ret; } static int ucma_set_option_level(struct ucma_context *ctx, int level, int optname, void *optval, size_t optlen) { Loading @@ -821,6 +867,9 @@ static int ucma_set_option_level(struct ucma_context *ctx, int level, case RDMA_OPTION_ID: ret = ucma_set_option_id(ctx, optname, optval, optlen); break; case RDMA_OPTION_IB: ret = ucma_set_option_ib(ctx, optname, optval, optlen); break; default: ret = -ENOSYS; } Loading Loading
Documentation/infiniband/ipoib.txt +5 −5 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ Datagram vs Connected modes fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes. In connected mode, the IB RC (Reliable Connected) transport is used. Connected mode is to takes advantage of the connected nature of the IB transport and allows an MTU up to the maximal IP packet size of 64K, which reduces the number of IP packets needed for handling large UDP datagrams, TCP segments, etc and increases the performance for large messages. Connected mode takes advantage of the connected nature of the IB transport and allows an MTU up to the maximal IP packet size of 64K, which reduces the number of IP packets needed for handling large UDP datagrams, TCP segments, etc and increases the performance for large messages. In connected mode, the interface's UD QP is still used for multicast and communication with peers that don't support connected mode. In Loading
drivers/infiniband/core/addr.c +98 −177 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ #include <linux/mutex.h> #include <linux/inetdevice.h> #include <linux/workqueue.h> #include <linux/if_arp.h> #include <net/arp.h> #include <net/neighbour.h> #include <net/route.h> Loading Loading @@ -92,22 +91,12 @@ EXPORT_SYMBOL(rdma_addr_unregister_client); int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, const unsigned char *dst_dev_addr) { switch (dev->type) { case ARPHRD_INFINIBAND: dev_addr->dev_type = RDMA_NODE_IB_CA; break; case ARPHRD_ETHER: dev_addr->dev_type = RDMA_NODE_RNIC; break; default: return -EADDRNOTAVAIL; } dev_addr->dev_type = dev->type; memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); if (dst_dev_addr) memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); dev_addr->src_dev = dev; dev_addr->bound_dev_if = dev->ifindex; return 0; } EXPORT_SYMBOL(rdma_copy_addr); Loading @@ -117,6 +106,15 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) struct net_device *dev; int ret = -EADDRNOTAVAIL; if (dev_addr->bound_dev_if) { dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); if (!dev) return -ENODEV; ret = rdma_copy_addr(dev_addr, dev, NULL); dev_put(dev); return ret; } switch (addr->sa_family) { case AF_INET: dev = ip_dev_find(&init_net, Loading @@ -131,6 +129,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: read_lock(&dev_base_lock); for_each_netdev(&init_net, dev) { if (ipv6_chk_addr(&init_net, &((struct sockaddr_in6 *) addr)->sin6_addr, Loading @@ -139,6 +138,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) break; } } read_unlock(&dev_base_lock); break; #endif } Loading Loading @@ -176,46 +176,7 @@ static void queue_req(struct addr_req *req) mutex_unlock(&lock); } static void addr_send_arp(struct sockaddr *dst_in) { struct rtable *rt; struct flowi fl; memset(&fl, 0, sizeof fl); switch (dst_in->sa_family) { case AF_INET: fl.nl_u.ip4_u.daddr = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; if (ip_route_output_key(&init_net, &rt, &fl)) return; neigh_event_send(rt->u.dst.neighbour, NULL); ip_rt_put(rt); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct dst_entry *dst; fl.nl_u.ip6_u.daddr = ((struct sockaddr_in6 *) dst_in)->sin6_addr; dst = ip6_route_output(&init_net, NULL, &fl); if (!dst) return; neigh_event_send(dst->neighbour, NULL); dst_release(dst); break; } #endif } } static int addr4_resolve_remote(struct sockaddr_in *src_in, static int addr4_resolve(struct sockaddr_in *src_in, struct sockaddr_in *dst_in, struct rdma_dev_addr *addr) { Loading @@ -229,10 +190,22 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, memset(&fl, 0, sizeof fl); fl.nl_u.ip4_u.daddr = dst_ip; fl.nl_u.ip4_u.saddr = src_ip; fl.oif = addr->bound_dev_if; ret = ip_route_output_key(&init_net, &rt, &fl); if (ret) goto out; src_in->sin_family = AF_INET; src_in->sin_addr.s_addr = rt->rt_src; if (rt->idev->dev->flags & IFF_LOOPBACK) { ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); goto put; } /* If the device does ARP internally, return 'done' */ if (rt->idev->dev->flags & IFF_NOARP) { rdma_copy_addr(addr, rt->idev->dev, NULL); Loading @@ -240,19 +213,12 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, } neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); if (!neigh) { ret = -ENODATA; goto put; } if (!(neigh->nud_state & NUD_VALID)) { if (!neigh || !(neigh->nud_state & NUD_VALID)) { neigh_event_send(rt->u.dst.neighbour, NULL); ret = -ENODATA; if (neigh) goto release; } if (!src_ip) { src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = rt->rt_src; goto put; } ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); Loading @@ -265,36 +231,61 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in, } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int addr6_resolve_remote(struct sockaddr_in6 *src_in, static int addr6_resolve(struct sockaddr_in6 *src_in, struct sockaddr_in6 *dst_in, struct rdma_dev_addr *addr) { struct flowi fl; struct neighbour *neigh; struct dst_entry *dst; int ret = -ENODATA; int ret; memset(&fl, 0, sizeof fl); fl.nl_u.ip6_u.daddr = dst_in->sin6_addr; fl.nl_u.ip6_u.saddr = src_in->sin6_addr; ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr); ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr); fl.oif = addr->bound_dev_if; dst = ip6_route_output(&init_net, NULL, &fl); if (!dst) return ret; if ((ret = dst->error)) goto put; if (ipv6_addr_any(&fl.fl6_src)) { ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev, &fl.fl6_dst, 0, &fl.fl6_src); if (ret) goto put; src_in->sin6_family = AF_INET6; ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src); } if (dst->dev->flags & IFF_LOOPBACK) { ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); goto put; } /* If the device does ARP internally, return 'done' */ if (dst->dev->flags & IFF_NOARP) { ret = rdma_copy_addr(addr, dst->dev, NULL); } else { goto put; } neigh = dst->neighbour; if (neigh && (neigh->nud_state & NUD_VALID)) ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); if (!neigh || !(neigh->nud_state & NUD_VALID)) { neigh_event_send(dst->neighbour, NULL); ret = -ENODATA; goto put; } ret = rdma_copy_addr(addr, dst->dev, neigh->ha); put: dst_release(dst); return ret; } #else static int addr6_resolve_remote(struct sockaddr_in6 *src_in, static int addr6_resolve(struct sockaddr_in6 *src_in, struct sockaddr_in6 *dst_in, struct rdma_dev_addr *addr) { Loading @@ -302,15 +293,15 @@ static int addr6_resolve_remote(struct sockaddr_in6 *src_in, } #endif static int addr_resolve_remote(struct sockaddr *src_in, static int addr_resolve(struct sockaddr *src_in, struct sockaddr *dst_in, struct rdma_dev_addr *addr) { if (src_in->sa_family == AF_INET) { return addr4_resolve_remote((struct sockaddr_in *) src_in, return addr4_resolve((struct sockaddr_in *) src_in, (struct sockaddr_in *) dst_in, addr); } else return addr6_resolve_remote((struct sockaddr_in6 *) src_in, return addr6_resolve((struct sockaddr_in6 *) src_in, (struct sockaddr_in6 *) dst_in, addr); } Loading @@ -327,8 +318,7 @@ static void process_req(struct work_struct *work) if (req->status == -ENODATA) { src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; req->status = addr_resolve_remote(src_in, dst_in, req->addr); req->status = addr_resolve(src_in, dst_in, req->addr); if (req->status && time_after_eq(jiffies, req->timeout)) req->status = -ETIMEDOUT; else if (req->status == -ENODATA) Loading @@ -352,82 +342,6 @@ static void process_req(struct work_struct *work) } } static int addr_resolve_local(struct sockaddr *src_in, struct sockaddr *dst_in, struct rdma_dev_addr *addr) { struct net_device *dev; int ret; switch (dst_in->sa_family) { case AF_INET: { __be32 src_ip = ((struct sockaddr_in *) src_in)->sin_addr.s_addr; __be32 dst_ip = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr; dev = ip_dev_find(&init_net, dst_ip); if (!dev) return -EADDRNOTAVAIL; if (ipv4_is_zeronet(src_ip)) { src_in->sa_family = dst_in->sa_family; ((struct sockaddr_in *) src_in)->sin_addr.s_addr = dst_ip; ret = rdma_copy_addr(addr, dev, dev->dev_addr); } else if (ipv4_is_loopback(src_ip)) { ret = rdma_translate_ip(dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } else { ret = rdma_translate_ip(src_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } dev_put(dev); break; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct in6_addr *a; for_each_netdev(&init_net, dev) if (ipv6_chk_addr(&init_net, &((struct sockaddr_in6 *) dst_in)->sin6_addr, dev, 1)) break; if (!dev) return -EADDRNOTAVAIL; a = &((struct sockaddr_in6 *) src_in)->sin6_addr; if (ipv6_addr_any(a)) { src_in->sa_family = dst_in->sa_family; ((struct sockaddr_in6 *) src_in)->sin6_addr = ((struct sockaddr_in6 *) dst_in)->sin6_addr; ret = rdma_copy_addr(addr, dev, dev->dev_addr); } else if (ipv6_addr_loopback(a)) { ret = rdma_translate_ip(dst_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } else { ret = rdma_translate_ip(src_in, addr); if (!ret) memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); } break; } #endif default: ret = -EADDRNOTAVAIL; break; } return ret; } int rdma_resolve_ip(struct rdma_addr_client *client, struct sockaddr *src_addr, struct sockaddr *dst_addr, struct rdma_dev_addr *addr, int timeout_ms, Loading @@ -443,22 +357,28 @@ int rdma_resolve_ip(struct rdma_addr_client *client, if (!req) return -ENOMEM; if (src_addr) memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr)); memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr)); src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; if (src_addr) { if (src_addr->sa_family != dst_addr->sa_family) { ret = -EINVAL; goto err; } memcpy(src_in, src_addr, ip_addr_size(src_addr)); } else { src_in->sa_family = dst_addr->sa_family; } memcpy(dst_in, dst_addr, ip_addr_size(dst_addr)); req->addr = addr; req->callback = callback; req->context = context; req->client = client; atomic_inc(&client->refcount); src_in = (struct sockaddr *) &req->src_addr; dst_in = (struct sockaddr *) &req->dst_addr; req->status = addr_resolve_local(src_in, dst_in, addr); if (req->status == -EADDRNOTAVAIL) req->status = addr_resolve_remote(src_in, dst_in, addr); req->status = addr_resolve(src_in, dst_in, addr); switch (req->status) { case 0: req->timeout = jiffies; Loading @@ -467,15 +387,16 @@ int rdma_resolve_ip(struct rdma_addr_client *client, case -ENODATA: req->timeout = msecs_to_jiffies(timeout_ms) + jiffies; queue_req(req); addr_send_arp(dst_in); break; default: ret = req->status; atomic_dec(&client->refcount); kfree(req); break; goto err; } return ret; err: kfree(req); return ret; } EXPORT_SYMBOL(rdma_resolve_ip); Loading
drivers/infiniband/core/cma.c +83 −50 Original line number Diff line number Diff line Loading @@ -330,17 +330,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) union ib_gid gid; int ret = -ENODEV; switch (rdma_node_get_transport(dev_addr->dev_type)) { case RDMA_TRANSPORT_IB: ib_addr_get_sgid(dev_addr, &gid); break; case RDMA_TRANSPORT_IWARP: iw_addr_get_sgid(dev_addr, &gid); break; default: return -ENODEV; } rdma_addr_get_sgid(dev_addr, &gid); list_for_each_entry(cma_dev, &dev_list, list) { ret = ib_find_cached_gid(cma_dev->device, &gid, &id_priv->id.port_num, NULL); Loading Loading @@ -1032,11 +1022,17 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, if (rt->num_paths == 2) rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, &id->route.addr.dev_addr); if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) { rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND; rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey); } else { ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr, &rt->addr.dev_addr); if (ret) goto destroy_id; } rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = CMA_CONNECT; Loading Loading @@ -1071,10 +1067,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, cma_save_net_info(&id->route.addr, &listen_id->route.addr, ip_ver, port, src, dst); if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, &id->route.addr.dev_addr); if (ret) goto err; } id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = CMA_CONNECT; Loading Loading @@ -1474,15 +1472,6 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv) mutex_unlock(&lock); } static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af) { struct sockaddr_storage addr_in; memset(&addr_in, 0, sizeof addr_in); addr_in.ss_family = af; return rdma_bind_addr(id, (struct sockaddr *) &addr_in); } int rdma_listen(struct rdma_cm_id *id, int backlog) { struct rdma_id_private *id_priv; Loading @@ -1490,7 +1479,8 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) id_priv = container_of(id, struct rdma_id_private, id); if (id_priv->state == CMA_IDLE) { ret = cma_bind_any(id, AF_INET); ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET; ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr); if (ret) return ret; } Loading Loading @@ -1565,8 +1555,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, struct sockaddr_in6 *sin6; memset(&path_rec, 0, sizeof path_rec); ib_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); ib_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr)); path_rec.numb_path = 1; path_rec.reversible = 1; Loading Loading @@ -1781,7 +1771,11 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) if (ret) goto out; ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); id_priv->id.route.addr.dev_addr.dev_type = (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ? ARPHRD_INFINIBAND : ARPHRD_ETHER; rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); id_priv->id.port_num = p; cma_attach_to_dev(id_priv, cma_dev); Loading Loading @@ -1839,7 +1833,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, static int cma_resolve_loopback(struct rdma_id_private *id_priv) { struct cma_work *work; struct sockaddr_in *src_in, *dst_in; struct sockaddr *src, *dst; union ib_gid gid; int ret; Loading @@ -1853,14 +1847,19 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) goto err; } ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); if (cma_zero_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) { src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr; src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr; src = (struct sockaddr *) &id_priv->id.route.addr.src_addr; if (cma_zero_addr(src)) { dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr; if ((src->sa_family = dst->sa_family) == AF_INET) { ((struct sockaddr_in *) src)->sin_addr.s_addr = ((struct sockaddr_in *) dst)->sin_addr.s_addr; } else { ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr, &((struct sockaddr_in6 *) dst)->sin6_addr); } } work->id = id_priv; Loading @@ -1878,10 +1877,14 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, struct sockaddr *dst_addr) { if (src_addr && src_addr->sa_family) 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) { ((struct sockaddr_in6 *) src_addr)->sin6_scope_id = ((struct sockaddr_in6 *) dst_addr)->sin6_scope_id; } } return rdma_bind_addr(id, src_addr); else return cma_bind_any(id, dst_addr->sa_family); } int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, Loading Loading @@ -2077,6 +2080,25 @@ static int cma_get_port(struct rdma_id_private *id_priv) return ret; } static int cma_check_linklocal(struct rdma_dev_addr *dev_addr, struct sockaddr *addr) { #if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; if (addr->sa_family != AF_INET6) return 0; sin6 = (struct sockaddr_in6 *) addr; if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) && !sin6->sin6_scope_id) return -EINVAL; dev_addr->bound_dev_if = sin6->sin6_scope_id; #endif return 0; } int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) { struct rdma_id_private *id_priv; Loading @@ -2089,7 +2111,13 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) return -EINVAL; if (!cma_any_addr(addr)) { ret = cma_check_linklocal(&id->route.addr.dev_addr, addr); if (ret) goto err1; if (cma_loopback_addr(addr)) { ret = cma_bind_loopback(id_priv); } else if (!cma_zero_addr(addr)) { ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); if (ret) goto err1; Loading @@ -2108,7 +2136,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) return 0; err2: if (!cma_any_addr(addr)) { if (id_priv->cma_dev) { mutex_lock(&lock); cma_detach_from_dev(id_priv); mutex_unlock(&lock); Loading Loading @@ -2687,10 +2715,15 @@ static void cma_set_mgid(struct rdma_id_private *id_priv, if (cma_any_addr(addr)) { memset(mgid, 0, sizeof *mgid); } else if ((addr->sa_family == AF_INET6) && ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) == ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFFF0FFFF) == 0xFF10A01B)) { /* IPv6 address is an SA assigned MGID. */ memcpy(mgid, &sin6->sin6_addr, sizeof *mgid); } else if ((addr->sa_family == AF_INET6)) { ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map); if (id_priv->id.ps == RDMA_PS_UDP) mc_map[7] = 0x01; /* Use RDMA CM signature */ *mgid = *(union ib_gid *) (mc_map + 4); } else { ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map); if (id_priv->id.ps == RDMA_PS_UDP) Loading @@ -2716,7 +2749,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv, cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid); if (id_priv->id.ps == RDMA_PS_UDP) rec.qkey = cpu_to_be32(RDMA_UDP_QKEY); ib_addr_get_sgid(dev_addr, &rec.port_gid); rdma_addr_get_sgid(dev_addr, &rec.port_gid); rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); rec.join_state = 1; Loading Loading @@ -2815,7 +2848,7 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id dev_addr = &id_priv->id.route.addr.dev_addr; if ((dev_addr->src_dev == ndev) && if ((dev_addr->bound_dev_if == ndev->ifindex) && memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) { printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n", ndev->name, &id_priv->id); Loading
drivers/infiniband/core/sa_query.c +6 −0 Original line number Diff line number Diff line Loading @@ -604,6 +604,12 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) return ret ? ret : id; } void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec) { ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), attribute, rec); } EXPORT_SYMBOL(ib_sa_unpack_path); static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, int status, struct ib_sa_mad *mad) Loading
drivers/infiniband/core/ucma.c +53 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <rdma/rdma_user_cm.h> #include <rdma/ib_marshall.h> #include <rdma/rdma_cm.h> #include <rdma/rdma_cm_ib.h> MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); Loading Loading @@ -562,9 +563,9 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp, switch (route->num_paths) { case 0: dev_addr = &route->addr.dev_addr; ib_addr_get_dgid(dev_addr, rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid); ib_addr_get_sgid(dev_addr, rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid); resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); break; Loading Loading @@ -812,6 +813,51 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname, return ret; } static int ucma_set_ib_path(struct ucma_context *ctx, struct ib_path_rec_data *path_data, size_t optlen) { struct ib_sa_path_rec sa_path; struct rdma_cm_event event; int ret; if (optlen % sizeof(*path_data)) return -EINVAL; for (; optlen; optlen -= sizeof(*path_data), path_data++) { if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY | IB_PATH_BIDIRECTIONAL)) break; } if (!optlen) return -EINVAL; ib_sa_unpack_path(path_data->path_rec, &sa_path); ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1); if (ret) return ret; memset(&event, 0, sizeof event); event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; return ucma_event_handler(ctx->cm_id, &event); } static int ucma_set_option_ib(struct ucma_context *ctx, int optname, void *optval, size_t optlen) { int ret; switch (optname) { case RDMA_OPTION_IB_PATH: ret = ucma_set_ib_path(ctx, optval, optlen); break; default: ret = -ENOSYS; } return ret; } static int ucma_set_option_level(struct ucma_context *ctx, int level, int optname, void *optval, size_t optlen) { Loading @@ -821,6 +867,9 @@ static int ucma_set_option_level(struct ucma_context *ctx, int level, case RDMA_OPTION_ID: ret = ucma_set_option_id(ctx, optname, optval, optlen); break; case RDMA_OPTION_IB: ret = ucma_set_option_ib(ctx, optname, optval, optlen); break; default: ret = -ENOSYS; } Loading