addr.c revision 234183
192108Sphk/*
292108Sphk * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
392108Sphk * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
492108Sphk * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
592108Sphk * Copyright (c) 2005 Intel Corporation.  All rights reserved.
692108Sphk *
792108Sphk * This software is available to you under a choice of one of two
892108Sphk * licenses.  You may choose to be licensed under the terms of the GNU
992108Sphk * General Public License (GPL) Version 2, available from the file
1092108Sphk * COPYING in the main directory of this source tree, or the
1192108Sphk * OpenIB.org BSD license below:
1292108Sphk *
1392108Sphk *     Redistribution and use in source and binary forms, with or
1492108Sphk *     without modification, are permitted provided that the following
1592108Sphk *     conditions are met:
1692108Sphk *
1792108Sphk *      - Redistributions of source code must retain the above
1892108Sphk *        copyright notice, this list of conditions and the following
1992108Sphk *        disclaimer.
2092108Sphk *
2192108Sphk *      - Redistributions in binary form must reproduce the above
2292108Sphk *        copyright notice, this list of conditions and the following
2392108Sphk *        disclaimer in the documentation and/or other materials
2492108Sphk *        provided with the distribution.
2592108Sphk *
2692108Sphk * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2792108Sphk * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2892108Sphk * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2992108Sphk * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3092108Sphk * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3192108Sphk * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3292108Sphk * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3392108Sphk * SOFTWARE.
3492108Sphk */
3592108Sphk
3692108Sphk#include <linux/mutex.h>
3792108Sphk#include <linux/inetdevice.h>
3892108Sphk#include <linux/workqueue.h>
3992108Sphk#include <net/arp.h>
4092108Sphk#include <net/neighbour.h>
4192108Sphk#include <net/route.h>
4292108Sphk#include <net/netevent.h>
4392108Sphk#include <net/addrconf.h>
4492108Sphk#include <net/ip6_route.h>
4592108Sphk#include <rdma/ib_addr.h>
4692108Sphk
4792108SphkMODULE_AUTHOR("Sean Hefty");
4892108SphkMODULE_DESCRIPTION("IB Address Translation");
4992108SphkMODULE_LICENSE("Dual BSD/GPL");
5092108Sphk
5195323Sphkstruct addr_req {
5295038Sphk	struct list_head list;
5392108Sphk	struct sockaddr_storage src_addr;
5492108Sphk	struct sockaddr_storage dst_addr;
5592108Sphk	struct rdma_dev_addr *addr;
5692108Sphk	struct rdma_addr_client *client;
5792108Sphk	void *context;
5892108Sphk	void (*callback)(int status, struct sockaddr *src_addr,
5992108Sphk			 struct rdma_dev_addr *addr, void *context);
6092108Sphk	unsigned long timeout;
6192108Sphk	int status;
6292108Sphk};
6392108Sphk
6492108Sphkstatic void process_req(struct work_struct *work);
6592108Sphk
6692108Sphkstatic DEFINE_MUTEX(lock);
6792108Sphkstatic LIST_HEAD(req_list);
6892108Sphkstatic struct delayed_work work;
6992108Sphkstatic struct workqueue_struct *addr_wq;
7092108Sphk
7192108Sphkvoid rdma_addr_register_client(struct rdma_addr_client *client)
7292108Sphk{
7392108Sphk	atomic_set(&client->refcount, 1);
7492108Sphk	init_completion(&client->comp);
7592108Sphk}
7692108SphkEXPORT_SYMBOL(rdma_addr_register_client);
7792108Sphk
7892108Sphkstatic inline void put_client(struct rdma_addr_client *client)
7992108Sphk{
8092108Sphk	if (atomic_dec_and_test(&client->refcount))
8193248Sphk		complete(&client->comp);
8297075Sphk}
8392108Sphk
8492108Sphkvoid rdma_addr_unregister_client(struct rdma_addr_client *client)
8593248Sphk{
8692108Sphk	put_client(client);
8792108Sphk	wait_for_completion(&client->comp);
8892108Sphk}
8992108SphkEXPORT_SYMBOL(rdma_addr_unregister_client);
9092108Sphk
9192108Sphk#ifdef __linux__
9292108Sphkint rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
9392108Sphk		     const unsigned char *dst_dev_addr)
9492108Sphk{
9592108Sphk	dev_addr->dev_type = dev->type;
9692108Sphk	memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
9792108Sphk	memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
9892108Sphk	if (dst_dev_addr)
9992108Sphk		memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
10092108Sphk	dev_addr->bound_dev_if = dev->ifindex;
10193248Sphk	return 0;
10292108Sphk}
10392108Sphk#else
10492108Sphkint rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct ifnet *dev,
10592108Sphk		     const unsigned char *dst_dev_addr)
10692108Sphk{
10792108Sphk	if (dev->if_type == IFT_INFINIBAND)
10892108Sphk		dev_addr->dev_type = ARPHRD_INFINIBAND;
10992108Sphk	else if (dev->if_type == IFT_ETHER)
11092108Sphk		dev_addr->dev_type = ARPHRD_ETHER;
11192108Sphk	else
11292108Sphk		dev_addr->dev_type = 0;
11392108Sphk	memcpy(dev_addr->src_dev_addr, IF_LLADDR(dev), dev->if_addrlen);
11492108Sphk	memcpy(dev_addr->broadcast, __DECONST(char *, dev->if_broadcastaddr),
11592108Sphk	    dev->if_addrlen);
11692108Sphk	if (dst_dev_addr)
11796987Sphk		memcpy(dev_addr->dst_dev_addr, dst_dev_addr, dev->if_addrlen);
11892108Sphk	dev_addr->bound_dev_if = dev->if_index;
11996987Sphk	return 0;
12092108Sphk}
12192108Sphk#endif
12292108SphkEXPORT_SYMBOL(rdma_copy_addr);
12392108Sphk
12492108Sphkint rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
12592108Sphk{
12692108Sphk	struct net_device *dev;
12793250Sphk	int ret = -EADDRNOTAVAIL;
12892108Sphk
12992108Sphk	if (dev_addr->bound_dev_if) {
13092108Sphk		dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
13192108Sphk		if (!dev)
13296987Sphk			return -ENODEV;
13392108Sphk		ret = rdma_copy_addr(dev_addr, dev, NULL);
13492108Sphk		dev_put(dev);
13592108Sphk		return ret;
13692108Sphk	}
13792108Sphk
13893248Sphk	switch (addr->sa_family) {
13992108Sphk#ifdef INET
14092108Sphk	case AF_INET:
14193776Sphk		dev = ip_dev_find(NULL,
14292108Sphk			((struct sockaddr_in *) addr)->sin_addr.s_addr);
14396987Sphk
14496987Sphk		if (!dev)
14596987Sphk			return ret;
14696987Sphk
14796987Sphk		ret = rdma_copy_addr(dev_addr, dev, NULL);
14896987Sphk		dev_put(dev);
14996987Sphk		break;
15092108Sphk#endif
15192108Sphk
15296987Sphk#if defined(INET6)
15392108Sphk	case AF_INET6:
15496987Sphk#ifdef __linux__
15596987Sphk		read_lock(&dev_base_lock);
15696987Sphk		for_each_netdev(&init_net, dev) {
15792108Sphk			if (ipv6_chk_addr(&init_net,
15892108Sphk					  &((struct sockaddr_in6 *) addr)->sin6_addr,
15992108Sphk					  dev, 1)) {
16092108Sphk				ret = rdma_copy_addr(dev_addr, dev, NULL);
16192108Sphk				break;
16292108Sphk			}
16392108Sphk		}
16492108Sphk		read_unlock(&dev_base_lock);
16592108Sphk#else
16692108Sphk		{
16792108Sphk			struct sockaddr_in6 *sin6;
16892108Sphk			struct ifaddr *ifa;
16992108Sphk			in_port_t port;
17092108Sphk
17192108Sphk			sin6 = (struct sockaddr_in6 *)addr;
17292108Sphk			port = sin6->sin6_port;
17392108Sphk			sin6->sin6_port = 0;
17492108Sphk			ifa = ifa_ifwithaddr(addr);
17592108Sphk			sin6->sin6_port = port;
17692479Sphk			if (ifa == NULL) {
17792108Sphk				ret = -ENODEV;
17892108Sphk				break;
17992108Sphk			}
18092108Sphk			ret = rdma_copy_addr(dev_addr, ifa->ifa_ifp, NULL);
18192108Sphk			ifa_free(ifa);
18292108Sphk			break;
18392108Sphk		}
18492479Sphk#endif
18592108Sphk		break;
18692108Sphk#endif
18792108Sphk	}
18892108Sphk	return ret;
18992108Sphk}
19092108SphkEXPORT_SYMBOL(rdma_translate_ip);
19192108Sphk
19292108Sphkstatic void set_timeout(unsigned long time)
19392108Sphk{
19492108Sphk	unsigned long delay;
19592108Sphk
19692108Sphk	cancel_delayed_work(&work);
19792108Sphk
19892108Sphk	delay = time - jiffies;
19992108Sphk	if ((long)delay <= 0)
20092108Sphk		delay = 1;
20192108Sphk
20292479Sphk	queue_delayed_work(addr_wq, &work, delay);
20392108Sphk}
20492108Sphk
20592108Sphkstatic void queue_req(struct addr_req *req)
20692108Sphk{
20792108Sphk	struct addr_req *temp_req;
20892108Sphk
20992108Sphk	mutex_lock(&lock);
21092479Sphk	list_for_each_entry_reverse(temp_req, &req_list, list) {
21192108Sphk		if (time_after_eq(req->timeout, temp_req->timeout))
21292108Sphk			break;
21392108Sphk	}
21492108Sphk
21592108Sphk	list_add(&req->list, &temp_req->list);
21692108Sphk
21792108Sphk	if (req_list.next == &req->list)
21895323Sphk		set_timeout(req->timeout);
21992108Sphk	mutex_unlock(&lock);
22095323Sphk}
22195038Sphk
22292108Sphk#ifdef __linux__
22395038Sphkstatic int addr4_resolve(struct sockaddr_in *src_in,
22492403Sphk			 struct sockaddr_in *dst_in,
22595323Sphk			 struct rdma_dev_addr *addr)
22692108Sphk{
22792108Sphk	__be32 src_ip = src_in->sin_addr.s_addr;
22892108Sphk	__be32 dst_ip = dst_in->sin_addr.s_addr;
22995323Sphk	struct flowi fl;
23095323Sphk	struct rtable *rt;
23192108Sphk	struct neighbour *neigh;
23292108Sphk	int ret;
23392479Sphk
23492403Sphk	memset(&fl, 0, sizeof fl);
23592698Sphk	fl.nl_u.ip4_u.daddr = dst_ip;
23692698Sphk	fl.nl_u.ip4_u.saddr = src_ip;
23792698Sphk	fl.oif = addr->bound_dev_if;
23893250Sphk
23992698Sphk	ret = ip_route_output_key(&init_net, &rt, &fl);
24092698Sphk	if (ret)
24193250Sphk		goto out;
24292698Sphk
24392698Sphk	src_in->sin_family = AF_INET;
24493250Sphk	src_in->sin_addr.s_addr = rt->rt_src;
24592698Sphk
24692698Sphk	if (rt->idev->dev->flags & IFF_LOOPBACK) {
24793250Sphk		ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
24892698Sphk		if (!ret)
24994287Sphk			memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
25094287Sphk		goto put;
25194287Sphk	}
25295038Sphk
25395038Sphk	/* If the device does ARP internally, return 'done' */
25495038Sphk	if (rt->idev->dev->flags & IFF_NOARP) {
25595038Sphk		rdma_copy_addr(addr, rt->idev->dev, NULL);
25695038Sphk		goto put;
25795038Sphk	}
25895038Sphk
25995038Sphk	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
26095038Sphk	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
26195038Sphk		neigh_event_send(rt->u.dst.neighbour, NULL);
26295038Sphk		ret = -ENODATA;
26395038Sphk		if (neigh)
26495038Sphk			goto release;
26595038Sphk		goto put;
26695323Sphk	}
26795323Sphk
26895323Sphk	ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
26995323Sphkrelease:
27095323Sphk	neigh_release(neigh);
27195323Sphkput:
27295323Sphk	ip_rt_put(rt);
27395323Sphkout:
27495323Sphk	return ret;
27595323Sphk}
27695323Sphk
27792698Sphk#if defined(INET6)
27892698Sphkstatic int addr6_resolve(struct sockaddr_in6 *src_in,
27992698Sphk			 struct sockaddr_in6 *dst_in,
28092698Sphk			 struct rdma_dev_addr *addr)
28192698Sphk{
28292698Sphk	struct flowi fl;
28392698Sphk	struct neighbour *neigh;
28492698Sphk	struct dst_entry *dst;
28593250Sphk	int ret;
28692698Sphk
28793250Sphk	memset(&fl, 0, sizeof fl);
28892698Sphk	ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr);
28992698Sphk	ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr);
29092698Sphk	fl.oif = addr->bound_dev_if;
29192403Sphk
29292408Sphk	dst = ip6_route_output(&init_net, NULL, &fl);
29392408Sphk	if ((ret = dst->error))
29497075Sphk		goto put;
29592408Sphk
29692108Sphk	if (ipv6_addr_any(&fl.fl6_src)) {
29792479Sphk		ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev,
29892403Sphk					 &fl.fl6_dst, 0, &fl.fl6_src);
29992403Sphk		if (ret)
30092403Sphk			goto put;
30192108Sphk
30292108Sphk		src_in->sin6_family = AF_INET6;
30392108Sphk		ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src);
30492108Sphk	}
30592108Sphk
30692108Sphk	if (dst->dev->flags & IFF_LOOPBACK) {
30792108Sphk		ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
30892108Sphk		if (!ret)
30992108Sphk			memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
31092108Sphk		goto put;
31192403Sphk	}
31292403Sphk
31392108Sphk	/* If the device does ARP internally, return 'done' */
31492108Sphk	if (dst->dev->flags & IFF_NOARP) {
31592108Sphk		ret = rdma_copy_addr(addr, dst->dev, NULL);
31692108Sphk		goto put;
31792108Sphk	}
31892108Sphk
31992108Sphk	neigh = dst->neighbour;
32092108Sphk	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
32192108Sphk		neigh_event_send(dst->neighbour, NULL);
32292108Sphk		ret = -ENODATA;
32392108Sphk		goto put;
32492108Sphk	}
32592108Sphk
32692108Sphk	ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
32793250Sphkput:
32892108Sphk	dst_release(dst);
32992108Sphk	return ret;
33092108Sphk}
33192108Sphk#else
33292108Sphkstatic int addr6_resolve(struct sockaddr_in6 *src_in,
33392108Sphk			 struct sockaddr_in6 *dst_in,
33492108Sphk			 struct rdma_dev_addr *addr)
33592108Sphk{
33692108Sphk	return -EADDRNOTAVAIL;
33792108Sphk}
33892108Sphk#endif
33992108Sphk
34092108Sphk#else
34192108Sphk#include <netinet/if_ether.h>
34292108Sphk
34392108Sphkstatic int addr_resolve(struct sockaddr *src_in,
34492108Sphk			struct sockaddr *dst_in,
34592108Sphk			struct rdma_dev_addr *addr)
34692108Sphk{
34792108Sphk	struct sockaddr_in *sin;
34892108Sphk	struct sockaddr_in6 *sin6;
34992108Sphk	struct ifaddr *ifa;
35092108Sphk	struct ifnet *ifp;
35192108Sphk#if defined(INET) || defined(INET6)
35292108Sphk	struct llentry *lle;
35392108Sphk#endif
35492108Sphk	struct rtentry *rte;
35592108Sphk	in_port_t port;
35692108Sphk	u_char edst[MAX_ADDR_LEN];
35792108Sphk	int multi;
35892108Sphk	int bcast;
35992108Sphk	int error;
36092108Sphk
36192108Sphk	/*
36292108Sphk	 * Determine whether the address is unicast, multicast, or broadcast
36392108Sphk	 * and whether the source interface is valid.
36492108Sphk	 */
36592108Sphk	multi = 0;
36692108Sphk	bcast = 0;
36792108Sphk	sin = NULL;
36892108Sphk	sin6 = NULL;
36992108Sphk	ifp = NULL;
37092108Sphk	rte = NULL;
37192108Sphk	switch (dst_in->sa_family) {
37292108Sphk#ifdef INET
37392108Sphk	case AF_INET:
37492108Sphk		sin = (struct sockaddr_in *)dst_in;
37592108Sphk		if (sin->sin_addr.s_addr == INADDR_BROADCAST)
37692108Sphk			bcast = 1;
37796987Sphk		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
37896987Sphk			multi = 1;
37996987Sphk		sin = (struct sockaddr_in *)src_in;
38096987Sphk		if (sin->sin_addr.s_addr != INADDR_ANY) {
38196987Sphk			/*
38296987Sphk			 * Address comparison fails if the port is set
38396987Sphk			 * cache it here to be restored later.
38496987Sphk			 */
38596987Sphk			port = sin->sin_port;
38696987Sphk			sin->sin_port = 0;
38792108Sphk			memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
38892108Sphk		} else
38993250Sphk			src_in = NULL;
39092108Sphk		break;
39192108Sphk#endif
39292108Sphk#ifdef INET6
39392108Sphk	case AF_INET6:
39492108Sphk		sin6 = (struct sockaddr_in6 *)dst_in;
39592108Sphk		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
39692108Sphk			multi = 1;
39792108Sphk		sin6 = (struct sockaddr_in6 *)src_in;
39892108Sphk		if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
39992108Sphk			port = sin6->sin6_port;
40095038Sphk			sin6->sin6_port = 0;
40195038Sphk		} else
40296987Sphk			src_in = NULL;
40392108Sphk		break;
40492108Sphk#endif
40592108Sphk	default:
40692108Sphk		return -EINVAL;
40792108Sphk	}
40892108Sphk	/*
40992108Sphk	 * If we have a source address to use look it up first and verify
41092108Sphk	 * that it is a local interface.
41196987Sphk	 */
412	if (src_in) {
413		ifa = ifa_ifwithaddr(src_in);
414		if (sin)
415			sin->sin_port = port;
416		if (sin6)
417			sin6->sin6_port = port;
418		if (ifa == NULL)
419			return -ENETUNREACH;
420		ifp = ifa->ifa_ifp;
421		ifa_free(ifa);
422		if (bcast || multi)
423			goto mcast;
424	}
425	/*
426	 * Make sure the route exists and has a valid link.
427	 */
428	rte = rtalloc1(dst_in, 1, 0);
429	if (rte == NULL || rte->rt_ifp == NULL || !RT_LINK_IS_UP(rte->rt_ifp)) {
430		if (rte)
431			RTFREE_LOCKED(rte);
432		return -EHOSTUNREACH;
433	}
434	/*
435	 * If it's not multicast or broadcast and the route doesn't match the
436	 * requested interface return unreachable.  Otherwise fetch the
437	 * correct interface pointer and unlock the route.
438	 */
439	if (multi || bcast) {
440		if (ifp == NULL)
441			ifp = rte->rt_ifp;
442		RTFREE_LOCKED(rte);
443	} else if (ifp && ifp != rte->rt_ifp) {
444		RTFREE_LOCKED(rte);
445		return -ENETUNREACH;
446	} else {
447		if (ifp == NULL)
448			ifp = rte->rt_ifp;
449		RT_UNLOCK(rte);
450	}
451mcast:
452	if (bcast)
453		return rdma_copy_addr(addr, ifp, ifp->if_broadcastaddr);
454	if (multi) {
455		struct sockaddr *llsa;
456
457		error = ifp->if_resolvemulti(ifp, &llsa, dst_in);
458		if (error)
459			return -error;
460		error = rdma_copy_addr(addr, ifp,
461		    LLADDR((struct sockaddr_dl *)llsa));
462		free(llsa, M_IFMADDR);
463		return error;
464	}
465	/*
466	 * Resolve the link local address.
467	 */
468	switch (dst_in->sa_family) {
469#ifdef INET
470	case AF_INET:
471		error = arpresolve(ifp, rte, NULL, dst_in, edst, &lle);
472		break;
473#endif
474#ifdef INET6
475	case AF_INET6:
476		error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst, &lle);
477		break;
478#endif
479	default:
480		/* XXX: Shouldn't happen. */
481		error = -EINVAL;
482	}
483	RTFREE(rte);
484	if (error == 0)
485		return rdma_copy_addr(addr, ifp, edst);
486	if (error == EWOULDBLOCK)
487		return -ENODATA;
488	return -error;
489}
490
491#endif
492
493static void process_req(struct work_struct *work)
494{
495	struct addr_req *req, *temp_req;
496	struct sockaddr *src_in, *dst_in;
497	struct list_head done_list;
498
499	INIT_LIST_HEAD(&done_list);
500
501	mutex_lock(&lock);
502	list_for_each_entry_safe(req, temp_req, &req_list, list) {
503		if (req->status == -ENODATA) {
504			src_in = (struct sockaddr *) &req->src_addr;
505			dst_in = (struct sockaddr *) &req->dst_addr;
506			req->status = addr_resolve(src_in, dst_in, req->addr);
507			if (req->status && time_after_eq(jiffies, req->timeout))
508				req->status = -ETIMEDOUT;
509			else if (req->status == -ENODATA)
510				continue;
511		}
512		list_move_tail(&req->list, &done_list);
513	}
514
515	if (!list_empty(&req_list)) {
516		req = list_entry(req_list.next, struct addr_req, list);
517		set_timeout(req->timeout);
518	}
519	mutex_unlock(&lock);
520
521	list_for_each_entry_safe(req, temp_req, &done_list, list) {
522		list_del(&req->list);
523		req->callback(req->status, (struct sockaddr *) &req->src_addr,
524			req->addr, req->context);
525		put_client(req->client);
526		kfree(req);
527	}
528}
529
530int rdma_resolve_ip(struct rdma_addr_client *client,
531		    struct sockaddr *src_addr, struct sockaddr *dst_addr,
532		    struct rdma_dev_addr *addr, int timeout_ms,
533		    void (*callback)(int status, struct sockaddr *src_addr,
534				     struct rdma_dev_addr *addr, void *context),
535		    void *context)
536{
537	struct sockaddr *src_in, *dst_in;
538	struct addr_req *req;
539	int ret = 0;
540
541	req = kzalloc(sizeof *req, GFP_KERNEL);
542	if (!req)
543		return -ENOMEM;
544
545	src_in = (struct sockaddr *) &req->src_addr;
546	dst_in = (struct sockaddr *) &req->dst_addr;
547
548	if (src_addr) {
549		if (src_addr->sa_family != dst_addr->sa_family) {
550			ret = -EINVAL;
551			goto err;
552		}
553
554		memcpy(src_in, src_addr, ip_addr_size(src_addr));
555	} else {
556		src_in->sa_family = dst_addr->sa_family;
557	}
558
559	memcpy(dst_in, dst_addr, ip_addr_size(dst_addr));
560	req->addr = addr;
561	req->callback = callback;
562	req->context = context;
563	req->client = client;
564	atomic_inc(&client->refcount);
565
566	req->status = addr_resolve(src_in, dst_in, addr);
567	switch (req->status) {
568	case 0:
569		req->timeout = jiffies;
570		queue_req(req);
571		break;
572	case -ENODATA:
573		req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
574		queue_req(req);
575		break;
576	default:
577		ret = req->status;
578		atomic_dec(&client->refcount);
579		goto err;
580	}
581	return ret;
582err:
583	kfree(req);
584	return ret;
585}
586EXPORT_SYMBOL(rdma_resolve_ip);
587
588void rdma_addr_cancel(struct rdma_dev_addr *addr)
589{
590	struct addr_req *req, *temp_req;
591
592	mutex_lock(&lock);
593	list_for_each_entry_safe(req, temp_req, &req_list, list) {
594		if (req->addr == addr) {
595			req->status = -ECANCELED;
596			req->timeout = jiffies;
597			list_move(&req->list, &req_list);
598			set_timeout(req->timeout);
599			break;
600		}
601	}
602	mutex_unlock(&lock);
603}
604EXPORT_SYMBOL(rdma_addr_cancel);
605
606static int netevent_callback(struct notifier_block *self, unsigned long event,
607	void *ctx)
608{
609	if (event == NETEVENT_NEIGH_UPDATE) {
610#ifdef __linux__
611		struct neighbour *neigh = ctx;
612
613		if (neigh->nud_state & NUD_VALID) {
614			set_timeout(jiffies);
615		}
616#else
617		set_timeout(jiffies);
618#endif
619	}
620	return 0;
621}
622
623static struct notifier_block nb = {
624	.notifier_call = netevent_callback
625};
626
627static int addr_init(void)
628{
629	INIT_DELAYED_WORK(&work, process_req);
630	addr_wq = create_singlethread_workqueue("ib_addr");
631	if (!addr_wq)
632		return -ENOMEM;
633
634	register_netevent_notifier(&nb);
635	return 0;
636}
637
638static void addr_cleanup(void)
639{
640	unregister_netevent_notifier(&nb);
641	destroy_workqueue(addr_wq);
642}
643
644module_init(addr_init);
645module_exit(addr_cleanup);
646