Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 923c100e authored by Sean Hefty's avatar Sean Hefty Committed by Roland Dreier
Browse files

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: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 6f8372b6
Loading
Loading
Loading
Loading
+23 −58
Original line number Diff line number Diff line
@@ -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,7 +204,7 @@ static void addr_send_arp(struct sockaddr *dst_in)
	}
}

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)
{
@@ -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,19 +241,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);
@@ -305,12 +297,12 @@ 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,
@@ -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: