@@ -247,12 +247,11 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
247
247
if (nla_put_u32 (skb , NHA_ID , nh -> id ))
248
248
goto nla_put_failure ;
249
249
250
- if (nh -> is_fdb_nh && nla_put_flag (skb , NHA_FDB ))
251
- goto nla_put_failure ;
252
-
253
250
if (nh -> is_group ) {
254
251
struct nh_group * nhg = rtnl_dereference (nh -> nh_grp );
255
252
253
+ if (nhg -> fdb_nh && nla_put_flag (skb , NHA_FDB ))
254
+ goto nla_put_failure ;
256
255
if (nla_put_nh_group (skb , nhg ))
257
256
goto nla_put_failure ;
258
257
goto out ;
@@ -264,7 +263,10 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
264
263
if (nla_put_flag (skb , NHA_BLACKHOLE ))
265
264
goto nla_put_failure ;
266
265
goto out ;
267
- } else if (!nh -> is_fdb_nh ) {
266
+ } else if (nhi -> fdb_nh ) {
267
+ if (nla_put_flag (skb , NHA_FDB ))
268
+ goto nla_put_failure ;
269
+ } else {
268
270
const struct net_device * dev ;
269
271
270
272
dev = nhi -> fib_nhc .nhc_dev ;
@@ -385,7 +387,7 @@ static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info)
385
387
}
386
388
387
389
static bool valid_group_nh (struct nexthop * nh , unsigned int npaths ,
388
- struct netlink_ext_ack * extack )
390
+ bool * is_fdb , struct netlink_ext_ack * extack )
389
391
{
390
392
if (nh -> is_group ) {
391
393
struct nh_group * nhg = rtnl_dereference (nh -> nh_grp );
@@ -398,6 +400,7 @@ static bool valid_group_nh(struct nexthop *nh, unsigned int npaths,
398
400
"Multipath group can not be a nexthop within a group" );
399
401
return false;
400
402
}
403
+ * is_fdb = nhg -> fdb_nh ;
401
404
} else {
402
405
struct nh_info * nhi = rtnl_dereference (nh -> nh_info );
403
406
@@ -406,6 +409,7 @@ static bool valid_group_nh(struct nexthop *nh, unsigned int npaths,
406
409
"Blackhole nexthop can not be used in a group with more than 1 path" );
407
410
return false;
408
411
}
412
+ * is_fdb = nhi -> fdb_nh ;
409
413
}
410
414
411
415
return true;
@@ -416,12 +420,13 @@ static int nh_check_attr_fdb_group(struct nexthop *nh, u8 *nh_family,
416
420
{
417
421
struct nh_info * nhi ;
418
422
419
- if (!nh -> is_fdb_nh ) {
423
+ nhi = rtnl_dereference (nh -> nh_info );
424
+
425
+ if (!nhi -> fdb_nh ) {
420
426
NL_SET_ERR_MSG (extack , "FDB nexthop group can only have fdb nexthops" );
421
427
return - EINVAL ;
422
428
}
423
429
424
- nhi = rtnl_dereference (nh -> nh_info );
425
430
if (* nh_family == AF_UNSPEC ) {
426
431
* nh_family = nhi -> family ;
427
432
} else if (* nh_family != nhi -> family ) {
@@ -473,19 +478,20 @@ static int nh_check_attr_group(struct net *net, struct nlattr *tb[],
473
478
nhg = nla_data (tb [NHA_GROUP ]);
474
479
for (i = 0 ; i < len ; ++ i ) {
475
480
struct nexthop * nh ;
481
+ bool is_fdb_nh ;
476
482
477
483
nh = nexthop_find_by_id (net , nhg [i ].id );
478
484
if (!nh ) {
479
485
NL_SET_ERR_MSG (extack , "Invalid nexthop id" );
480
486
return - EINVAL ;
481
487
}
482
- if (!valid_group_nh (nh , len , extack ))
488
+ if (!valid_group_nh (nh , len , & is_fdb_nh , extack ))
483
489
return - EINVAL ;
484
490
485
491
if (nhg_fdb && nh_check_attr_fdb_group (nh , & nh_family , extack ))
486
492
return - EINVAL ;
487
493
488
- if (!nhg_fdb && nh -> is_fdb_nh ) {
494
+ if (!nhg_fdb && is_fdb_nh ) {
489
495
NL_SET_ERR_MSG (extack , "Non FDB nexthop group cannot have fdb nexthops" );
490
496
return - EINVAL ;
491
497
}
@@ -553,13 +559,13 @@ struct nexthop *nexthop_select_path(struct nexthop *nh, int hash)
553
559
if (hash > atomic_read (& nhge -> upper_bound ))
554
560
continue ;
555
561
556
- if (nhge -> nh -> is_fdb_nh )
562
+ nhi = rcu_dereference (nhge -> nh -> nh_info );
563
+ if (nhi -> fdb_nh )
557
564
return nhge -> nh ;
558
565
559
566
/* nexthops always check if it is good and does
560
567
* not rely on a sysctl for this behavior
561
568
*/
562
- nhi = rcu_dereference (nhge -> nh -> nh_info );
563
569
switch (nhi -> family ) {
564
570
case AF_INET :
565
571
if (ipv4_good_nh (& nhi -> fib_nh ))
@@ -624,11 +630,7 @@ int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg,
624
630
struct netlink_ext_ack * extack )
625
631
{
626
632
struct nh_info * nhi ;
627
-
628
- if (nh -> is_fdb_nh ) {
629
- NL_SET_ERR_MSG (extack , "Route cannot point to a fdb nexthop" );
630
- return - EINVAL ;
631
- }
633
+ bool is_fdb_nh ;
632
634
633
635
/* fib6_src is unique to a fib6_info and limits the ability to cache
634
636
* routes in fib6_nh within a nexthop that is potentially shared
@@ -645,10 +647,17 @@ int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg,
645
647
nhg = rtnl_dereference (nh -> nh_grp );
646
648
if (nhg -> has_v4 )
647
649
goto no_v4_nh ;
650
+ is_fdb_nh = nhg -> fdb_nh ;
648
651
} else {
649
652
nhi = rtnl_dereference (nh -> nh_info );
650
653
if (nhi -> family == AF_INET )
651
654
goto no_v4_nh ;
655
+ is_fdb_nh = nhi -> fdb_nh ;
656
+ }
657
+
658
+ if (is_fdb_nh ) {
659
+ NL_SET_ERR_MSG (extack , "Route cannot point to a fdb nexthop" );
660
+ return - EINVAL ;
652
661
}
653
662
654
663
return 0 ;
@@ -677,12 +686,9 @@ static int fib6_check_nh_list(struct nexthop *old, struct nexthop *new,
677
686
return fib6_check_nexthop (new , NULL , extack );
678
687
}
679
688
680
- static int nexthop_check_scope (struct nexthop * nh , u8 scope ,
689
+ static int nexthop_check_scope (struct nh_info * nhi , u8 scope ,
681
690
struct netlink_ext_ack * extack )
682
691
{
683
- struct nh_info * nhi ;
684
-
685
- nhi = rtnl_dereference (nh -> nh_info );
686
692
if (scope == RT_SCOPE_HOST && nhi -> fib_nhc .nhc_gw_family ) {
687
693
NL_SET_ERR_MSG (extack ,
688
694
"Route with host scope can not have a gateway" );
@@ -704,29 +710,38 @@ static int nexthop_check_scope(struct nexthop *nh, u8 scope,
704
710
int fib_check_nexthop (struct nexthop * nh , u8 scope ,
705
711
struct netlink_ext_ack * extack )
706
712
{
713
+ struct nh_info * nhi ;
707
714
int err = 0 ;
708
715
709
- if (nh -> is_fdb_nh ) {
710
- NL_SET_ERR_MSG (extack , "Route cannot point to a fdb nexthop" );
711
- err = - EINVAL ;
712
- goto out ;
713
- }
714
-
715
716
if (nh -> is_group ) {
716
717
struct nh_group * nhg ;
717
718
719
+ nhg = rtnl_dereference (nh -> nh_grp );
720
+ if (nhg -> fdb_nh ) {
721
+ NL_SET_ERR_MSG (extack , "Route cannot point to a fdb nexthop" );
722
+ err = - EINVAL ;
723
+ goto out ;
724
+ }
725
+
718
726
if (scope == RT_SCOPE_HOST ) {
719
727
NL_SET_ERR_MSG (extack , "Route with host scope can not have multiple nexthops" );
720
728
err = - EINVAL ;
721
729
goto out ;
722
730
}
723
731
724
- nhg = rtnl_dereference (nh -> nh_grp );
725
732
/* all nexthops in a group have the same scope */
726
- err = nexthop_check_scope (nhg -> nh_entries [0 ].nh , scope , extack );
733
+ nhi = rtnl_dereference (nhg -> nh_entries [0 ].nh -> nh_info );
734
+ err = nexthop_check_scope (nhi , scope , extack );
727
735
} else {
728
- err = nexthop_check_scope (nh , scope , extack );
736
+ nhi = rtnl_dereference (nh -> nh_info );
737
+ if (nhi -> fdb_nh ) {
738
+ NL_SET_ERR_MSG (extack , "Route cannot point to a fdb nexthop" );
739
+ err = - EINVAL ;
740
+ goto out ;
741
+ }
742
+ err = nexthop_check_scope (nhi , scope , extack );
729
743
}
744
+
730
745
out :
731
746
return err ;
732
747
}
@@ -787,6 +802,7 @@ static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
787
802
788
803
newg -> has_v4 = nhg -> has_v4 ;
789
804
newg -> mpath = nhg -> mpath ;
805
+ newg -> fdb_nh = nhg -> fdb_nh ;
790
806
newg -> num_nh = nhg -> num_nh ;
791
807
792
808
/* copy old entries to new except the one getting removed */
@@ -1216,7 +1232,7 @@ static struct nexthop *nexthop_create_group(struct net *net,
1216
1232
}
1217
1233
1218
1234
if (cfg -> nh_fdb )
1219
- nh -> is_fdb_nh = 1 ;
1235
+ nhg -> fdb_nh = 1 ;
1220
1236
1221
1237
rcu_assign_pointer (nh -> nh_grp , nhg );
1222
1238
@@ -1255,7 +1271,7 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh,
1255
1271
goto out ;
1256
1272
}
1257
1273
1258
- if (nh -> is_fdb_nh )
1274
+ if (nhi -> fdb_nh )
1259
1275
goto out ;
1260
1276
1261
1277
/* sets nh_dev if successful */
@@ -1326,7 +1342,7 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
1326
1342
nhi -> fib_nhc .nhc_scope = RT_SCOPE_LINK ;
1327
1343
1328
1344
if (cfg -> nh_fdb )
1329
- nh -> is_fdb_nh = 1 ;
1345
+ nhi -> fdb_nh = 1 ;
1330
1346
1331
1347
if (cfg -> nh_blackhole ) {
1332
1348
nhi -> reject_nh = 1 ;
@@ -1349,7 +1365,7 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
1349
1365
}
1350
1366
1351
1367
/* add the entry to the device based hash */
1352
- if (!nh -> is_fdb_nh )
1368
+ if (!nhi -> fdb_nh )
1353
1369
nexthop_devhash_add (net , nhi );
1354
1370
1355
1371
rcu_assign_pointer (nh -> nh_info , nhi );
0 commit comments