xref: /src/sys/ofed/drivers/infiniband/core/ib_addr.c (revision 6780e684d49034610f82bea5d3bfb04d42e91628)
1 /*
2  * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
4  * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
5  * Copyright (c) 2005 Intel Corporation.  All rights reserved.
6  *
7  * This software is available to you under a choice of one of two
8  * licenses.  You may choose to be licensed under the terms of the GNU
9  * General Public License (GPL) Version 2, available from the file
10  * COPYING in the main directory of this source tree, or the
11  * OpenIB.org BSD license below:
12  *
13  *     Redistribution and use in source and binary forms, with or
14  *     without modification, are permitted provided that the following
15  *     conditions are met:
16  *
17  *      - Redistributions of source code must retain the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer.
20  *
21  *      - Redistributions in binary form must reproduce the above
22  *        copyright notice, this list of conditions and the following
23  *        disclaimer in the documentation and/or other materials
24  *        provided with the distribution.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33  * SOFTWARE.
34  */
35 
36 #include <linux/mutex.h>
37 #include <linux/inetdevice.h>
38 #include <linux/slab.h>
39 #include <linux/workqueue.h>
40 #include <linux/module.h>
41 #include <net/route.h>
42 #include <net/netevent.h>
43 #include <rdma/ib_addr.h>
44 #include <rdma/ib.h>
45 
46 #include <netinet/if_ether.h>
47 #include <netinet/ip_var.h>
48 #include <netinet6/scope6_var.h>
49 #include <netinet6/in6_pcb.h>
50 
51 #include "core_priv.h"
52 
53 struct addr_req {
54 	struct list_head list;
55 	struct sockaddr_storage src_addr;
56 	struct sockaddr_storage dst_addr;
57 	struct rdma_dev_addr *addr;
58 	struct rdma_addr_client *client;
59 	void *context;
60 	void (*callback)(int status, struct sockaddr *src_addr,
61 			 struct rdma_dev_addr *addr, void *context);
62 	unsigned long timeout;
63 	int status;
64 };
65 
66 static void process_req(struct work_struct *work);
67 
68 static DEFINE_MUTEX(lock);
69 static LIST_HEAD(req_list);
70 static DECLARE_DELAYED_WORK(work, process_req);
71 static struct workqueue_struct *addr_wq;
72 
73 int rdma_addr_size(struct sockaddr *addr)
74 {
75 	switch (addr->sa_family) {
76 	case AF_INET:
77 		return sizeof(struct sockaddr_in);
78 	case AF_INET6:
79 		return sizeof(struct sockaddr_in6);
80 	case AF_IB:
81 		return sizeof(struct sockaddr_ib);
82 	default:
83 		return 0;
84 	}
85 }
86 EXPORT_SYMBOL(rdma_addr_size);
87 
88 static struct rdma_addr_client self;
89 
90 void rdma_addr_register_client(struct rdma_addr_client *client)
91 {
92 	atomic_set(&client->refcount, 1);
93 	init_completion(&client->comp);
94 }
95 EXPORT_SYMBOL(rdma_addr_register_client);
96 
97 static inline void put_client(struct rdma_addr_client *client)
98 {
99 	if (atomic_dec_and_test(&client->refcount))
100 		complete(&client->comp);
101 }
102 
103 void rdma_addr_unregister_client(struct rdma_addr_client *client)
104 {
105 	put_client(client);
106 	wait_for_completion(&client->comp);
107 }
108 EXPORT_SYMBOL(rdma_addr_unregister_client);
109 
110 static inline void
111 rdma_copy_addr_sub(u8 *dst, const u8 *src, unsigned min, unsigned max)
112 {
113 	if (min > max)
114 		min = max;
115 	memcpy(dst, src, min);
116 	memset(dst + min, 0, max - min);
117 }
118 
119 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
120 		     const unsigned char *dst_dev_addr)
121 {
122 	if (dev->if_type == IFT_INFINIBAND)
123 		dev_addr->dev_type = ARPHRD_INFINIBAND;
124 	else if (dev->if_type == IFT_ETHER)
125 		dev_addr->dev_type = ARPHRD_ETHER;
126 	else
127 		dev_addr->dev_type = 0;
128 	rdma_copy_addr_sub(dev_addr->src_dev_addr, IF_LLADDR(dev),
129 			   dev->if_addrlen, MAX_ADDR_LEN);
130 	rdma_copy_addr_sub(dev_addr->broadcast, dev->if_broadcastaddr,
131 			   dev->if_addrlen, MAX_ADDR_LEN);
132 	if (dst_dev_addr != NULL) {
133 		rdma_copy_addr_sub(dev_addr->dst_dev_addr, dst_dev_addr,
134 				   dev->if_addrlen, MAX_ADDR_LEN);
135 	}
136 	dev_addr->bound_dev_if = dev->if_index;
137 	return 0;
138 }
139 EXPORT_SYMBOL(rdma_copy_addr);
140 
141 int rdma_translate_ip(const struct sockaddr *addr,
142 		      struct rdma_dev_addr *dev_addr,
143 		      u16 *vlan_id)
144 {
145 	struct net_device *dev = NULL;
146 	int ret = -EADDRNOTAVAIL;
147 
148 	if (dev_addr->bound_dev_if) {
149 		dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
150 		if (!dev)
151 			return -ENODEV;
152 		ret = rdma_copy_addr(dev_addr, dev, NULL);
153 		dev_put(dev);
154 		return ret;
155 	}
156 
157 	switch (addr->sa_family) {
158 #ifdef INET
159 	case AF_INET:
160 		dev = ip_dev_find(dev_addr->net,
161 			((const struct sockaddr_in *)addr)->sin_addr.s_addr);
162 		break;
163 #endif
164 #ifdef INET6
165 	case AF_INET6:
166 		dev = ip6_dev_find(dev_addr->net,
167 			((const struct sockaddr_in6 *)addr)->sin6_addr);
168 		break;
169 #endif
170 	default:
171 		break;
172 	}
173 
174 	if (dev != NULL) {
175 		ret = rdma_copy_addr(dev_addr, dev, NULL);
176 		if (vlan_id)
177 			*vlan_id = rdma_vlan_dev_vlan_id(dev);
178 		dev_put(dev);
179 	}
180 	return ret;
181 }
182 EXPORT_SYMBOL(rdma_translate_ip);
183 
184 static void set_timeout(unsigned long time)
185 {
186 	int delay;	/* under FreeBSD ticks are 32-bit */
187 
188 	delay = time - jiffies;
189 	if (delay <= 0)
190 		delay = 1;
191 
192 	mod_delayed_work(addr_wq, &work, delay);
193 }
194 
195 static void queue_req(struct addr_req *req)
196 {
197 	struct addr_req *temp_req;
198 
199 	mutex_lock(&lock);
200 	list_for_each_entry_reverse(temp_req, &req_list, list) {
201 		if (time_after_eq(req->timeout, temp_req->timeout))
202 			break;
203 	}
204 
205 	list_add(&req->list, &temp_req->list);
206 
207 	if (req_list.next == &req->list)
208 		set_timeout(req->timeout);
209 	mutex_unlock(&lock);
210 }
211 
212 #if defined(INET) || defined(INET6)
213 static int addr_resolve_multi(u8 *edst, struct ifnet *ifp, struct sockaddr *dst_in)
214 {
215 	struct sockaddr *llsa;
216 	struct sockaddr_dl sdl;
217 	int error;
218 
219 	sdl.sdl_len = sizeof(sdl);
220 	llsa = (struct sockaddr *)&sdl;
221 
222 	if (ifp->if_resolvemulti == NULL) {
223 		error = EOPNOTSUPP;
224 	} else {
225 		error = ifp->if_resolvemulti(ifp, &llsa, dst_in);
226 		if (error == 0) {
227 			rdma_copy_addr_sub(edst, LLADDR((struct sockaddr_dl *)llsa),
228 			    ifp->if_addrlen, MAX_ADDR_LEN);
229 		}
230 	}
231 	return (error);
232 }
233 #endif
234 
235 #ifdef INET
236 static int addr4_resolve(struct sockaddr_in *src_in,
237 			 const struct sockaddr_in *dst_in,
238 			 struct rdma_dev_addr *addr,
239 			 struct ifnet **ifpp)
240 {
241 	struct sockaddr_in dst_tmp = *dst_in;
242 	u8 edst[MAX_ADDR_LEN];
243 	in_port_t src_port;
244 	struct sockaddr *saddr;
245 	struct rtentry *rte;
246 	struct ifnet *ifp;
247 	int error;
248 	int type;
249 
250 	/* set VNET, if any */
251 	CURVNET_SET(addr->net);
252 
253 	/* set default TTL limit */
254 	addr->hoplimit = V_ip_defttl;
255 
256 	type = 0;
257 	if (src_in->sin_addr.s_addr == INADDR_ANY)
258 		type |= 1;
259 	if (dst_tmp.sin_addr.s_addr == INADDR_ANY)
260 		type |= 2;
261 
262 	/*
263 	 * Make sure the socket address length field
264 	 * is set, else rtalloc1() will fail.
265 	 */
266 	dst_tmp.sin_len = sizeof(dst_tmp);
267 
268 	/* Step 1 - lookup destination route if any */
269 	switch (type) {
270 	case 0:
271 	case 1:
272 		/* regular destination route lookup */
273 		rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
274 		if (rte == NULL) {
275 			error = EHOSTUNREACH;
276 			goto done;
277 		} else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif ||
278 		    RT_LINK_IS_UP(rte->rt_ifp) == 0) {
279 			RTFREE_LOCKED(rte);
280 			error = EHOSTUNREACH;
281 			goto done;
282 		}
283 		RT_UNLOCK(rte);
284 		break;
285 	default:
286 		error = ENETUNREACH;
287 		goto done;
288 	}
289 
290 	/* Step 2 - find outgoing network interface */
291 	switch (type) {
292 	case 0:
293 		/* source check */
294 		ifp = ip_dev_find(addr->net, src_in->sin_addr.s_addr);
295 		if (ifp == NULL) {
296 			error = ENETUNREACH;
297 			goto error_rt_free;
298 		} else if (ifp != rte->rt_ifp) {
299 			error = ENETUNREACH;
300 			goto error_put_ifp;
301 		}
302 		break;
303 	case 1:
304 		/* get destination network interface from route */
305 		ifp = rte->rt_ifp;
306 		dev_hold(ifp);
307 		saddr = rte->rt_ifa->ifa_addr;
308 
309 		src_port = src_in->sin_port;
310 		memcpy(src_in, saddr, rdma_addr_size(saddr));
311 		src_in->sin_port = src_port;	/* preserve port number */
312 		break;
313 	default:
314 		break;
315 	}
316 
317 	/*
318 	 * Step 3 - resolve destination MAC address
319 	 */
320 	if (dst_tmp.sin_addr.s_addr == INADDR_BROADCAST) {
321 		rdma_copy_addr_sub(edst, ifp->if_broadcastaddr,
322 		    ifp->if_addrlen, MAX_ADDR_LEN);
323 	} else if (IN_MULTICAST(ntohl(dst_tmp.sin_addr.s_addr))) {
324 		error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp);
325 		if (error != 0)
326 			goto error_put_ifp;
327 	} else {
328 		bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
329 		memset(edst, 0, sizeof(edst));
330 		error = arpresolve(ifp, is_gw, NULL, is_gw ?
331 		    rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
332 		    edst, NULL, NULL);
333 		if (error != 0)
334 			goto error_put_ifp;
335 		else if (is_gw != 0)
336 			addr->network = RDMA_NETWORK_IPV4;
337 	}
338 
339 	/*
340 	 * Step 4 - copy destination and source MAC addresses
341 	 */
342 	error = -rdma_copy_addr(addr, ifp, edst);
343 	if (error != 0)
344 		goto error_put_ifp;
345 
346 	if (rte != NULL)
347 		RTFREE(rte);
348 
349 	*ifpp = ifp;
350 
351 	goto done;
352 
353 error_put_ifp:
354 	dev_put(ifp);
355 error_rt_free:
356 	RTFREE(rte);
357 done:
358 	CURVNET_RESTORE();
359 
360 	if (error == EWOULDBLOCK || error == EAGAIN)
361 		error = ENODATA;
362 	return (-error);
363 }
364 #else
365 static int addr4_resolve(struct sockaddr_in *src_in,
366 			 const struct sockaddr_in *dst_in,
367 			 struct rdma_dev_addr *addr,
368 			 struct ifnet **ifpp)
369 {
370 	return -EADDRNOTAVAIL;
371 }
372 #endif
373 
374 #ifdef INET6
375 static int addr6_resolve(struct sockaddr_in6 *src_in,
376 			 const struct sockaddr_in6 *dst_in,
377 			 struct rdma_dev_addr *addr,
378 			 struct ifnet **ifpp)
379 {
380 	struct sockaddr_in6 dst_tmp = *dst_in;
381 	u8 edst[MAX_ADDR_LEN];
382 	in_port_t src_port;
383 	struct sockaddr *saddr;
384 	struct rtentry *rte;
385 	struct ifnet *ifp;
386 	int error;
387 	int type;
388 
389 	/* set VNET, if any */
390 	CURVNET_SET(addr->net);
391 
392 	/* set default TTL limit */
393 	addr->hoplimit = V_ip_defttl;
394 
395 	type = 0;
396 	if (ipv6_addr_any(&src_in->sin6_addr))
397 		type |= 1;
398 	if (ipv6_addr_any(&dst_tmp.sin6_addr))
399 		type |= 2;
400 
401 	/*
402 	 * Make sure the socket address length field
403 	 * is set, else rtalloc1() will fail.
404 	 */
405 	dst_tmp.sin6_len = sizeof(dst_tmp);
406 
407 	/* Step 1 - lookup destination route if any */
408 	switch (type) {
409 	case 0:
410 		/* sanity check for IPv4 addresses */
411 		if (ipv6_addr_v4mapped(&src_in->sin6_addr) !=
412 		    ipv6_addr_v4mapped(&dst_tmp.sin6_addr)) {
413 			error = EAFNOSUPPORT;
414 			goto done;
415 		}
416 		/* FALLTHROUGH */
417 	case 1:
418 		/* regular destination route lookup */
419 		rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
420 		if (rte == NULL) {
421 			error = EHOSTUNREACH;
422 			goto done;
423 		} else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif ||
424 		    RT_LINK_IS_UP(rte->rt_ifp) == 0) {
425 			RTFREE_LOCKED(rte);
426 			error = EHOSTUNREACH;
427 			goto done;
428 		}
429 		RT_UNLOCK(rte);
430 		break;
431 	default:
432 		error = ENETUNREACH;
433 		goto done;
434 	}
435 
436 	/* Step 2 - find outgoing network interface */
437 	switch (type) {
438 	case 0:
439 		/* source check */
440 		ifp = ip6_dev_find(addr->net, src_in->sin6_addr);
441 		if (ifp == NULL) {
442 			error = ENETUNREACH;
443 			goto error_rt_free;
444 		} else if (ifp != rte->rt_ifp) {
445 			error = ENETUNREACH;
446 			goto error_put_ifp;
447 		}
448 		break;
449 	case 1:
450 		/* get destination network interface from route */
451 		ifp = rte->rt_ifp;
452 		dev_hold(ifp);
453 		saddr = rte->rt_ifa->ifa_addr;
454 
455 		src_port = src_in->sin6_port;
456 		memcpy(src_in, saddr, rdma_addr_size(saddr));
457 		src_in->sin6_port = src_port;	/* preserve port number */
458 		break;
459 	default:
460 		break;
461 	}
462 
463 	/*
464 	 * Step 3 - resolve destination MAC address
465 	 */
466 	if (IN6_IS_ADDR_MULTICAST(&dst_tmp.sin6_addr)) {
467 		error = addr_resolve_multi(edst, ifp,
468 		    (struct sockaddr *)&dst_tmp);
469 		if (error != 0)
470 			goto error_put_ifp;
471 	} else {
472 		bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
473 		memset(edst, 0, sizeof(edst));
474 		error = nd6_resolve(ifp, is_gw, NULL, is_gw ?
475 		    rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
476 		    edst, NULL, NULL);
477 		if (error != 0)
478 			goto error_put_ifp;
479 		else if (is_gw != 0)
480 			addr->network = RDMA_NETWORK_IPV6;
481 	}
482 
483 	/*
484 	 * Step 4 - copy destination and source MAC addresses
485 	 */
486 	error = -rdma_copy_addr(addr, ifp, edst);
487 	if (error != 0)
488 		goto error_put_ifp;
489 
490 	if (rte != NULL)
491 		RTFREE(rte);
492 
493 	*ifpp = ifp;
494 
495 	goto done;
496 
497 error_put_ifp:
498 	dev_put(ifp);
499 error_rt_free:
500 	RTFREE(rte);
501 done:
502 	CURVNET_RESTORE();
503 
504 	if (error == EWOULDBLOCK || error == EAGAIN)
505 		error = ENODATA;
506 	return (-error);
507 }
508 #else
509 static int addr6_resolve(struct sockaddr_in6 *src_in,
510 			 const struct sockaddr_in6 *dst_in,
511 			 struct rdma_dev_addr *addr,
512 			 struct ifnet **ifpp)
513 {
514 	return -EADDRNOTAVAIL;
515 }
516 #endif
517 
518 static int addr_resolve_neigh(struct ifnet *dev,
519 			      const struct sockaddr *dst_in,
520 			      struct rdma_dev_addr *addr)
521 {
522 	if (dev->if_flags & IFF_LOOPBACK) {
523 		int ret;
524 
525 		ret = rdma_translate_ip(dst_in, addr, NULL);
526 		if (!ret)
527 			memcpy(addr->dst_dev_addr, addr->src_dev_addr,
528 			       MAX_ADDR_LEN);
529 
530 		return ret;
531 	}
532 
533 	/* If the device doesn't do ARP internally */
534 	if (!(dev->if_flags & IFF_NOARP))
535 		return 0;
536 
537 	return rdma_copy_addr(addr, dev, NULL);
538 }
539 
540 static int addr_resolve(struct sockaddr *src_in,
541 			const struct sockaddr *dst_in,
542 			struct rdma_dev_addr *addr,
543 			bool resolve_neigh)
544 {
545 	struct net_device *ndev = NULL;
546 	int ret;
547 
548 	if (dst_in->sa_family != src_in->sa_family)
549 		return -EINVAL;
550 
551 	if (src_in->sa_family == AF_INET) {
552 		ret = addr4_resolve((struct sockaddr_in *)src_in,
553 				    (const struct sockaddr_in *)dst_in,
554 				    addr, &ndev);
555 		if (ret)
556 			return ret;
557 
558 		if (resolve_neigh)
559 			ret = addr_resolve_neigh(ndev, dst_in, addr);
560 	} else {
561 		ret = addr6_resolve((struct sockaddr_in6 *)src_in,
562 				    (const struct sockaddr_in6 *)dst_in, addr,
563 				    &ndev);
564 		if (ret)
565 			return ret;
566 
567 		if (resolve_neigh)
568 			ret = addr_resolve_neigh(ndev, dst_in, addr);
569 	}
570 
571 	addr->bound_dev_if = ndev->if_index;
572 	addr->net = dev_net(ndev);
573 	dev_put(ndev);
574 
575 	return ret;
576 }
577 
578 static void process_req(struct work_struct *work)
579 {
580 	struct addr_req *req, *temp_req;
581 	struct sockaddr *src_in, *dst_in;
582 	struct list_head done_list;
583 
584 	INIT_LIST_HEAD(&done_list);
585 
586 	mutex_lock(&lock);
587 	list_for_each_entry_safe(req, temp_req, &req_list, list) {
588 		if (req->status == -ENODATA) {
589 			src_in = (struct sockaddr *) &req->src_addr;
590 			dst_in = (struct sockaddr *) &req->dst_addr;
591 			req->status = addr_resolve(src_in, dst_in, req->addr,
592 						   true);
593 			if (req->status && time_after_eq(jiffies, req->timeout))
594 				req->status = -ETIMEDOUT;
595 			else if (req->status == -ENODATA)
596 				continue;
597 		}
598 		list_move_tail(&req->list, &done_list);
599 	}
600 
601 	if (!list_empty(&req_list)) {
602 		req = list_entry(req_list.next, struct addr_req, list);
603 		set_timeout(req->timeout);
604 	}
605 	mutex_unlock(&lock);
606 
607 	list_for_each_entry_safe(req, temp_req, &done_list, list) {
608 		list_del(&req->list);
609 		req->callback(req->status, (struct sockaddr *) &req->src_addr,
610 			req->addr, req->context);
611 		put_client(req->client);
612 		kfree(req);
613 	}
614 }
615 
616 int rdma_resolve_ip(struct rdma_addr_client *client,
617 		    struct sockaddr *src_addr, struct sockaddr *dst_addr,
618 		    struct rdma_dev_addr *addr, int timeout_ms,
619 		    void (*callback)(int status, struct sockaddr *src_addr,
620 				     struct rdma_dev_addr *addr, void *context),
621 		    void *context)
622 {
623 	struct sockaddr *src_in, *dst_in;
624 	struct addr_req *req;
625 	int ret = 0;
626 
627 	req = kzalloc(sizeof *req, GFP_KERNEL);
628 	if (!req)
629 		return -ENOMEM;
630 
631 	src_in = (struct sockaddr *) &req->src_addr;
632 	dst_in = (struct sockaddr *) &req->dst_addr;
633 
634 	if (src_addr) {
635 		if (src_addr->sa_family != dst_addr->sa_family) {
636 			ret = -EINVAL;
637 			goto err;
638 		}
639 
640 		memcpy(src_in, src_addr, rdma_addr_size(src_addr));
641 	} else {
642 		src_in->sa_family = dst_addr->sa_family;
643 	}
644 
645 	memcpy(dst_in, dst_addr, rdma_addr_size(dst_addr));
646 	req->addr = addr;
647 	req->callback = callback;
648 	req->context = context;
649 	req->client = client;
650 	atomic_inc(&client->refcount);
651 
652 	req->status = addr_resolve(src_in, dst_in, addr, true);
653 	switch (req->status) {
654 	case 0:
655 		req->timeout = jiffies;
656 		queue_req(req);
657 		break;
658 	case -ENODATA:
659 		req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
660 		queue_req(req);
661 		break;
662 	default:
663 		ret = req->status;
664 		atomic_dec(&client->refcount);
665 		goto err;
666 	}
667 	return ret;
668 err:
669 	kfree(req);
670 	return ret;
671 }
672 EXPORT_SYMBOL(rdma_resolve_ip);
673 
674 int rdma_resolve_ip_route(struct sockaddr *src_addr,
675 			  const struct sockaddr *dst_addr,
676 			  struct rdma_dev_addr *addr)
677 {
678 	struct sockaddr_storage ssrc_addr = {};
679 	struct sockaddr *src_in = (struct sockaddr *)&ssrc_addr;
680 
681 	if (src_addr) {
682 		if (src_addr->sa_family != dst_addr->sa_family)
683 			return -EINVAL;
684 
685 		memcpy(src_in, src_addr, rdma_addr_size(src_addr));
686 	} else {
687 		src_in->sa_family = dst_addr->sa_family;
688 	}
689 
690 	return addr_resolve(src_in, dst_addr, addr, false);
691 }
692 EXPORT_SYMBOL(rdma_resolve_ip_route);
693 
694 void rdma_addr_cancel(struct rdma_dev_addr *addr)
695 {
696 	struct addr_req *req, *temp_req;
697 
698 	mutex_lock(&lock);
699 	list_for_each_entry_safe(req, temp_req, &req_list, list) {
700 		if (req->addr == addr) {
701 			req->status = -ECANCELED;
702 			req->timeout = jiffies;
703 			list_move(&req->list, &req_list);
704 			set_timeout(req->timeout);
705 			break;
706 		}
707 	}
708 	mutex_unlock(&lock);
709 }
710 EXPORT_SYMBOL(rdma_addr_cancel);
711 
712 struct resolve_cb_context {
713 	struct rdma_dev_addr *addr;
714 	struct completion comp;
715 	int status;
716 };
717 
718 static void resolve_cb(int status, struct sockaddr *src_addr,
719 	     struct rdma_dev_addr *addr, void *context)
720 {
721 	if (!status)
722 		memcpy(((struct resolve_cb_context *)context)->addr,
723 		       addr, sizeof(struct rdma_dev_addr));
724 	((struct resolve_cb_context *)context)->status = status;
725 	complete(&((struct resolve_cb_context *)context)->comp);
726 }
727 
728 int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
729 				 const union ib_gid *dgid,
730 				 u8 *dmac, u16 *vlan_id, int *if_index,
731 				 int *hoplimit)
732 {
733 	int ret = 0;
734 	struct rdma_dev_addr dev_addr;
735 	struct resolve_cb_context ctx;
736 	struct net_device *dev;
737 
738 	union {
739 		struct sockaddr     _sockaddr;
740 		struct sockaddr_in  _sockaddr_in;
741 		struct sockaddr_in6 _sockaddr_in6;
742 	} sgid_addr, dgid_addr;
743 
744 
745 	rdma_gid2ip(&sgid_addr._sockaddr, sgid);
746 	rdma_gid2ip(&dgid_addr._sockaddr, dgid);
747 
748 	memset(&dev_addr, 0, sizeof(dev_addr));
749 	if (if_index)
750 		dev_addr.bound_dev_if = *if_index;
751 	dev_addr.net = TD_TO_VNET(curthread);
752 
753 	ctx.addr = &dev_addr;
754 	init_completion(&ctx.comp);
755 	ret = rdma_resolve_ip(&self, &sgid_addr._sockaddr, &dgid_addr._sockaddr,
756 			&dev_addr, 1000, resolve_cb, &ctx);
757 	if (ret)
758 		return ret;
759 
760 	wait_for_completion(&ctx.comp);
761 
762 	ret = ctx.status;
763 	if (ret)
764 		return ret;
765 
766 	memcpy(dmac, dev_addr.dst_dev_addr, ETH_ALEN);
767 	dev = dev_get_by_index(dev_addr.net, dev_addr.bound_dev_if);
768 	if (!dev)
769 		return -ENODEV;
770 	if (if_index)
771 		*if_index = dev_addr.bound_dev_if;
772 	if (vlan_id)
773 		*vlan_id = rdma_vlan_dev_vlan_id(dev);
774 	if (hoplimit)
775 		*hoplimit = dev_addr.hoplimit;
776 	dev_put(dev);
777 	return ret;
778 }
779 EXPORT_SYMBOL(rdma_addr_find_l2_eth_by_grh);
780 
781 int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
782 {
783 	int ret = 0;
784 	struct rdma_dev_addr dev_addr;
785 	union {
786 		struct sockaddr     _sockaddr;
787 		struct sockaddr_in  _sockaddr_in;
788 		struct sockaddr_in6 _sockaddr_in6;
789 	} gid_addr;
790 
791 	rdma_gid2ip(&gid_addr._sockaddr, sgid);
792 
793 	memset(&dev_addr, 0, sizeof(dev_addr));
794 	dev_addr.net = TD_TO_VNET(curthread);
795 	ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
796 	if (ret)
797 		return ret;
798 
799 	memcpy(smac, dev_addr.src_dev_addr, ETH_ALEN);
800 	return ret;
801 }
802 EXPORT_SYMBOL(rdma_addr_find_smac_by_sgid);
803 
804 int addr_init(void)
805 {
806 	addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
807 	if (!addr_wq)
808 		return -ENOMEM;
809 
810 	rdma_addr_register_client(&self);
811 
812 	return 0;
813 }
814 
815 void addr_cleanup(void)
816 {
817 	rdma_addr_unregister_client(&self);
818 	destroy_workqueue(addr_wq);
819 }
820