Skip to content

Commit 5f9ae3d

Browse files
lxindavem330
authored andcommitted
ipv4: do metrics match when looking up and deleting a route
Now when ipv4 route inserts a fib_info, it memcmp fib_metrics. It means ipv4 route identifies one route also with metrics. But when removing a route, it tries to find the route without caring about the metrics. It will cause that the route with right metrics can't be removed. Thomas noticed this issue when doing the testing: 1. add: # ip route append 192.168.7.0/24 dev v window 1000 # ip route append 192.168.7.0/24 dev v window 1001 # ip route append 192.168.7.0/24 dev v window 1002 # ip route append 192.168.7.0/24 dev v window 1003 2. delete: # ip route delete 192.168.7.0/24 dev v window 1002 3. show: 192.168.7.0/24 proto boot scope link window 1001 192.168.7.0/24 proto boot scope link window 1002 192.168.7.0/24 proto boot scope link window 1003 The one with window 1002 wasn't deleted but the first one was. This patch is to do metrics match when looking up and deleting one route. Reported-by: Thomas Haller <[email protected]> Signed-off-by: Xin Long <[email protected]> Acked-by: Hannes Frederic Sowa <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d260e9e commit 5f9ae3d

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

net/ipv4/fib_lookup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
3232
struct netlink_ext_ack *extack);
3333
int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
3434
struct netlink_ext_ack *extack);
35+
bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi);
3536
int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id,
3637
u8 type, __be32 dst, int dst_len, u8 tos, struct fib_info *fi,
3738
unsigned int);

net/ipv4/fib_semantics.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,40 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
696696
return 0;
697697
}
698698

699+
bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi)
700+
{
701+
struct nlattr *nla;
702+
int remaining;
703+
704+
if (!cfg->fc_mx)
705+
return true;
706+
707+
nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
708+
int type = nla_type(nla);
709+
u32 val;
710+
711+
if (!type)
712+
continue;
713+
if (type > RTAX_MAX)
714+
return false;
715+
716+
if (type == RTAX_CC_ALGO) {
717+
char tmp[TCP_CA_NAME_MAX];
718+
bool ecn_ca = false;
719+
720+
nla_strlcpy(tmp, nla, sizeof(tmp));
721+
val = tcp_ca_get_key_by_name(tmp, &ecn_ca);
722+
} else {
723+
val = nla_get_u32(nla);
724+
}
725+
726+
if (fi->fib_metrics->metrics[type - 1] != val)
727+
return false;
728+
}
729+
730+
return true;
731+
}
732+
699733

700734
/*
701735
* Picture

net/ipv4/fib_trie.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,8 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
15631563
fi->fib_prefsrc == cfg->fc_prefsrc) &&
15641564
(!cfg->fc_protocol ||
15651565
fi->fib_protocol == cfg->fc_protocol) &&
1566-
fib_nh_match(cfg, fi, extack) == 0) {
1566+
fib_nh_match(cfg, fi, extack) == 0 &&
1567+
fib_metrics_match(cfg, fi)) {
15671568
fa_to_delete = fa;
15681569
break;
15691570
}

0 commit comments

Comments
 (0)