1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2005 Voltaire Inc. All rights reserved.
3*4882a593Smuzhiyun * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
4*4882a593Smuzhiyun * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
5*4882a593Smuzhiyun * Copyright (c) 2005 Intel Corporation. All rights reserved.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This software is available to you under a choice of one of two
8*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
9*4882a593Smuzhiyun * General Public License (GPL) Version 2, available from the file
10*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the
11*4882a593Smuzhiyun * OpenIB.org BSD license below:
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or
14*4882a593Smuzhiyun * without modification, are permitted provided that the following
15*4882a593Smuzhiyun * conditions are met:
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * - Redistributions of source code must retain the above
18*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
19*4882a593Smuzhiyun * disclaimer.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above
22*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
23*4882a593Smuzhiyun * disclaimer in the documentation and/or other materials
24*4882a593Smuzhiyun * provided with the distribution.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*4882a593Smuzhiyun * SOFTWARE.
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <linux/mutex.h>
37*4882a593Smuzhiyun #include <linux/inetdevice.h>
38*4882a593Smuzhiyun #include <linux/slab.h>
39*4882a593Smuzhiyun #include <linux/workqueue.h>
40*4882a593Smuzhiyun #include <linux/module.h>
41*4882a593Smuzhiyun #include <net/arp.h>
42*4882a593Smuzhiyun #include <net/neighbour.h>
43*4882a593Smuzhiyun #include <net/route.h>
44*4882a593Smuzhiyun #include <net/netevent.h>
45*4882a593Smuzhiyun #include <net/ipv6_stubs.h>
46*4882a593Smuzhiyun #include <net/ip6_route.h>
47*4882a593Smuzhiyun #include <rdma/ib_addr.h>
48*4882a593Smuzhiyun #include <rdma/ib_cache.h>
49*4882a593Smuzhiyun #include <rdma/ib_sa.h>
50*4882a593Smuzhiyun #include <rdma/ib.h>
51*4882a593Smuzhiyun #include <rdma/rdma_netlink.h>
52*4882a593Smuzhiyun #include <net/netlink.h>
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #include "core_priv.h"
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun struct addr_req {
57*4882a593Smuzhiyun struct list_head list;
58*4882a593Smuzhiyun struct sockaddr_storage src_addr;
59*4882a593Smuzhiyun struct sockaddr_storage dst_addr;
60*4882a593Smuzhiyun struct rdma_dev_addr *addr;
61*4882a593Smuzhiyun void *context;
62*4882a593Smuzhiyun void (*callback)(int status, struct sockaddr *src_addr,
63*4882a593Smuzhiyun struct rdma_dev_addr *addr, void *context);
64*4882a593Smuzhiyun unsigned long timeout;
65*4882a593Smuzhiyun struct delayed_work work;
66*4882a593Smuzhiyun bool resolve_by_gid_attr; /* Consider gid attr in resolve phase */
67*4882a593Smuzhiyun int status;
68*4882a593Smuzhiyun u32 seq;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun static atomic_t ib_nl_addr_request_seq = ATOMIC_INIT(0);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static DEFINE_SPINLOCK(lock);
74*4882a593Smuzhiyun static LIST_HEAD(req_list);
75*4882a593Smuzhiyun static struct workqueue_struct *addr_wq;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
78*4882a593Smuzhiyun [LS_NLA_TYPE_DGID] = {.type = NLA_BINARY,
79*4882a593Smuzhiyun .len = sizeof(struct rdma_nla_ls_gid),
80*4882a593Smuzhiyun .validation_type = NLA_VALIDATE_MIN,
81*4882a593Smuzhiyun .min = sizeof(struct rdma_nla_ls_gid)},
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
ib_nl_is_good_ip_resp(const struct nlmsghdr * nlh)84*4882a593Smuzhiyun static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
87*4882a593Smuzhiyun int ret;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
90*4882a593Smuzhiyun return false;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
93*4882a593Smuzhiyun nlmsg_len(nlh), ib_nl_addr_policy, NULL);
94*4882a593Smuzhiyun if (ret)
95*4882a593Smuzhiyun return false;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun return true;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
ib_nl_process_good_ip_rsep(const struct nlmsghdr * nlh)100*4882a593Smuzhiyun static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun const struct nlattr *head, *curr;
103*4882a593Smuzhiyun union ib_gid gid;
104*4882a593Smuzhiyun struct addr_req *req;
105*4882a593Smuzhiyun int len, rem;
106*4882a593Smuzhiyun int found = 0;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun head = (const struct nlattr *)nlmsg_data(nlh);
109*4882a593Smuzhiyun len = nlmsg_len(nlh);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun nla_for_each_attr(curr, head, len, rem) {
112*4882a593Smuzhiyun if (curr->nla_type == LS_NLA_TYPE_DGID)
113*4882a593Smuzhiyun memcpy(&gid, nla_data(curr), nla_len(curr));
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun spin_lock_bh(&lock);
117*4882a593Smuzhiyun list_for_each_entry(req, &req_list, list) {
118*4882a593Smuzhiyun if (nlh->nlmsg_seq != req->seq)
119*4882a593Smuzhiyun continue;
120*4882a593Smuzhiyun /* We set the DGID part, the rest was set earlier */
121*4882a593Smuzhiyun rdma_addr_set_dgid(req->addr, &gid);
122*4882a593Smuzhiyun req->status = 0;
123*4882a593Smuzhiyun found = 1;
124*4882a593Smuzhiyun break;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun spin_unlock_bh(&lock);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun if (!found)
129*4882a593Smuzhiyun pr_info("Couldn't find request waiting for DGID: %pI6\n",
130*4882a593Smuzhiyun &gid);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
ib_nl_handle_ip_res_resp(struct sk_buff * skb,struct nlmsghdr * nlh,struct netlink_ext_ack * extack)133*4882a593Smuzhiyun int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
134*4882a593Smuzhiyun struct nlmsghdr *nlh,
135*4882a593Smuzhiyun struct netlink_ext_ack *extack)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun if ((nlh->nlmsg_flags & NLM_F_REQUEST) ||
138*4882a593Smuzhiyun !(NETLINK_CB(skb).sk))
139*4882a593Smuzhiyun return -EPERM;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (ib_nl_is_good_ip_resp(nlh))
142*4882a593Smuzhiyun ib_nl_process_good_ip_rsep(nlh);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun return 0;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
ib_nl_ip_send_msg(struct rdma_dev_addr * dev_addr,const void * daddr,u32 seq,u16 family)147*4882a593Smuzhiyun static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr,
148*4882a593Smuzhiyun const void *daddr,
149*4882a593Smuzhiyun u32 seq, u16 family)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun struct sk_buff *skb = NULL;
152*4882a593Smuzhiyun struct nlmsghdr *nlh;
153*4882a593Smuzhiyun struct rdma_ls_ip_resolve_header *header;
154*4882a593Smuzhiyun void *data;
155*4882a593Smuzhiyun size_t size;
156*4882a593Smuzhiyun int attrtype;
157*4882a593Smuzhiyun int len;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (family == AF_INET) {
160*4882a593Smuzhiyun size = sizeof(struct in_addr);
161*4882a593Smuzhiyun attrtype = RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_IPV4;
162*4882a593Smuzhiyun } else {
163*4882a593Smuzhiyun size = sizeof(struct in6_addr);
164*4882a593Smuzhiyun attrtype = RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_IPV6;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun len = nla_total_size(sizeof(size));
168*4882a593Smuzhiyun len += NLMSG_ALIGN(sizeof(*header));
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun skb = nlmsg_new(len, GFP_KERNEL);
171*4882a593Smuzhiyun if (!skb)
172*4882a593Smuzhiyun return -ENOMEM;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun data = ibnl_put_msg(skb, &nlh, seq, 0, RDMA_NL_LS,
175*4882a593Smuzhiyun RDMA_NL_LS_OP_IP_RESOLVE, NLM_F_REQUEST);
176*4882a593Smuzhiyun if (!data) {
177*4882a593Smuzhiyun nlmsg_free(skb);
178*4882a593Smuzhiyun return -ENODATA;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Construct the family header first */
182*4882a593Smuzhiyun header = skb_put(skb, NLMSG_ALIGN(sizeof(*header)));
183*4882a593Smuzhiyun header->ifindex = dev_addr->bound_dev_if;
184*4882a593Smuzhiyun nla_put(skb, attrtype, size, daddr);
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun /* Repair the nlmsg header length */
187*4882a593Smuzhiyun nlmsg_end(skb, nlh);
188*4882a593Smuzhiyun rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, GFP_KERNEL);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /* Make the request retry, so when we get the response from userspace
191*4882a593Smuzhiyun * we will have something.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun return -ENODATA;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
rdma_addr_size(const struct sockaddr * addr)196*4882a593Smuzhiyun int rdma_addr_size(const struct sockaddr *addr)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun switch (addr->sa_family) {
199*4882a593Smuzhiyun case AF_INET:
200*4882a593Smuzhiyun return sizeof(struct sockaddr_in);
201*4882a593Smuzhiyun case AF_INET6:
202*4882a593Smuzhiyun return sizeof(struct sockaddr_in6);
203*4882a593Smuzhiyun case AF_IB:
204*4882a593Smuzhiyun return sizeof(struct sockaddr_ib);
205*4882a593Smuzhiyun default:
206*4882a593Smuzhiyun return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_addr_size);
210*4882a593Smuzhiyun
rdma_addr_size_in6(struct sockaddr_in6 * addr)211*4882a593Smuzhiyun int rdma_addr_size_in6(struct sockaddr_in6 *addr)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun int ret = rdma_addr_size((struct sockaddr *) addr);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun return ret <= sizeof(*addr) ? ret : 0;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_addr_size_in6);
218*4882a593Smuzhiyun
rdma_addr_size_kss(struct __kernel_sockaddr_storage * addr)219*4882a593Smuzhiyun int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun int ret = rdma_addr_size((struct sockaddr *) addr);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun return ret <= sizeof(*addr) ? ret : 0;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_addr_size_kss);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /**
228*4882a593Smuzhiyun * rdma_copy_src_l2_addr - Copy netdevice source addresses
229*4882a593Smuzhiyun * @dev_addr: Destination address pointer where to copy the addresses
230*4882a593Smuzhiyun * @dev: Netdevice whose source addresses to copy
231*4882a593Smuzhiyun *
232*4882a593Smuzhiyun * rdma_copy_src_l2_addr() copies source addresses from the specified netdevice.
233*4882a593Smuzhiyun * This includes unicast address, broadcast address, device type and
234*4882a593Smuzhiyun * interface index.
235*4882a593Smuzhiyun */
rdma_copy_src_l2_addr(struct rdma_dev_addr * dev_addr,const struct net_device * dev)236*4882a593Smuzhiyun void rdma_copy_src_l2_addr(struct rdma_dev_addr *dev_addr,
237*4882a593Smuzhiyun const struct net_device *dev)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun dev_addr->dev_type = dev->type;
240*4882a593Smuzhiyun memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
241*4882a593Smuzhiyun memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
242*4882a593Smuzhiyun dev_addr->bound_dev_if = dev->ifindex;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_copy_src_l2_addr);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun static struct net_device *
rdma_find_ndev_for_src_ip_rcu(struct net * net,const struct sockaddr * src_in)247*4882a593Smuzhiyun rdma_find_ndev_for_src_ip_rcu(struct net *net, const struct sockaddr *src_in)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun struct net_device *dev = NULL;
250*4882a593Smuzhiyun int ret = -EADDRNOTAVAIL;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun switch (src_in->sa_family) {
253*4882a593Smuzhiyun case AF_INET:
254*4882a593Smuzhiyun dev = __ip_dev_find(net,
255*4882a593Smuzhiyun ((const struct sockaddr_in *)src_in)->sin_addr.s_addr,
256*4882a593Smuzhiyun false);
257*4882a593Smuzhiyun if (dev)
258*4882a593Smuzhiyun ret = 0;
259*4882a593Smuzhiyun break;
260*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
261*4882a593Smuzhiyun case AF_INET6:
262*4882a593Smuzhiyun for_each_netdev_rcu(net, dev) {
263*4882a593Smuzhiyun if (ipv6_chk_addr(net,
264*4882a593Smuzhiyun &((const struct sockaddr_in6 *)src_in)->sin6_addr,
265*4882a593Smuzhiyun dev, 1)) {
266*4882a593Smuzhiyun ret = 0;
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun break;
271*4882a593Smuzhiyun #endif
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun return ret ? ERR_PTR(ret) : dev;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
rdma_translate_ip(const struct sockaddr * addr,struct rdma_dev_addr * dev_addr)276*4882a593Smuzhiyun int rdma_translate_ip(const struct sockaddr *addr,
277*4882a593Smuzhiyun struct rdma_dev_addr *dev_addr)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun struct net_device *dev;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (dev_addr->bound_dev_if) {
282*4882a593Smuzhiyun dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
283*4882a593Smuzhiyun if (!dev)
284*4882a593Smuzhiyun return -ENODEV;
285*4882a593Smuzhiyun rdma_copy_src_l2_addr(dev_addr, dev);
286*4882a593Smuzhiyun dev_put(dev);
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun rcu_read_lock();
291*4882a593Smuzhiyun dev = rdma_find_ndev_for_src_ip_rcu(dev_addr->net, addr);
292*4882a593Smuzhiyun if (!IS_ERR(dev))
293*4882a593Smuzhiyun rdma_copy_src_l2_addr(dev_addr, dev);
294*4882a593Smuzhiyun rcu_read_unlock();
295*4882a593Smuzhiyun return PTR_ERR_OR_ZERO(dev);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_translate_ip);
298*4882a593Smuzhiyun
set_timeout(struct addr_req * req,unsigned long time)299*4882a593Smuzhiyun static void set_timeout(struct addr_req *req, unsigned long time)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun unsigned long delay;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun delay = time - jiffies;
304*4882a593Smuzhiyun if ((long)delay < 0)
305*4882a593Smuzhiyun delay = 0;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun mod_delayed_work(addr_wq, &req->work, delay);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
queue_req(struct addr_req * req)310*4882a593Smuzhiyun static void queue_req(struct addr_req *req)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun spin_lock_bh(&lock);
313*4882a593Smuzhiyun list_add_tail(&req->list, &req_list);
314*4882a593Smuzhiyun set_timeout(req, req->timeout);
315*4882a593Smuzhiyun spin_unlock_bh(&lock);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
ib_nl_fetch_ha(struct rdma_dev_addr * dev_addr,const void * daddr,u32 seq,u16 family)318*4882a593Smuzhiyun static int ib_nl_fetch_ha(struct rdma_dev_addr *dev_addr,
319*4882a593Smuzhiyun const void *daddr, u32 seq, u16 family)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun if (!rdma_nl_chk_listeners(RDMA_NL_GROUP_LS))
322*4882a593Smuzhiyun return -EADDRNOTAVAIL;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return ib_nl_ip_send_msg(dev_addr, daddr, seq, family);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
dst_fetch_ha(const struct dst_entry * dst,struct rdma_dev_addr * dev_addr,const void * daddr)327*4882a593Smuzhiyun static int dst_fetch_ha(const struct dst_entry *dst,
328*4882a593Smuzhiyun struct rdma_dev_addr *dev_addr,
329*4882a593Smuzhiyun const void *daddr)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun struct neighbour *n;
332*4882a593Smuzhiyun int ret = 0;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun n = dst_neigh_lookup(dst, daddr);
335*4882a593Smuzhiyun if (!n)
336*4882a593Smuzhiyun return -ENODATA;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun if (!(n->nud_state & NUD_VALID)) {
339*4882a593Smuzhiyun neigh_event_send(n, NULL);
340*4882a593Smuzhiyun ret = -ENODATA;
341*4882a593Smuzhiyun } else {
342*4882a593Smuzhiyun neigh_ha_snapshot(dev_addr->dst_dev_addr, n, dst->dev);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun neigh_release(n);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun return ret;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
has_gateway(const struct dst_entry * dst,sa_family_t family)350*4882a593Smuzhiyun static bool has_gateway(const struct dst_entry *dst, sa_family_t family)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun struct rtable *rt;
353*4882a593Smuzhiyun struct rt6_info *rt6;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (family == AF_INET) {
356*4882a593Smuzhiyun rt = container_of(dst, struct rtable, dst);
357*4882a593Smuzhiyun return rt->rt_uses_gateway;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun rt6 = container_of(dst, struct rt6_info, dst);
361*4882a593Smuzhiyun return rt6->rt6i_flags & RTF_GATEWAY;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
fetch_ha(const struct dst_entry * dst,struct rdma_dev_addr * dev_addr,const struct sockaddr * dst_in,u32 seq)364*4882a593Smuzhiyun static int fetch_ha(const struct dst_entry *dst, struct rdma_dev_addr *dev_addr,
365*4882a593Smuzhiyun const struct sockaddr *dst_in, u32 seq)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun const struct sockaddr_in *dst_in4 =
368*4882a593Smuzhiyun (const struct sockaddr_in *)dst_in;
369*4882a593Smuzhiyun const struct sockaddr_in6 *dst_in6 =
370*4882a593Smuzhiyun (const struct sockaddr_in6 *)dst_in;
371*4882a593Smuzhiyun const void *daddr = (dst_in->sa_family == AF_INET) ?
372*4882a593Smuzhiyun (const void *)&dst_in4->sin_addr.s_addr :
373*4882a593Smuzhiyun (const void *)&dst_in6->sin6_addr;
374*4882a593Smuzhiyun sa_family_t family = dst_in->sa_family;
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun might_sleep();
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* If we have a gateway in IB mode then it must be an IB network */
379*4882a593Smuzhiyun if (has_gateway(dst, family) && dev_addr->network == RDMA_NETWORK_IB)
380*4882a593Smuzhiyun return ib_nl_fetch_ha(dev_addr, daddr, seq, family);
381*4882a593Smuzhiyun else
382*4882a593Smuzhiyun return dst_fetch_ha(dst, dev_addr, daddr);
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
addr4_resolve(struct sockaddr * src_sock,const struct sockaddr * dst_sock,struct rdma_dev_addr * addr,struct rtable ** prt)385*4882a593Smuzhiyun static int addr4_resolve(struct sockaddr *src_sock,
386*4882a593Smuzhiyun const struct sockaddr *dst_sock,
387*4882a593Smuzhiyun struct rdma_dev_addr *addr,
388*4882a593Smuzhiyun struct rtable **prt)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun struct sockaddr_in *src_in = (struct sockaddr_in *)src_sock;
391*4882a593Smuzhiyun const struct sockaddr_in *dst_in =
392*4882a593Smuzhiyun (const struct sockaddr_in *)dst_sock;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun __be32 src_ip = src_in->sin_addr.s_addr;
395*4882a593Smuzhiyun __be32 dst_ip = dst_in->sin_addr.s_addr;
396*4882a593Smuzhiyun struct rtable *rt;
397*4882a593Smuzhiyun struct flowi4 fl4;
398*4882a593Smuzhiyun int ret;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun memset(&fl4, 0, sizeof(fl4));
401*4882a593Smuzhiyun fl4.daddr = dst_ip;
402*4882a593Smuzhiyun fl4.saddr = src_ip;
403*4882a593Smuzhiyun fl4.flowi4_oif = addr->bound_dev_if;
404*4882a593Smuzhiyun rt = ip_route_output_key(addr->net, &fl4);
405*4882a593Smuzhiyun ret = PTR_ERR_OR_ZERO(rt);
406*4882a593Smuzhiyun if (ret)
407*4882a593Smuzhiyun return ret;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun src_in->sin_addr.s_addr = fl4.saddr;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun addr->hoplimit = ip4_dst_hoplimit(&rt->dst);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun *prt = rt;
414*4882a593Smuzhiyun return 0;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
addr6_resolve(struct sockaddr * src_sock,const struct sockaddr * dst_sock,struct rdma_dev_addr * addr,struct dst_entry ** pdst)418*4882a593Smuzhiyun static int addr6_resolve(struct sockaddr *src_sock,
419*4882a593Smuzhiyun const struct sockaddr *dst_sock,
420*4882a593Smuzhiyun struct rdma_dev_addr *addr,
421*4882a593Smuzhiyun struct dst_entry **pdst)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun struct sockaddr_in6 *src_in = (struct sockaddr_in6 *)src_sock;
424*4882a593Smuzhiyun const struct sockaddr_in6 *dst_in =
425*4882a593Smuzhiyun (const struct sockaddr_in6 *)dst_sock;
426*4882a593Smuzhiyun struct flowi6 fl6;
427*4882a593Smuzhiyun struct dst_entry *dst;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun memset(&fl6, 0, sizeof fl6);
430*4882a593Smuzhiyun fl6.daddr = dst_in->sin6_addr;
431*4882a593Smuzhiyun fl6.saddr = src_in->sin6_addr;
432*4882a593Smuzhiyun fl6.flowi6_oif = addr->bound_dev_if;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
435*4882a593Smuzhiyun if (IS_ERR(dst))
436*4882a593Smuzhiyun return PTR_ERR(dst);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun if (ipv6_addr_any(&src_in->sin6_addr))
439*4882a593Smuzhiyun src_in->sin6_addr = fl6.saddr;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun addr->hoplimit = ip6_dst_hoplimit(dst);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun *pdst = dst;
444*4882a593Smuzhiyun return 0;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun #else
addr6_resolve(struct sockaddr * src_sock,const struct sockaddr * dst_sock,struct rdma_dev_addr * addr,struct dst_entry ** pdst)447*4882a593Smuzhiyun static int addr6_resolve(struct sockaddr *src_sock,
448*4882a593Smuzhiyun const struct sockaddr *dst_sock,
449*4882a593Smuzhiyun struct rdma_dev_addr *addr,
450*4882a593Smuzhiyun struct dst_entry **pdst)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun return -EADDRNOTAVAIL;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun #endif
455*4882a593Smuzhiyun
addr_resolve_neigh(const struct dst_entry * dst,const struct sockaddr * dst_in,struct rdma_dev_addr * addr,unsigned int ndev_flags,u32 seq)456*4882a593Smuzhiyun static int addr_resolve_neigh(const struct dst_entry *dst,
457*4882a593Smuzhiyun const struct sockaddr *dst_in,
458*4882a593Smuzhiyun struct rdma_dev_addr *addr,
459*4882a593Smuzhiyun unsigned int ndev_flags,
460*4882a593Smuzhiyun u32 seq)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun int ret = 0;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun if (ndev_flags & IFF_LOOPBACK) {
465*4882a593Smuzhiyun memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
466*4882a593Smuzhiyun } else {
467*4882a593Smuzhiyun if (!(ndev_flags & IFF_NOARP)) {
468*4882a593Smuzhiyun /* If the device doesn't do ARP internally */
469*4882a593Smuzhiyun ret = fetch_ha(dst, addr, dst_in, seq);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun return ret;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
copy_src_l2_addr(struct rdma_dev_addr * dev_addr,const struct sockaddr * dst_in,const struct dst_entry * dst,const struct net_device * ndev)475*4882a593Smuzhiyun static int copy_src_l2_addr(struct rdma_dev_addr *dev_addr,
476*4882a593Smuzhiyun const struct sockaddr *dst_in,
477*4882a593Smuzhiyun const struct dst_entry *dst,
478*4882a593Smuzhiyun const struct net_device *ndev)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun int ret = 0;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (dst->dev->flags & IFF_LOOPBACK)
483*4882a593Smuzhiyun ret = rdma_translate_ip(dst_in, dev_addr);
484*4882a593Smuzhiyun else
485*4882a593Smuzhiyun rdma_copy_src_l2_addr(dev_addr, dst->dev);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /*
488*4882a593Smuzhiyun * If there's a gateway and type of device not ARPHRD_INFINIBAND,
489*4882a593Smuzhiyun * we're definitely in RoCE v2 (as RoCE v1 isn't routable) set the
490*4882a593Smuzhiyun * network type accordingly.
491*4882a593Smuzhiyun */
492*4882a593Smuzhiyun if (has_gateway(dst, dst_in->sa_family) &&
493*4882a593Smuzhiyun ndev->type != ARPHRD_INFINIBAND)
494*4882a593Smuzhiyun dev_addr->network = dst_in->sa_family == AF_INET ?
495*4882a593Smuzhiyun RDMA_NETWORK_IPV4 :
496*4882a593Smuzhiyun RDMA_NETWORK_IPV6;
497*4882a593Smuzhiyun else
498*4882a593Smuzhiyun dev_addr->network = RDMA_NETWORK_IB;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun return ret;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
rdma_set_src_addr_rcu(struct rdma_dev_addr * dev_addr,unsigned int * ndev_flags,const struct sockaddr * dst_in,const struct dst_entry * dst)503*4882a593Smuzhiyun static int rdma_set_src_addr_rcu(struct rdma_dev_addr *dev_addr,
504*4882a593Smuzhiyun unsigned int *ndev_flags,
505*4882a593Smuzhiyun const struct sockaddr *dst_in,
506*4882a593Smuzhiyun const struct dst_entry *dst)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun struct net_device *ndev = READ_ONCE(dst->dev);
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun *ndev_flags = ndev->flags;
511*4882a593Smuzhiyun /* A physical device must be the RDMA device to use */
512*4882a593Smuzhiyun if (ndev->flags & IFF_LOOPBACK) {
513*4882a593Smuzhiyun /*
514*4882a593Smuzhiyun * RDMA (IB/RoCE, iWarp) doesn't run on lo interface or
515*4882a593Smuzhiyun * loopback IP address. So if route is resolved to loopback
516*4882a593Smuzhiyun * interface, translate that to a real ndev based on non
517*4882a593Smuzhiyun * loopback IP address.
518*4882a593Smuzhiyun */
519*4882a593Smuzhiyun ndev = rdma_find_ndev_for_src_ip_rcu(dev_net(ndev), dst_in);
520*4882a593Smuzhiyun if (IS_ERR(ndev))
521*4882a593Smuzhiyun return -ENODEV;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun return copy_src_l2_addr(dev_addr, dst_in, dst, ndev);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
set_addr_netns_by_gid_rcu(struct rdma_dev_addr * addr)527*4882a593Smuzhiyun static int set_addr_netns_by_gid_rcu(struct rdma_dev_addr *addr)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun struct net_device *ndev;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun ndev = rdma_read_gid_attr_ndev_rcu(addr->sgid_attr);
532*4882a593Smuzhiyun if (IS_ERR(ndev))
533*4882a593Smuzhiyun return PTR_ERR(ndev);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun /*
536*4882a593Smuzhiyun * Since we are holding the rcu, reading net and ifindex
537*4882a593Smuzhiyun * are safe without any additional reference; because
538*4882a593Smuzhiyun * change_net_namespace() in net/core/dev.c does rcu sync
539*4882a593Smuzhiyun * after it changes the state to IFF_DOWN and before
540*4882a593Smuzhiyun * updating netdev fields {net, ifindex}.
541*4882a593Smuzhiyun */
542*4882a593Smuzhiyun addr->net = dev_net(ndev);
543*4882a593Smuzhiyun addr->bound_dev_if = ndev->ifindex;
544*4882a593Smuzhiyun return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
rdma_addr_set_net_defaults(struct rdma_dev_addr * addr)547*4882a593Smuzhiyun static void rdma_addr_set_net_defaults(struct rdma_dev_addr *addr)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun addr->net = &init_net;
550*4882a593Smuzhiyun addr->bound_dev_if = 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
addr_resolve(struct sockaddr * src_in,const struct sockaddr * dst_in,struct rdma_dev_addr * addr,bool resolve_neigh,bool resolve_by_gid_attr,u32 seq)553*4882a593Smuzhiyun static int addr_resolve(struct sockaddr *src_in,
554*4882a593Smuzhiyun const struct sockaddr *dst_in,
555*4882a593Smuzhiyun struct rdma_dev_addr *addr,
556*4882a593Smuzhiyun bool resolve_neigh,
557*4882a593Smuzhiyun bool resolve_by_gid_attr,
558*4882a593Smuzhiyun u32 seq)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct dst_entry *dst = NULL;
561*4882a593Smuzhiyun unsigned int ndev_flags = 0;
562*4882a593Smuzhiyun struct rtable *rt = NULL;
563*4882a593Smuzhiyun int ret;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun if (!addr->net) {
566*4882a593Smuzhiyun pr_warn_ratelimited("%s: missing namespace\n", __func__);
567*4882a593Smuzhiyun return -EINVAL;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun rcu_read_lock();
571*4882a593Smuzhiyun if (resolve_by_gid_attr) {
572*4882a593Smuzhiyun if (!addr->sgid_attr) {
573*4882a593Smuzhiyun rcu_read_unlock();
574*4882a593Smuzhiyun pr_warn_ratelimited("%s: missing gid_attr\n", __func__);
575*4882a593Smuzhiyun return -EINVAL;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun /*
578*4882a593Smuzhiyun * If the request is for a specific gid attribute of the
579*4882a593Smuzhiyun * rdma_dev_addr, derive net from the netdevice of the
580*4882a593Smuzhiyun * GID attribute.
581*4882a593Smuzhiyun */
582*4882a593Smuzhiyun ret = set_addr_netns_by_gid_rcu(addr);
583*4882a593Smuzhiyun if (ret) {
584*4882a593Smuzhiyun rcu_read_unlock();
585*4882a593Smuzhiyun return ret;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun if (src_in->sa_family == AF_INET) {
589*4882a593Smuzhiyun ret = addr4_resolve(src_in, dst_in, addr, &rt);
590*4882a593Smuzhiyun dst = &rt->dst;
591*4882a593Smuzhiyun } else {
592*4882a593Smuzhiyun ret = addr6_resolve(src_in, dst_in, addr, &dst);
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun if (ret) {
595*4882a593Smuzhiyun rcu_read_unlock();
596*4882a593Smuzhiyun goto done;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun ret = rdma_set_src_addr_rcu(addr, &ndev_flags, dst_in, dst);
599*4882a593Smuzhiyun rcu_read_unlock();
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /*
602*4882a593Smuzhiyun * Resolve neighbor destination address if requested and
603*4882a593Smuzhiyun * only if src addr translation didn't fail.
604*4882a593Smuzhiyun */
605*4882a593Smuzhiyun if (!ret && resolve_neigh)
606*4882a593Smuzhiyun ret = addr_resolve_neigh(dst, dst_in, addr, ndev_flags, seq);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (src_in->sa_family == AF_INET)
609*4882a593Smuzhiyun ip_rt_put(rt);
610*4882a593Smuzhiyun else
611*4882a593Smuzhiyun dst_release(dst);
612*4882a593Smuzhiyun done:
613*4882a593Smuzhiyun /*
614*4882a593Smuzhiyun * Clear the addr net to go back to its original state, only if it was
615*4882a593Smuzhiyun * derived from GID attribute in this context.
616*4882a593Smuzhiyun */
617*4882a593Smuzhiyun if (resolve_by_gid_attr)
618*4882a593Smuzhiyun rdma_addr_set_net_defaults(addr);
619*4882a593Smuzhiyun return ret;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
process_one_req(struct work_struct * _work)622*4882a593Smuzhiyun static void process_one_req(struct work_struct *_work)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun struct addr_req *req;
625*4882a593Smuzhiyun struct sockaddr *src_in, *dst_in;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun req = container_of(_work, struct addr_req, work.work);
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if (req->status == -ENODATA) {
630*4882a593Smuzhiyun src_in = (struct sockaddr *)&req->src_addr;
631*4882a593Smuzhiyun dst_in = (struct sockaddr *)&req->dst_addr;
632*4882a593Smuzhiyun req->status = addr_resolve(src_in, dst_in, req->addr,
633*4882a593Smuzhiyun true, req->resolve_by_gid_attr,
634*4882a593Smuzhiyun req->seq);
635*4882a593Smuzhiyun if (req->status && time_after_eq(jiffies, req->timeout)) {
636*4882a593Smuzhiyun req->status = -ETIMEDOUT;
637*4882a593Smuzhiyun } else if (req->status == -ENODATA) {
638*4882a593Smuzhiyun /* requeue the work for retrying again */
639*4882a593Smuzhiyun spin_lock_bh(&lock);
640*4882a593Smuzhiyun if (!list_empty(&req->list))
641*4882a593Smuzhiyun set_timeout(req, req->timeout);
642*4882a593Smuzhiyun spin_unlock_bh(&lock);
643*4882a593Smuzhiyun return;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun req->callback(req->status, (struct sockaddr *)&req->src_addr,
648*4882a593Smuzhiyun req->addr, req->context);
649*4882a593Smuzhiyun req->callback = NULL;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun spin_lock_bh(&lock);
652*4882a593Smuzhiyun /*
653*4882a593Smuzhiyun * Although the work will normally have been canceled by the workqueue,
654*4882a593Smuzhiyun * it can still be requeued as long as it is on the req_list.
655*4882a593Smuzhiyun */
656*4882a593Smuzhiyun cancel_delayed_work(&req->work);
657*4882a593Smuzhiyun if (!list_empty(&req->list)) {
658*4882a593Smuzhiyun list_del_init(&req->list);
659*4882a593Smuzhiyun kfree(req);
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun spin_unlock_bh(&lock);
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
rdma_resolve_ip(struct sockaddr * src_addr,const struct sockaddr * dst_addr,struct rdma_dev_addr * addr,unsigned long timeout_ms,void (* callback)(int status,struct sockaddr * src_addr,struct rdma_dev_addr * addr,void * context),bool resolve_by_gid_attr,void * context)664*4882a593Smuzhiyun int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr,
665*4882a593Smuzhiyun struct rdma_dev_addr *addr, unsigned long timeout_ms,
666*4882a593Smuzhiyun void (*callback)(int status, struct sockaddr *src_addr,
667*4882a593Smuzhiyun struct rdma_dev_addr *addr, void *context),
668*4882a593Smuzhiyun bool resolve_by_gid_attr, void *context)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun struct sockaddr *src_in, *dst_in;
671*4882a593Smuzhiyun struct addr_req *req;
672*4882a593Smuzhiyun int ret = 0;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun req = kzalloc(sizeof *req, GFP_KERNEL);
675*4882a593Smuzhiyun if (!req)
676*4882a593Smuzhiyun return -ENOMEM;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun src_in = (struct sockaddr *) &req->src_addr;
679*4882a593Smuzhiyun dst_in = (struct sockaddr *) &req->dst_addr;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun if (src_addr) {
682*4882a593Smuzhiyun if (src_addr->sa_family != dst_addr->sa_family) {
683*4882a593Smuzhiyun ret = -EINVAL;
684*4882a593Smuzhiyun goto err;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun memcpy(src_in, src_addr, rdma_addr_size(src_addr));
688*4882a593Smuzhiyun } else {
689*4882a593Smuzhiyun src_in->sa_family = dst_addr->sa_family;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun memcpy(dst_in, dst_addr, rdma_addr_size(dst_addr));
693*4882a593Smuzhiyun req->addr = addr;
694*4882a593Smuzhiyun req->callback = callback;
695*4882a593Smuzhiyun req->context = context;
696*4882a593Smuzhiyun req->resolve_by_gid_attr = resolve_by_gid_attr;
697*4882a593Smuzhiyun INIT_DELAYED_WORK(&req->work, process_one_req);
698*4882a593Smuzhiyun req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun req->status = addr_resolve(src_in, dst_in, addr, true,
701*4882a593Smuzhiyun req->resolve_by_gid_attr, req->seq);
702*4882a593Smuzhiyun switch (req->status) {
703*4882a593Smuzhiyun case 0:
704*4882a593Smuzhiyun req->timeout = jiffies;
705*4882a593Smuzhiyun queue_req(req);
706*4882a593Smuzhiyun break;
707*4882a593Smuzhiyun case -ENODATA:
708*4882a593Smuzhiyun req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
709*4882a593Smuzhiyun queue_req(req);
710*4882a593Smuzhiyun break;
711*4882a593Smuzhiyun default:
712*4882a593Smuzhiyun ret = req->status;
713*4882a593Smuzhiyun goto err;
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun return ret;
716*4882a593Smuzhiyun err:
717*4882a593Smuzhiyun kfree(req);
718*4882a593Smuzhiyun return ret;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_resolve_ip);
721*4882a593Smuzhiyun
roce_resolve_route_from_path(struct sa_path_rec * rec,const struct ib_gid_attr * attr)722*4882a593Smuzhiyun int roce_resolve_route_from_path(struct sa_path_rec *rec,
723*4882a593Smuzhiyun const struct ib_gid_attr *attr)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun union {
726*4882a593Smuzhiyun struct sockaddr _sockaddr;
727*4882a593Smuzhiyun struct sockaddr_in _sockaddr_in;
728*4882a593Smuzhiyun struct sockaddr_in6 _sockaddr_in6;
729*4882a593Smuzhiyun } sgid, dgid;
730*4882a593Smuzhiyun struct rdma_dev_addr dev_addr = {};
731*4882a593Smuzhiyun int ret;
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun might_sleep();
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun if (rec->roce.route_resolved)
736*4882a593Smuzhiyun return 0;
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun rdma_gid2ip((struct sockaddr *)&sgid, &rec->sgid);
739*4882a593Smuzhiyun rdma_gid2ip((struct sockaddr *)&dgid, &rec->dgid);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun if (sgid._sockaddr.sa_family != dgid._sockaddr.sa_family)
742*4882a593Smuzhiyun return -EINVAL;
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun if (!attr || !attr->ndev)
745*4882a593Smuzhiyun return -EINVAL;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun dev_addr.net = &init_net;
748*4882a593Smuzhiyun dev_addr.sgid_attr = attr;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun ret = addr_resolve((struct sockaddr *)&sgid, (struct sockaddr *)&dgid,
751*4882a593Smuzhiyun &dev_addr, false, true, 0);
752*4882a593Smuzhiyun if (ret)
753*4882a593Smuzhiyun return ret;
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun if ((dev_addr.network == RDMA_NETWORK_IPV4 ||
756*4882a593Smuzhiyun dev_addr.network == RDMA_NETWORK_IPV6) &&
757*4882a593Smuzhiyun rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2)
758*4882a593Smuzhiyun return -EINVAL;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun rec->roce.route_resolved = true;
761*4882a593Smuzhiyun return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /**
765*4882a593Smuzhiyun * rdma_addr_cancel - Cancel resolve ip request
766*4882a593Smuzhiyun * @addr: Pointer to address structure given previously
767*4882a593Smuzhiyun * during rdma_resolve_ip().
768*4882a593Smuzhiyun * rdma_addr_cancel() is synchronous function which cancels any pending
769*4882a593Smuzhiyun * request if there is any.
770*4882a593Smuzhiyun */
rdma_addr_cancel(struct rdma_dev_addr * addr)771*4882a593Smuzhiyun void rdma_addr_cancel(struct rdma_dev_addr *addr)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun struct addr_req *req, *temp_req;
774*4882a593Smuzhiyun struct addr_req *found = NULL;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun spin_lock_bh(&lock);
777*4882a593Smuzhiyun list_for_each_entry_safe(req, temp_req, &req_list, list) {
778*4882a593Smuzhiyun if (req->addr == addr) {
779*4882a593Smuzhiyun /*
780*4882a593Smuzhiyun * Removing from the list means we take ownership of
781*4882a593Smuzhiyun * the req
782*4882a593Smuzhiyun */
783*4882a593Smuzhiyun list_del_init(&req->list);
784*4882a593Smuzhiyun found = req;
785*4882a593Smuzhiyun break;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun spin_unlock_bh(&lock);
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun if (!found)
791*4882a593Smuzhiyun return;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun /*
794*4882a593Smuzhiyun * sync canceling the work after removing it from the req_list
795*4882a593Smuzhiyun * guarentees no work is running and none will be started.
796*4882a593Smuzhiyun */
797*4882a593Smuzhiyun cancel_delayed_work_sync(&found->work);
798*4882a593Smuzhiyun kfree(found);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun EXPORT_SYMBOL(rdma_addr_cancel);
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun struct resolve_cb_context {
803*4882a593Smuzhiyun struct completion comp;
804*4882a593Smuzhiyun int status;
805*4882a593Smuzhiyun };
806*4882a593Smuzhiyun
resolve_cb(int status,struct sockaddr * src_addr,struct rdma_dev_addr * addr,void * context)807*4882a593Smuzhiyun static void resolve_cb(int status, struct sockaddr *src_addr,
808*4882a593Smuzhiyun struct rdma_dev_addr *addr, void *context)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun ((struct resolve_cb_context *)context)->status = status;
811*4882a593Smuzhiyun complete(&((struct resolve_cb_context *)context)->comp);
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun
rdma_addr_find_l2_eth_by_grh(const union ib_gid * sgid,const union ib_gid * dgid,u8 * dmac,const struct ib_gid_attr * sgid_attr,int * hoplimit)814*4882a593Smuzhiyun int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
815*4882a593Smuzhiyun const union ib_gid *dgid,
816*4882a593Smuzhiyun u8 *dmac, const struct ib_gid_attr *sgid_attr,
817*4882a593Smuzhiyun int *hoplimit)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun struct rdma_dev_addr dev_addr;
820*4882a593Smuzhiyun struct resolve_cb_context ctx;
821*4882a593Smuzhiyun union {
822*4882a593Smuzhiyun struct sockaddr_in _sockaddr_in;
823*4882a593Smuzhiyun struct sockaddr_in6 _sockaddr_in6;
824*4882a593Smuzhiyun } sgid_addr, dgid_addr;
825*4882a593Smuzhiyun int ret;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
828*4882a593Smuzhiyun rdma_gid2ip((struct sockaddr *)&dgid_addr, dgid);
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun memset(&dev_addr, 0, sizeof(dev_addr));
831*4882a593Smuzhiyun dev_addr.net = &init_net;
832*4882a593Smuzhiyun dev_addr.sgid_attr = sgid_attr;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun init_completion(&ctx.comp);
835*4882a593Smuzhiyun ret = rdma_resolve_ip((struct sockaddr *)&sgid_addr,
836*4882a593Smuzhiyun (struct sockaddr *)&dgid_addr, &dev_addr, 1000,
837*4882a593Smuzhiyun resolve_cb, true, &ctx);
838*4882a593Smuzhiyun if (ret)
839*4882a593Smuzhiyun return ret;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun wait_for_completion(&ctx.comp);
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun ret = ctx.status;
844*4882a593Smuzhiyun if (ret)
845*4882a593Smuzhiyun return ret;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun memcpy(dmac, dev_addr.dst_dev_addr, ETH_ALEN);
848*4882a593Smuzhiyun *hoplimit = dev_addr.hoplimit;
849*4882a593Smuzhiyun return 0;
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun
netevent_callback(struct notifier_block * self,unsigned long event,void * ctx)852*4882a593Smuzhiyun static int netevent_callback(struct notifier_block *self, unsigned long event,
853*4882a593Smuzhiyun void *ctx)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun struct addr_req *req;
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if (event == NETEVENT_NEIGH_UPDATE) {
858*4882a593Smuzhiyun struct neighbour *neigh = ctx;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun if (neigh->nud_state & NUD_VALID) {
861*4882a593Smuzhiyun spin_lock_bh(&lock);
862*4882a593Smuzhiyun list_for_each_entry(req, &req_list, list)
863*4882a593Smuzhiyun set_timeout(req, jiffies);
864*4882a593Smuzhiyun spin_unlock_bh(&lock);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun return 0;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun static struct notifier_block nb = {
871*4882a593Smuzhiyun .notifier_call = netevent_callback
872*4882a593Smuzhiyun };
873*4882a593Smuzhiyun
addr_init(void)874*4882a593Smuzhiyun int addr_init(void)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun addr_wq = alloc_ordered_workqueue("ib_addr", 0);
877*4882a593Smuzhiyun if (!addr_wq)
878*4882a593Smuzhiyun return -ENOMEM;
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun register_netevent_notifier(&nb);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun return 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
addr_cleanup(void)885*4882a593Smuzhiyun void addr_cleanup(void)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun unregister_netevent_notifier(&nb);
888*4882a593Smuzhiyun destroy_workqueue(addr_wq);
889*4882a593Smuzhiyun WARN_ON(!list_empty(&req_list));
890*4882a593Smuzhiyun }
891