@@ -121,7 +121,8 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
121
121
}
122
122
EXPORT_SYMBOL (rdma_copy_addr );
123
123
124
- int rdma_translate_ip (struct sockaddr * addr , struct rdma_dev_addr * dev_addr ,
124
+ int rdma_translate_ip (const struct sockaddr * addr ,
125
+ struct rdma_dev_addr * dev_addr ,
125
126
u16 * vlan_id )
126
127
{
127
128
struct net_device * dev ;
@@ -139,7 +140,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
139
140
switch (addr -> sa_family ) {
140
141
case AF_INET :
141
142
dev = ip_dev_find (dev_addr -> net ,
142
- ((struct sockaddr_in * ) addr )-> sin_addr .s_addr );
143
+ ((const struct sockaddr_in * )addr )-> sin_addr .s_addr );
143
144
144
145
if (!dev )
145
146
return ret ;
@@ -154,7 +155,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr,
154
155
rcu_read_lock ();
155
156
for_each_netdev_rcu (dev_addr -> net , dev ) {
156
157
if (ipv6_chk_addr (dev_addr -> net ,
157
- & ((struct sockaddr_in6 * ) addr )-> sin6_addr ,
158
+ & ((const struct sockaddr_in6 * )addr )-> sin6_addr ,
158
159
dev , 1 )) {
159
160
ret = rdma_copy_addr (dev_addr , dev , NULL );
160
161
if (vlan_id )
@@ -198,7 +199,8 @@ static void queue_req(struct addr_req *req)
198
199
mutex_unlock (& lock );
199
200
}
200
201
201
- static int dst_fetch_ha (struct dst_entry * dst , struct rdma_dev_addr * dev_addr , void * daddr )
202
+ static int dst_fetch_ha (struct dst_entry * dst , struct rdma_dev_addr * dev_addr ,
203
+ const void * daddr )
202
204
{
203
205
struct neighbour * n ;
204
206
int ret ;
@@ -222,8 +224,9 @@ static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr, v
222
224
}
223
225
224
226
static int addr4_resolve (struct sockaddr_in * src_in ,
225
- struct sockaddr_in * dst_in ,
226
- struct rdma_dev_addr * addr )
227
+ const struct sockaddr_in * dst_in ,
228
+ struct rdma_dev_addr * addr ,
229
+ struct rtable * * prt )
227
230
{
228
231
__be32 src_ip = src_in -> sin_addr .s_addr ;
229
232
__be32 dst_ip = dst_in -> sin_addr .s_addr ;
@@ -243,36 +246,23 @@ static int addr4_resolve(struct sockaddr_in *src_in,
243
246
src_in -> sin_family = AF_INET ;
244
247
src_in -> sin_addr .s_addr = fl4 .saddr ;
245
248
246
- if (rt -> dst .dev -> flags & IFF_LOOPBACK ) {
247
- ret = rdma_translate_ip ((struct sockaddr * )dst_in , addr , NULL );
248
- if (!ret )
249
- memcpy (addr -> dst_dev_addr , addr -> src_dev_addr , MAX_ADDR_LEN );
250
- goto put ;
251
- }
252
-
253
- /* If the device does ARP internally, return 'done' */
254
- if (rt -> dst .dev -> flags & IFF_NOARP ) {
255
- ret = rdma_copy_addr (addr , rt -> dst .dev , NULL );
256
- goto put ;
257
- }
258
-
259
249
/* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't
260
250
* routable) and we could set the network type accordingly.
261
251
*/
262
252
if (rt -> rt_uses_gateway )
263
253
addr -> network = RDMA_NETWORK_IPV4 ;
264
254
265
- ret = dst_fetch_ha (& rt -> dst , addr , & fl4 .daddr );
266
- put :
267
- ip_rt_put (rt );
255
+ * prt = rt ;
256
+ return 0 ;
268
257
out :
269
258
return ret ;
270
259
}
271
260
272
261
#if IS_ENABLED (CONFIG_IPV6 )
273
262
static int addr6_resolve (struct sockaddr_in6 * src_in ,
274
- struct sockaddr_in6 * dst_in ,
275
- struct rdma_dev_addr * addr )
263
+ const struct sockaddr_in6 * dst_in ,
264
+ struct rdma_dev_addr * addr ,
265
+ struct dst_entry * * pdst )
276
266
{
277
267
struct flowi6 fl6 ;
278
268
struct dst_entry * dst ;
@@ -299,49 +289,109 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
299
289
src_in -> sin6_addr = fl6 .saddr ;
300
290
}
301
291
302
- if (dst -> dev -> flags & IFF_LOOPBACK ) {
303
- ret = rdma_translate_ip ((struct sockaddr * )dst_in , addr , NULL );
304
- if (!ret )
305
- memcpy (addr -> dst_dev_addr , addr -> src_dev_addr , MAX_ADDR_LEN );
306
- goto put ;
307
- }
308
-
309
- /* If the device does ARP internally, return 'done' */
310
- if (dst -> dev -> flags & IFF_NOARP ) {
311
- ret = rdma_copy_addr (addr , dst -> dev , NULL );
312
- goto put ;
313
- }
314
-
315
292
/* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't
316
293
* routable) and we could set the network type accordingly.
317
294
*/
318
295
if (rt -> rt6i_flags & RTF_GATEWAY )
319
296
addr -> network = RDMA_NETWORK_IPV6 ;
320
297
321
- ret = dst_fetch_ha (dst , addr , & fl6 .daddr );
298
+ * pdst = dst ;
299
+ return 0 ;
322
300
put :
323
301
dst_release (dst );
324
302
return ret ;
325
303
}
326
304
#else
327
305
static int addr6_resolve (struct sockaddr_in6 * src_in ,
328
- struct sockaddr_in6 * dst_in ,
329
- struct rdma_dev_addr * addr )
306
+ const struct sockaddr_in6 * dst_in ,
307
+ struct rdma_dev_addr * addr ,
308
+ struct dst_entry * * pdst )
330
309
{
331
310
return - EADDRNOTAVAIL ;
332
311
}
333
312
#endif
334
313
314
+ static int addr_resolve_neigh (struct dst_entry * dst ,
315
+ const struct sockaddr * dst_in ,
316
+ struct rdma_dev_addr * addr )
317
+ {
318
+ if (dst -> dev -> flags & IFF_LOOPBACK ) {
319
+ int ret ;
320
+
321
+ ret = rdma_translate_ip (dst_in , addr , NULL );
322
+ if (!ret )
323
+ memcpy (addr -> dst_dev_addr , addr -> src_dev_addr ,
324
+ MAX_ADDR_LEN );
325
+
326
+ return ret ;
327
+ }
328
+
329
+ /* If the device doesn't do ARP internally */
330
+ if (!(dst -> dev -> flags & IFF_NOARP )) {
331
+ const struct sockaddr_in * dst_in4 =
332
+ (const struct sockaddr_in * )dst_in ;
333
+ const struct sockaddr_in6 * dst_in6 =
334
+ (const struct sockaddr_in6 * )dst_in ;
335
+
336
+ return dst_fetch_ha (dst , addr ,
337
+ dst_in -> sa_family == AF_INET ?
338
+ (const void * )& dst_in4 -> sin_addr .s_addr :
339
+ (const void * )& dst_in6 -> sin6_addr );
340
+ }
341
+
342
+ return rdma_copy_addr (addr , dst -> dev , NULL );
343
+ }
344
+
335
345
static int addr_resolve (struct sockaddr * src_in ,
336
- struct sockaddr * dst_in ,
337
- struct rdma_dev_addr * addr )
346
+ const struct sockaddr * dst_in ,
347
+ struct rdma_dev_addr * addr ,
348
+ bool resolve_neigh )
338
349
{
350
+ struct net_device * ndev ;
351
+ struct dst_entry * dst ;
352
+ int ret ;
353
+
339
354
if (src_in -> sa_family == AF_INET ) {
340
- return addr4_resolve ((struct sockaddr_in * ) src_in ,
341
- (struct sockaddr_in * ) dst_in , addr );
342
- } else
343
- return addr6_resolve ((struct sockaddr_in6 * ) src_in ,
344
- (struct sockaddr_in6 * ) dst_in , addr );
355
+ struct rtable * rt = NULL ;
356
+ const struct sockaddr_in * dst_in4 =
357
+ (const struct sockaddr_in * )dst_in ;
358
+
359
+ ret = addr4_resolve ((struct sockaddr_in * )src_in ,
360
+ dst_in4 , addr , & rt );
361
+ if (ret )
362
+ return ret ;
363
+
364
+ if (resolve_neigh )
365
+ ret = addr_resolve_neigh (& rt -> dst , dst_in , addr );
366
+
367
+ ndev = rt -> dst .dev ;
368
+ dev_hold (ndev );
369
+
370
+ ip_rt_put (rt );
371
+ } else {
372
+ const struct sockaddr_in6 * dst_in6 =
373
+ (const struct sockaddr_in6 * )dst_in ;
374
+
375
+ ret = addr6_resolve ((struct sockaddr_in6 * )src_in ,
376
+ dst_in6 , addr ,
377
+ & dst );
378
+ if (ret )
379
+ return ret ;
380
+
381
+ if (resolve_neigh )
382
+ ret = addr_resolve_neigh (dst , dst_in , addr );
383
+
384
+ ndev = dst -> dev ;
385
+ dev_hold (ndev );
386
+
387
+ dst_release (dst );
388
+ }
389
+
390
+ addr -> bound_dev_if = ndev -> ifindex ;
391
+ addr -> net = dev_net (ndev );
392
+ dev_put (ndev );
393
+
394
+ return ret ;
345
395
}
346
396
347
397
static void process_req (struct work_struct * work )
@@ -357,7 +407,8 @@ static void process_req(struct work_struct *work)
357
407
if (req -> status == - ENODATA ) {
358
408
src_in = (struct sockaddr * ) & req -> src_addr ;
359
409
dst_in = (struct sockaddr * ) & req -> dst_addr ;
360
- req -> status = addr_resolve (src_in , dst_in , req -> addr );
410
+ req -> status = addr_resolve (src_in , dst_in , req -> addr ,
411
+ true);
361
412
if (req -> status && time_after_eq (jiffies , req -> timeout ))
362
413
req -> status = - ETIMEDOUT ;
363
414
else if (req -> status == - ENODATA )
@@ -417,7 +468,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
417
468
req -> client = client ;
418
469
atomic_inc (& client -> refcount );
419
470
420
- req -> status = addr_resolve (src_in , dst_in , addr );
471
+ req -> status = addr_resolve (src_in , dst_in , addr , true );
421
472
switch (req -> status ) {
422
473
case 0 :
423
474
req -> timeout = jiffies ;
@@ -439,6 +490,25 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
439
490
}
440
491
EXPORT_SYMBOL (rdma_resolve_ip );
441
492
493
+ int rdma_resolve_ip_route (struct sockaddr * src_addr ,
494
+ const struct sockaddr * dst_addr ,
495
+ struct rdma_dev_addr * addr )
496
+ {
497
+ struct sockaddr_storage ssrc_addr = {};
498
+ struct sockaddr * src_in = (struct sockaddr * )& ssrc_addr ;
499
+
500
+ if (src_addr -> sa_family != dst_addr -> sa_family )
501
+ return - EINVAL ;
502
+
503
+ if (src_addr )
504
+ memcpy (src_in , src_addr , rdma_addr_size (src_addr ));
505
+ else
506
+ src_in -> sa_family = dst_addr -> sa_family ;
507
+
508
+ return addr_resolve (src_in , dst_addr , addr , false);
509
+ }
510
+ EXPORT_SYMBOL (rdma_resolve_ip_route );
511
+
442
512
void rdma_addr_cancel (struct rdma_dev_addr * addr )
443
513
{
444
514
struct addr_req * req , * temp_req ;
@@ -471,7 +541,7 @@ static void resolve_cb(int status, struct sockaddr *src_addr,
471
541
}
472
542
473
543
int rdma_addr_find_dmac_by_grh (const union ib_gid * sgid , const union ib_gid * dgid ,
474
- u8 * dmac , u16 * vlan_id , int if_index )
544
+ u8 * dmac , u16 * vlan_id , int * if_index )
475
545
{
476
546
int ret = 0 ;
477
547
struct rdma_dev_addr dev_addr ;
@@ -489,7 +559,8 @@ int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgi
489
559
rdma_gid2ip (& dgid_addr ._sockaddr , dgid );
490
560
491
561
memset (& dev_addr , 0 , sizeof (dev_addr ));
492
- dev_addr .bound_dev_if = if_index ;
562
+ if (if_index )
563
+ dev_addr .bound_dev_if = * if_index ;
493
564
dev_addr .net = & init_net ;
494
565
495
566
ctx .addr = & dev_addr ;
@@ -505,6 +576,8 @@ int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgi
505
576
dev = dev_get_by_index (& init_net , dev_addr .bound_dev_if );
506
577
if (!dev )
507
578
return - ENODEV ;
579
+ if (if_index )
580
+ * if_index = dev_addr .bound_dev_if ;
508
581
if (vlan_id )
509
582
* vlan_id = rdma_vlan_dev_vlan_id (dev );
510
583
dev_put (dev );
0 commit comments