Skip to content

Commit ce9ac05

Browse files
dsaherndavem330
authored andcommitted
nexthop: Fix fdb labeling for groups
fdb nexthops are marked with a flag. For standalone nexthops, a flag was added to the nh_info struct. For groups that flag was added to struct nexthop when it should have been added to the group information. Fix by removing the flag from the nexthop struct and adding a flag to nh_group that mirrors nh_info and is really only a caching of the individual types. Add a helper, nexthop_is_fdb, for use by the vxlan code and fixup the internal code to use the flag from either nh_info or nh_group. v2 - propagate fdb_nh in remove_nh_grp_entry Fixes: 38428d6 ("nexthop: support for fdb ecmp nexthops") Cc: Roopa Prabhu <[email protected]> Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 89dc685 commit ce9ac05

File tree

3 files changed

+66
-35
lines changed

3 files changed

+66
-35
lines changed

drivers/net/vxlan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ static int vxlan_fdb_nh_update(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
876876
nh = NULL;
877877
goto err_inval;
878878
}
879-
if (!nh->is_fdb_nh) {
879+
if (!nexthop_is_fdb(nh)) {
880880
NL_SET_ERR_MSG(extack, "Nexthop is not a fdb nexthop");
881881
goto err_inval;
882882
}

include/net/nexthop.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct nh_group {
7676
struct nh_group *spare; /* spare group for removals */
7777
u16 num_nh;
7878
bool mpath;
79+
bool fdb_nh;
7980
bool has_v4;
8081
struct nh_grp_entry nh_entries[];
8182
};
@@ -93,7 +94,6 @@ struct nexthop {
9394
u8 protocol; /* app managing this nh */
9495
u8 nh_flags;
9596
bool is_group;
96-
bool is_fdb_nh;
9797

9898
refcount_t refcnt;
9999
struct rcu_head rcu;
@@ -136,6 +136,21 @@ static inline bool nexthop_cmp(const struct nexthop *nh1,
136136
return nh1 == nh2;
137137
}
138138

139+
static inline bool nexthop_is_fdb(const struct nexthop *nh)
140+
{
141+
if (nh->is_group) {
142+
const struct nh_group *nh_grp;
143+
144+
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
145+
return nh_grp->fdb_nh;
146+
} else {
147+
const struct nh_info *nhi;
148+
149+
nhi = rcu_dereference_rtnl(nh->nh_info);
150+
return nhi->fdb_nh;
151+
}
152+
}
153+
139154
static inline bool nexthop_is_multipath(const struct nexthop *nh)
140155
{
141156
if (nh->is_group) {

net/ipv4/nexthop.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,11 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
247247
if (nla_put_u32(skb, NHA_ID, nh->id))
248248
goto nla_put_failure;
249249

250-
if (nh->is_fdb_nh && nla_put_flag(skb, NHA_FDB))
251-
goto nla_put_failure;
252-
253250
if (nh->is_group) {
254251
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
255252

253+
if (nhg->fdb_nh && nla_put_flag(skb, NHA_FDB))
254+
goto nla_put_failure;
256255
if (nla_put_nh_group(skb, nhg))
257256
goto nla_put_failure;
258257
goto out;
@@ -264,7 +263,10 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
264263
if (nla_put_flag(skb, NHA_BLACKHOLE))
265264
goto nla_put_failure;
266265
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 {
268270
const struct net_device *dev;
269271

270272
dev = nhi->fib_nhc.nhc_dev;
@@ -385,7 +387,7 @@ static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info)
385387
}
386388

387389
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)
389391
{
390392
if (nh->is_group) {
391393
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
@@ -398,6 +400,7 @@ static bool valid_group_nh(struct nexthop *nh, unsigned int npaths,
398400
"Multipath group can not be a nexthop within a group");
399401
return false;
400402
}
403+
*is_fdb = nhg->fdb_nh;
401404
} else {
402405
struct nh_info *nhi = rtnl_dereference(nh->nh_info);
403406

@@ -406,6 +409,7 @@ static bool valid_group_nh(struct nexthop *nh, unsigned int npaths,
406409
"Blackhole nexthop can not be used in a group with more than 1 path");
407410
return false;
408411
}
412+
*is_fdb = nhi->fdb_nh;
409413
}
410414

411415
return true;
@@ -416,12 +420,13 @@ static int nh_check_attr_fdb_group(struct nexthop *nh, u8 *nh_family,
416420
{
417421
struct nh_info *nhi;
418422

419-
if (!nh->is_fdb_nh) {
423+
nhi = rtnl_dereference(nh->nh_info);
424+
425+
if (!nhi->fdb_nh) {
420426
NL_SET_ERR_MSG(extack, "FDB nexthop group can only have fdb nexthops");
421427
return -EINVAL;
422428
}
423429

424-
nhi = rtnl_dereference(nh->nh_info);
425430
if (*nh_family == AF_UNSPEC) {
426431
*nh_family = nhi->family;
427432
} else if (*nh_family != nhi->family) {
@@ -473,19 +478,20 @@ static int nh_check_attr_group(struct net *net, struct nlattr *tb[],
473478
nhg = nla_data(tb[NHA_GROUP]);
474479
for (i = 0; i < len; ++i) {
475480
struct nexthop *nh;
481+
bool is_fdb_nh;
476482

477483
nh = nexthop_find_by_id(net, nhg[i].id);
478484
if (!nh) {
479485
NL_SET_ERR_MSG(extack, "Invalid nexthop id");
480486
return -EINVAL;
481487
}
482-
if (!valid_group_nh(nh, len, extack))
488+
if (!valid_group_nh(nh, len, &is_fdb_nh, extack))
483489
return -EINVAL;
484490

485491
if (nhg_fdb && nh_check_attr_fdb_group(nh, &nh_family, extack))
486492
return -EINVAL;
487493

488-
if (!nhg_fdb && nh->is_fdb_nh) {
494+
if (!nhg_fdb && is_fdb_nh) {
489495
NL_SET_ERR_MSG(extack, "Non FDB nexthop group cannot have fdb nexthops");
490496
return -EINVAL;
491497
}
@@ -553,13 +559,13 @@ struct nexthop *nexthop_select_path(struct nexthop *nh, int hash)
553559
if (hash > atomic_read(&nhge->upper_bound))
554560
continue;
555561

556-
if (nhge->nh->is_fdb_nh)
562+
nhi = rcu_dereference(nhge->nh->nh_info);
563+
if (nhi->fdb_nh)
557564
return nhge->nh;
558565

559566
/* nexthops always check if it is good and does
560567
* not rely on a sysctl for this behavior
561568
*/
562-
nhi = rcu_dereference(nhge->nh->nh_info);
563569
switch (nhi->family) {
564570
case AF_INET:
565571
if (ipv4_good_nh(&nhi->fib_nh))
@@ -624,11 +630,7 @@ int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg,
624630
struct netlink_ext_ack *extack)
625631
{
626632
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;
632634

633635
/* fib6_src is unique to a fib6_info and limits the ability to cache
634636
* 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,
645647
nhg = rtnl_dereference(nh->nh_grp);
646648
if (nhg->has_v4)
647649
goto no_v4_nh;
650+
is_fdb_nh = nhg->fdb_nh;
648651
} else {
649652
nhi = rtnl_dereference(nh->nh_info);
650653
if (nhi->family == AF_INET)
651654
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;
652661
}
653662

654663
return 0;
@@ -677,12 +686,9 @@ static int fib6_check_nh_list(struct nexthop *old, struct nexthop *new,
677686
return fib6_check_nexthop(new, NULL, extack);
678687
}
679688

680-
static int nexthop_check_scope(struct nexthop *nh, u8 scope,
689+
static int nexthop_check_scope(struct nh_info *nhi, u8 scope,
681690
struct netlink_ext_ack *extack)
682691
{
683-
struct nh_info *nhi;
684-
685-
nhi = rtnl_dereference(nh->nh_info);
686692
if (scope == RT_SCOPE_HOST && nhi->fib_nhc.nhc_gw_family) {
687693
NL_SET_ERR_MSG(extack,
688694
"Route with host scope can not have a gateway");
@@ -704,29 +710,38 @@ static int nexthop_check_scope(struct nexthop *nh, u8 scope,
704710
int fib_check_nexthop(struct nexthop *nh, u8 scope,
705711
struct netlink_ext_ack *extack)
706712
{
713+
struct nh_info *nhi;
707714
int err = 0;
708715

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-
715716
if (nh->is_group) {
716717
struct nh_group *nhg;
717718

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+
718726
if (scope == RT_SCOPE_HOST) {
719727
NL_SET_ERR_MSG(extack, "Route with host scope can not have multiple nexthops");
720728
err = -EINVAL;
721729
goto out;
722730
}
723731

724-
nhg = rtnl_dereference(nh->nh_grp);
725732
/* 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);
727735
} 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);
729743
}
744+
730745
out:
731746
return err;
732747
}
@@ -787,6 +802,7 @@ static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
787802

788803
newg->has_v4 = nhg->has_v4;
789804
newg->mpath = nhg->mpath;
805+
newg->fdb_nh = nhg->fdb_nh;
790806
newg->num_nh = nhg->num_nh;
791807

792808
/* copy old entries to new except the one getting removed */
@@ -1216,7 +1232,7 @@ static struct nexthop *nexthop_create_group(struct net *net,
12161232
}
12171233

12181234
if (cfg->nh_fdb)
1219-
nh->is_fdb_nh = 1;
1235+
nhg->fdb_nh = 1;
12201236

12211237
rcu_assign_pointer(nh->nh_grp, nhg);
12221238

@@ -1255,7 +1271,7 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh,
12551271
goto out;
12561272
}
12571273

1258-
if (nh->is_fdb_nh)
1274+
if (nhi->fdb_nh)
12591275
goto out;
12601276

12611277
/* sets nh_dev if successful */
@@ -1326,7 +1342,7 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
13261342
nhi->fib_nhc.nhc_scope = RT_SCOPE_LINK;
13271343

13281344
if (cfg->nh_fdb)
1329-
nh->is_fdb_nh = 1;
1345+
nhi->fdb_nh = 1;
13301346

13311347
if (cfg->nh_blackhole) {
13321348
nhi->reject_nh = 1;
@@ -1349,7 +1365,7 @@ static struct nexthop *nexthop_create(struct net *net, struct nh_config *cfg,
13491365
}
13501366

13511367
/* add the entry to the device based hash */
1352-
if (!nh->is_fdb_nh)
1368+
if (!nhi->fdb_nh)
13531369
nexthop_devhash_add(net, nhi);
13541370

13551371
rcu_assign_pointer(nh->nh_info, nhi);

0 commit comments

Comments
 (0)