IB/addr: Simplify resolving IPv4 addresses
Merge resolve local/remote address resolution into a single data flow to ensure consistent access and use of the local routing tables. Based on work from: David Wilder <dwilder@us.ibm.com> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Родитель
6f8372b69c
Коммит
923c100ef0
|
@ -184,17 +184,6 @@ static void addr_send_arp(struct sockaddr *dst_in)
|
|||
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:
|
||||
{
|
||||
|
@ -215,9 +204,9 @@ static void addr_send_arp(struct sockaddr *dst_in)
|
|||
}
|
||||
}
|
||||
|
||||
static int addr4_resolve_remote(struct sockaddr_in *src_in,
|
||||
struct sockaddr_in *dst_in,
|
||||
struct rdma_dev_addr *addr)
|
||||
static int addr4_resolve(struct sockaddr_in *src_in,
|
||||
struct sockaddr_in *dst_in,
|
||||
struct rdma_dev_addr *addr)
|
||||
{
|
||||
__be32 src_ip = src_in->sin_addr.s_addr;
|
||||
__be32 dst_ip = dst_in->sin_addr.s_addr;
|
||||
|
@ -235,6 +224,16 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in,
|
|||
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);
|
||||
|
@ -242,21 +241,14 @@ static int addr4_resolve_remote(struct sockaddr_in *src_in,
|
|||
}
|
||||
|
||||
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
|
||||
if (!neigh) {
|
||||
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
|
||||
neigh_event_send(rt->u.dst.neighbour, NULL);
|
||||
ret = -ENODATA;
|
||||
if (neigh)
|
||||
goto release;
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (!(neigh->nud_state & NUD_VALID)) {
|
||||
ret = -ENODATA;
|
||||
goto release;
|
||||
}
|
||||
|
||||
if (!src_ip) {
|
||||
src_in->sin_family = dst_in->sin_family;
|
||||
src_in->sin_addr.s_addr = rt->rt_src;
|
||||
}
|
||||
|
||||
ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
|
||||
release:
|
||||
neigh_release(neigh);
|
||||
|
@ -305,12 +297,12 @@ static int addr6_resolve_remote(struct sockaddr_in6 *src_in,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int addr_resolve_remote(struct sockaddr *src_in,
|
||||
struct sockaddr *dst_in,
|
||||
struct rdma_dev_addr *addr)
|
||||
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,
|
||||
|
@ -330,8 +322,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)
|
||||
|
@ -363,32 +354,6 @@ static int addr_resolve_local(struct sockaddr *src_in,
|
|||
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:
|
||||
{
|
||||
|
@ -473,7 +438,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
|
|||
|
||||
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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче