Commit a349fcc8 authored by David S. Miller's avatar David S. Miller

Merge branch 'newroute-creation-flags'

Guillaume Nault says:

====================
ip: fix creation flags reported in RTM_NEWROUTE events

Netlink messages sent to user-space upon RTM_NEWROUTE events have their
nlmsg_flags field inconsistently set. While the NLM_F_REPLACE and
NLM_F_APPEND bits are correctly handled, NLM_F_CREATE and NLM_F_EXCL
are always 0.

This series sets the NLM_F_CREATE and NLM_F_EXCL bits when applicable,
for IPv4 and IPv6.

Since IPv6 ignores the NLM_F_APPEND flags in requests, this flag isn't
reported in RTM_NEWROUTE IPv6 events. This keeps IPv6 internal
consistency (same flag semantic for user requests and kernel events) at
the cost of bringing different flag interpretation for IPv4 and IPv6.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e895cdce 73483c12
...@@ -1081,7 +1081,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1081,7 +1081,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
struct trie *t = (struct trie *)tb->tb_data; struct trie *t = (struct trie *)tb->tb_data;
struct fib_alias *fa, *new_fa; struct fib_alias *fa, *new_fa;
struct key_vector *l, *tp; struct key_vector *l, *tp;
unsigned int nlflags = 0; u16 nlflags = NLM_F_EXCL;
struct fib_info *fi; struct fib_info *fi;
u8 plen = cfg->fc_dst_len; u8 plen = cfg->fc_dst_len;
u8 slen = KEYLENGTH - plen; u8 slen = KEYLENGTH - plen;
...@@ -1126,6 +1126,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1126,6 +1126,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
if (cfg->fc_nlflags & NLM_F_EXCL) if (cfg->fc_nlflags & NLM_F_EXCL)
goto out; goto out;
nlflags &= ~NLM_F_EXCL;
/* We have 2 goals: /* We have 2 goals:
* 1. Find exact match for type, scope, fib_info to avoid * 1. Find exact match for type, scope, fib_info to avoid
* duplicate routes * duplicate routes
...@@ -1151,6 +1153,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1151,6 +1153,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
struct fib_info *fi_drop; struct fib_info *fi_drop;
u8 state; u8 state;
nlflags |= NLM_F_REPLACE;
fa = fa_first; fa = fa_first;
if (fa_match) { if (fa_match) {
if (fa == fa_match) if (fa == fa_match)
...@@ -1191,7 +1194,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1191,7 +1194,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
if (state & FA_S_ACCESSED) if (state & FA_S_ACCESSED)
rt_cache_flush(cfg->fc_nlinfo.nl_net); rt_cache_flush(cfg->fc_nlinfo.nl_net);
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); tb->tb_id, &cfg->fc_nlinfo, nlflags);
goto succeeded; goto succeeded;
} }
...@@ -1203,7 +1206,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1203,7 +1206,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
goto out; goto out;
if (cfg->fc_nlflags & NLM_F_APPEND) if (cfg->fc_nlflags & NLM_F_APPEND)
nlflags = NLM_F_APPEND; nlflags |= NLM_F_APPEND;
else else
fa = fa_first; fa = fa_first;
} }
...@@ -1211,6 +1214,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1211,6 +1214,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
if (!(cfg->fc_nlflags & NLM_F_CREATE)) if (!(cfg->fc_nlflags & NLM_F_CREATE))
goto out; goto out;
nlflags |= NLM_F_CREATE;
err = -ENOBUFS; err = -ENOBUFS;
new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
if (!new_fa) if (!new_fa)
......
...@@ -743,6 +743,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -743,6 +743,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
(info->nlh->nlmsg_flags & NLM_F_CREATE)); (info->nlh->nlmsg_flags & NLM_F_CREATE));
int found = 0; int found = 0;
bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); bool rt_can_ecmp = rt6_qualify_for_ecmp(rt);
u16 nlflags = NLM_F_EXCL;
int err; int err;
ins = &fn->leaf; ins = &fn->leaf;
...@@ -759,6 +760,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -759,6 +760,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
if (info->nlh && if (info->nlh &&
(info->nlh->nlmsg_flags & NLM_F_EXCL)) (info->nlh->nlmsg_flags & NLM_F_EXCL))
return -EEXIST; return -EEXIST;
nlflags &= ~NLM_F_EXCL;
if (replace) { if (replace) {
if (rt_can_ecmp == rt6_qualify_for_ecmp(iter)) { if (rt_can_ecmp == rt6_qualify_for_ecmp(iter)) {
found++; found++;
...@@ -856,6 +859,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -856,6 +859,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
pr_warn("NLM_F_CREATE should be set when creating new route\n"); pr_warn("NLM_F_CREATE should be set when creating new route\n");
add: add:
nlflags |= NLM_F_CREATE;
err = fib6_commit_metrics(&rt->dst, mxc); err = fib6_commit_metrics(&rt->dst, mxc);
if (err) if (err)
return err; return err;
...@@ -864,7 +868,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -864,7 +868,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
*ins = rt; *ins = rt;
rt->rt6i_node = fn; rt->rt6i_node = fn;
atomic_inc(&rt->rt6i_ref); atomic_inc(&rt->rt6i_ref);
inet6_rt_notify(RTM_NEWROUTE, rt, info, 0); inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags);
info->nl_net->ipv6.rt6_stats->fib_rt_entries++; info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
if (!(fn->fn_flags & RTN_RTINFO)) { if (!(fn->fn_flags & RTN_RTINFO)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment