|
@@ -176,34 +176,6 @@ 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) {
|
|
|
-#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(struct sockaddr_in *src_in,
|
|
|
struct sockaddr_in *dst_in,
|
|
|
struct rdma_dev_addr *addr)
|
|
@@ -259,39 +231,63 @@ out:
|
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
|
-static int addr6_resolve_remote(struct sockaddr_in6 *src_in,
|
|
|
- struct sockaddr_in6 *dst_in,
|
|
|
- struct rdma_dev_addr *addr)
|
|
|
+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 {
|
|
|
- neigh = dst->neighbour;
|
|
|
- if (neigh && (neigh->nud_state & NUD_VALID))
|
|
|
- ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
|
|
|
+ goto put;
|
|
|
}
|
|
|
|
|
|
+ neigh = dst->neighbour;
|
|
|
+ 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,
|
|
|
- struct sockaddr_in6 *dst_in,
|
|
|
- struct rdma_dev_addr *addr)
|
|
|
+static int addr6_resolve(struct sockaddr_in6 *src_in,
|
|
|
+ struct sockaddr_in6 *dst_in,
|
|
|
+ struct rdma_dev_addr *addr)
|
|
|
{
|
|
|
return -EADDRNOTAVAIL;
|
|
|
}
|
|
@@ -305,7 +301,7 @@ static int addr_resolve(struct sockaddr *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);
|
|
|
}
|
|
|
|
|
@@ -346,60 +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) {
|
|
|
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
|
- case AF_INET6:
|
|
|
- {
|
|
|
- struct in6_addr *a;
|
|
|
-
|
|
|
- read_lock(&dev_base_lock);
|
|
|
- for_each_netdev(&init_net, dev)
|
|
|
- if (ipv6_chk_addr(&init_net,
|
|
|
- &((struct sockaddr_in6 *) dst_in)->sin6_addr,
|
|
|
- dev, 1))
|
|
|
- break;
|
|
|
-
|
|
|
- if (!dev) {
|
|
|
- read_unlock(&dev_base_lock);
|
|
|
- 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);
|
|
|
- }
|
|
|
- read_unlock(&dev_base_lock);
|
|
|
- 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,
|
|
@@ -436,10 +378,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
|
|
|
req->client = client;
|
|
|
atomic_inc(&client->refcount);
|
|
|
|
|
|
- req->status = addr_resolve_local(src_in, dst_in, addr);
|
|
|
- if (req->status == -EADDRNOTAVAIL)
|
|
|
- req->status = addr_resolve(src_in, dst_in, addr);
|
|
|
-
|
|
|
+ req->status = addr_resolve(src_in, dst_in, addr);
|
|
|
switch (req->status) {
|
|
|
case 0:
|
|
|
req->timeout = jiffies;
|
|
@@ -448,7 +387,6 @@ 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;
|