@@ -325,14 +325,32 @@ static inline unsigned int fib_devindex_hashfn(unsigned int val)
325
325
(val >> (DEVINDEX_HASHBITS * 2 ))) & mask ;
326
326
}
327
327
328
- static inline unsigned int fib_info_hashfn (const struct fib_info * fi )
328
+ static unsigned int fib_info_hashfn_1 (int init_val , u8 protocol , u8 scope ,
329
+ u32 prefsrc , u32 priority )
330
+ {
331
+ unsigned int val = init_val ;
332
+
333
+ val ^= (protocol << 8 ) | scope ;
334
+ val ^= prefsrc ;
335
+ val ^= priority ;
336
+
337
+ return val ;
338
+ }
339
+
340
+ static unsigned int fib_info_hashfn_result (unsigned int val )
329
341
{
330
342
unsigned int mask = (fib_info_hash_size - 1 );
331
- unsigned int val = fi -> fib_nhs ;
332
343
333
- val ^= (fi -> fib_protocol << 8 ) | fi -> fib_scope ;
334
- val ^= (__force u32 )fi -> fib_prefsrc ;
335
- val ^= fi -> fib_priority ;
344
+ return (val ^ (val >> 7 ) ^ (val >> 12 )) & mask ;
345
+ }
346
+
347
+ static inline unsigned int fib_info_hashfn (struct fib_info * fi )
348
+ {
349
+ unsigned int val ;
350
+
351
+ val = fib_info_hashfn_1 (fi -> fib_nhs , fi -> fib_protocol ,
352
+ fi -> fib_scope , (__force u32 )fi -> fib_prefsrc ,
353
+ fi -> fib_priority );
336
354
337
355
if (fi -> nh ) {
338
356
val ^= fib_devindex_hashfn (fi -> nh -> id );
@@ -342,7 +360,40 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
342
360
} endfor_nexthops (fi )
343
361
}
344
362
345
- return (val ^ (val >> 7 ) ^ (val >> 12 )) & mask ;
363
+ return fib_info_hashfn_result (val );
364
+ }
365
+
366
+ /* no metrics, only nexthop id */
367
+ static struct fib_info * fib_find_info_nh (struct net * net ,
368
+ const struct fib_config * cfg )
369
+ {
370
+ struct hlist_head * head ;
371
+ struct fib_info * fi ;
372
+ unsigned int hash ;
373
+
374
+ hash = fib_info_hashfn_1 (fib_devindex_hashfn (cfg -> fc_nh_id ),
375
+ cfg -> fc_protocol , cfg -> fc_scope ,
376
+ (__force u32 )cfg -> fc_prefsrc ,
377
+ cfg -> fc_priority );
378
+ hash = fib_info_hashfn_result (hash );
379
+ head = & fib_info_hash [hash ];
380
+
381
+ hlist_for_each_entry (fi , head , fib_hash ) {
382
+ if (!net_eq (fi -> fib_net , net ))
383
+ continue ;
384
+ if (!fi -> nh || fi -> nh -> id != cfg -> fc_nh_id )
385
+ continue ;
386
+ if (cfg -> fc_protocol == fi -> fib_protocol &&
387
+ cfg -> fc_scope == fi -> fib_scope &&
388
+ cfg -> fc_prefsrc == fi -> fib_prefsrc &&
389
+ cfg -> fc_priority == fi -> fib_priority &&
390
+ cfg -> fc_type == fi -> fib_type &&
391
+ cfg -> fc_table == fi -> fib_tb_id &&
392
+ !((cfg -> fc_flags ^ fi -> fib_flags ) & ~RTNH_COMPARE_MASK ))
393
+ return fi ;
394
+ }
395
+
396
+ return NULL ;
346
397
}
347
398
348
399
static struct fib_info * fib_find_info (struct fib_info * nfi )
@@ -1309,6 +1360,14 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
1309
1360
}
1310
1361
1311
1362
if (cfg -> fc_nh_id ) {
1363
+ if (!cfg -> fc_mx ) {
1364
+ fi = fib_find_info_nh (net , cfg );
1365
+ if (fi ) {
1366
+ fi -> fib_treeref ++ ;
1367
+ return fi ;
1368
+ }
1369
+ }
1370
+
1312
1371
nh = nexthop_find_by_id (net , cfg -> fc_nh_id );
1313
1372
if (!nh ) {
1314
1373
NL_SET_ERR_MSG (extack , "Nexthop id does not exist" );
0 commit comments