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