Commit d4ead6b3 authored by David Ahern's avatar David Ahern Committed by David S. Miller

net/ipv6: move metrics from dst to rt6_info

Similar to IPv4, add fib metrics to the fib struct, which at the moment
is rt6_info. Will be moved to fib6_info in a later patch. Copy metrics
into dst by reference using refcount.

To make the transition:
- add dst_metrics to rt6_info. Default to dst_default_metrics if no
  metrics are passed during route add. No need for a separate pmtu
  entry; it can reference the MTU slot in fib6_metrics

- ip6_convert_metrics allocates memory in the FIB entry and uses
  ip_metrics_convert to copy from netlink attribute to metrics entry

- the convert metrics call is done in ip6_route_info_create simplifying
  the route add path
  + fib6_commit_metrics and fib6_copy_metrics and the temporary
    mx6_config are no longer needed

- add fib6_metric_set helper to change the value of a metric in the
  fib entry since dst_metric_set can no longer be used

- cow_metrics for IPv6 can drop to dst_cow_metrics_generic

- rt6_dst_from_metrics_check is no longer needed

- rt6_fill_node needs the FIB entry and dst as separate arguments to
  keep compatibility with existing output. Current dst address is
  renamed to dest.
  (to be consistent with IPv4 rt6_fill_node really should be split
  into 2 functions similar to fib_dump_info and rt_fill_info)

- rt6_fill_node no longer needs the temporary metrics variable
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6edb3c96
...@@ -94,11 +94,6 @@ struct fib6_gc_args { ...@@ -94,11 +94,6 @@ struct fib6_gc_args {
#define FIB6_SUBTREE(fn) (rcu_dereference_protected((fn)->subtree, 1)) #define FIB6_SUBTREE(fn) (rcu_dereference_protected((fn)->subtree, 1))
#endif #endif
struct mx6_config {
const u32 *mx;
DECLARE_BITMAP(mx_valid, RTAX_MAX);
};
/* /*
* routing information * routing information
* *
...@@ -176,7 +171,6 @@ struct rt6_info { ...@@ -176,7 +171,6 @@ struct rt6_info {
struct rt6_exception_bucket __rcu *rt6i_exception_bucket; struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
u32 rt6i_metric; u32 rt6i_metric;
u32 rt6i_pmtu;
/* more non-fragment space at head required */ /* more non-fragment space at head required */
unsigned short rt6i_nfheader_len; unsigned short rt6i_nfheader_len;
u8 rt6i_protocol; u8 rt6i_protocol;
...@@ -185,6 +179,8 @@ struct rt6_info { ...@@ -185,6 +179,8 @@ struct rt6_info {
should_flush:1, should_flush:1,
unused:6; unused:6;
struct dst_metrics *fib6_metrics;
#define fib6_pmtu fib6_metrics->metrics[RTAX_MTU-1]
struct fib6_nh fib6_nh; struct fib6_nh fib6_nh;
}; };
...@@ -390,8 +386,7 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), ...@@ -390,8 +386,7 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
void *arg); void *arg);
int fib6_add(struct fib6_node *root, struct rt6_info *rt, int fib6_add(struct fib6_node *root, struct rt6_info *rt,
struct nl_info *info, struct mx6_config *mxc, struct nl_info *info, struct netlink_ext_ack *extack);
struct netlink_ext_ack *extack);
int fib6_del(struct rt6_info *rt, struct nl_info *info); int fib6_del(struct rt6_info *rt, struct nl_info *info);
void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info, void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info,
...@@ -420,6 +415,12 @@ int fib6_tables_dump(struct net *net, struct notifier_block *nb); ...@@ -420,6 +415,12 @@ int fib6_tables_dump(struct net *net, struct notifier_block *nb);
void fib6_update_sernum(struct net *net, struct rt6_info *rt); void fib6_update_sernum(struct net *net, struct rt6_info *rt);
void fib6_update_sernum_upto_root(struct net *net, struct rt6_info *rt); void fib6_update_sernum_upto_root(struct net *net, struct rt6_info *rt);
void fib6_metric_set(struct rt6_info *f6i, int metric, u32 val);
static inline bool fib6_metric_locked(struct rt6_info *f6i, int metric)
{
return !!(f6i->fib6_metrics->metrics[RTAX_LOCK - 1] & (1 << metric));
}
#ifdef CONFIG_IPV6_MULTIPLE_TABLES #ifdef CONFIG_IPV6_MULTIPLE_TABLES
int fib6_rules_init(void); int fib6_rules_init(void);
void fib6_rules_cleanup(void); void fib6_rules_cleanup(void);
......
...@@ -58,6 +58,7 @@ const struct dst_metrics dst_default_metrics = { ...@@ -58,6 +58,7 @@ const struct dst_metrics dst_default_metrics = {
*/ */
.refcnt = REFCOUNT_INIT(1), .refcnt = REFCOUNT_INIT(1),
}; };
EXPORT_SYMBOL(dst_default_metrics);
void dst_init(struct dst_entry *dst, struct dst_ops *ops, void dst_init(struct dst_entry *dst, struct dst_ops *ops,
struct net_device *dev, int initial_ref, int initial_obsolete, struct net_device *dev, int initial_ref, int initial_obsolete,
......
...@@ -578,6 +578,24 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -578,6 +578,24 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
return res; return res;
} }
void fib6_metric_set(struct rt6_info *f6i, int metric, u32 val)
{
if (!f6i)
return;
if (f6i->fib6_metrics == &dst_default_metrics) {
struct dst_metrics *p = kzalloc(sizeof(*p), GFP_ATOMIC);
if (!p)
return;
refcount_set(&p->refcnt, 1);
f6i->fib6_metrics = p;
}
f6i->fib6_metrics->metrics[metric - 1] = val;
}
/* /*
* Routing Table * Routing Table
* *
...@@ -801,38 +819,6 @@ static struct fib6_node *fib6_add_1(struct net *net, ...@@ -801,38 +819,6 @@ static struct fib6_node *fib6_add_1(struct net *net,
return ln; return ln;
} }
static void fib6_copy_metrics(u32 *mp, const struct mx6_config *mxc)
{
int i;
for (i = 0; i < RTAX_MAX; i++) {
if (test_bit(i, mxc->mx_valid))
mp[i] = mxc->mx[i];
}
}
static int fib6_commit_metrics(struct dst_entry *dst, struct mx6_config *mxc)
{
if (!mxc->mx)
return 0;
if (dst->flags & DST_HOST) {
u32 *mp = dst_metrics_write_ptr(dst);
if (unlikely(!mp))
return -ENOMEM;
fib6_copy_metrics(mp, mxc);
} else {
dst_init_metrics(dst, mxc->mx, false);
/* We've stolen mx now. */
mxc->mx = NULL;
}
return 0;
}
static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn,
struct net *net) struct net *net)
{ {
...@@ -866,7 +852,7 @@ static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, ...@@ -866,7 +852,7 @@ static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn,
*/ */
static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
struct nl_info *info, struct mx6_config *mxc, struct nl_info *info,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct rt6_info *leaf = rcu_dereference_protected(fn->leaf, struct rt6_info *leaf = rcu_dereference_protected(fn->leaf,
...@@ -923,7 +909,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -923,7 +909,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
rt6_clean_expires(iter); rt6_clean_expires(iter);
else else
rt6_set_expires(iter, rt->dst.expires); rt6_set_expires(iter, rt->dst.expires);
iter->rt6i_pmtu = rt->rt6i_pmtu; fib6_metric_set(iter, RTAX_MTU, rt->fib6_pmtu);
return -EEXIST; return -EEXIST;
} }
/* If we have the same destination and the same metric, /* If we have the same destination and the same metric,
...@@ -1002,9 +988,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -1002,9 +988,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
add: add:
nlflags |= NLM_F_CREATE; nlflags |= NLM_F_CREATE;
err = fib6_commit_metrics(&rt->dst, mxc);
if (err)
return err;
err = call_fib6_entry_notifiers(info->nl_net, err = call_fib6_entry_notifiers(info->nl_net,
FIB_EVENT_ENTRY_ADD, FIB_EVENT_ENTRY_ADD,
...@@ -1035,10 +1018,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, ...@@ -1035,10 +1018,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
return -ENOENT; return -ENOENT;
} }
err = fib6_commit_metrics(&rt->dst, mxc);
if (err)
return err;
err = call_fib6_entry_notifiers(info->nl_net, err = call_fib6_entry_notifiers(info->nl_net,
FIB_EVENT_ENTRY_REPLACE, FIB_EVENT_ENTRY_REPLACE,
rt, extack); rt, extack);
...@@ -1135,8 +1114,7 @@ void fib6_update_sernum_upto_root(struct net *net, struct rt6_info *rt) ...@@ -1135,8 +1114,7 @@ void fib6_update_sernum_upto_root(struct net *net, struct rt6_info *rt)
*/ */
int fib6_add(struct fib6_node *root, struct rt6_info *rt, int fib6_add(struct fib6_node *root, struct rt6_info *rt,
struct nl_info *info, struct mx6_config *mxc, struct nl_info *info, struct netlink_ext_ack *extack)
struct netlink_ext_ack *extack)
{ {
struct fib6_table *table = rt->rt6i_table; struct fib6_table *table = rt->rt6i_table;
struct fib6_node *fn, *pn = NULL; struct fib6_node *fn, *pn = NULL;
...@@ -1244,7 +1222,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, ...@@ -1244,7 +1222,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
} }
#endif #endif
err = fib6_add_rt2node(fn, rt, info, mxc, extack); err = fib6_add_rt2node(fn, rt, info, extack);
if (!err) { if (!err) {
__fib6_update_sernum_upto_root(rt, sernum); __fib6_update_sernum_upto_root(rt, sernum);
fib6_start_gc(info->nl_net, rt); fib6_start_gc(info->nl_net, rt);
......
...@@ -1323,9 +1323,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1323,9 +1323,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
ra_msg->icmph.icmp6_hop_limit) { ra_msg->icmph.icmp6_hop_limit) {
if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) { if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
if (rt) fib6_metric_set(rt, RTAX_HOPLIMIT,
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, ra_msg->icmph.icmp6_hop_limit);
ra_msg->icmph.icmp6_hop_limit);
} else { } else {
ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n"); ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n");
} }
...@@ -1477,10 +1476,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1477,10 +1476,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
ND_PRINTK(2, warn, "RA: invalid mtu: %d\n", mtu); ND_PRINTK(2, warn, "RA: invalid mtu: %d\n", mtu);
} else if (in6_dev->cnf.mtu6 != mtu) { } else if (in6_dev->cnf.mtu6 != mtu) {
in6_dev->cnf.mtu6 = mtu; in6_dev->cnf.mtu6 = mtu;
fib6_metric_set(rt, RTAX_MTU, mtu);
if (rt)
dst_metric_set(&rt->dst, RTAX_MTU, mtu);
rt6_mtu_change(skb->dev, mtu); rt6_mtu_change(skb->dev, mtu);
} }
} }
......
This diff is collapsed.
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