ipv6: Pass fib6_result to fib lookups
Change fib6_lookup and fib6_table_lookup to take a fib6_result and set f6i and nh rather than returning a fib6_info. For now both always return 0. A later patch set can make these more like the IPv4 counterparts and return EINVAL, EACCESS, etc based on fib6_type. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8ff2e5b26c
commit
effda4dd97
@ -389,12 +389,13 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
|
|||||||
/* called with rcu lock held; can return error pointer
|
/* called with rcu lock held; can return error pointer
|
||||||
* caller needs to select path
|
* caller needs to select path
|
||||||
*/
|
*/
|
||||||
struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
||||||
int flags);
|
struct fib6_result *res, int flags);
|
||||||
|
|
||||||
/* called with rcu lock held; caller needs to select path */
|
/* called with rcu lock held; caller needs to select path */
|
||||||
struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
|
int fib6_table_lookup(struct net *net, struct fib6_table *table,
|
||||||
int oif, struct flowi6 *fl6, int strict);
|
int oif, struct flowi6 *fl6, struct fib6_result *res,
|
||||||
|
int strict);
|
||||||
|
|
||||||
void fib6_select_path(const struct net *net, struct fib6_result *res,
|
void fib6_select_path(const struct net *net, struct fib6_result *res,
|
||||||
struct flowi6 *fl6, int oif, bool have_oif_match,
|
struct flowi6 *fl6, int oif, bool have_oif_match,
|
||||||
|
@ -29,12 +29,11 @@ struct ipv6_stub {
|
|||||||
int (*ipv6_route_input)(struct sk_buff *skb);
|
int (*ipv6_route_input)(struct sk_buff *skb);
|
||||||
|
|
||||||
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
|
struct fib6_table *(*fib6_get_table)(struct net *net, u32 id);
|
||||||
struct fib6_info *(*fib6_lookup)(struct net *net, int oif,
|
int (*fib6_lookup)(struct net *net, int oif, struct flowi6 *fl6,
|
||||||
struct flowi6 *fl6, int flags);
|
struct fib6_result *res, int flags);
|
||||||
struct fib6_info *(*fib6_table_lookup)(struct net *net,
|
int (*fib6_table_lookup)(struct net *net, struct fib6_table *table,
|
||||||
struct fib6_table *table,
|
int oif, struct flowi6 *fl6,
|
||||||
int oif, struct flowi6 *fl6,
|
struct fib6_result *res, int flags);
|
||||||
int flags);
|
|
||||||
void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
|
void (*fib6_select_path)(const struct net *net, struct fib6_result *res,
|
||||||
struct flowi6 *fl6, int oif, bool oif_match,
|
struct flowi6 *fl6, int oif, bool oif_match,
|
||||||
const struct sk_buff *skb, int strict);
|
const struct sk_buff *skb, int strict);
|
||||||
|
@ -4684,7 +4684,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
|
|||||||
struct inet6_dev *idev;
|
struct inet6_dev *idev;
|
||||||
struct flowi6 fl6;
|
struct flowi6 fl6;
|
||||||
int strict = 0;
|
int strict = 0;
|
||||||
int oif;
|
int oif, err;
|
||||||
u32 mtu;
|
u32 mtu;
|
||||||
|
|
||||||
/* link local addresses are never forwarded */
|
/* link local addresses are never forwarded */
|
||||||
@ -4726,18 +4726,18 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
|
|||||||
if (unlikely(!tb))
|
if (unlikely(!tb))
|
||||||
return BPF_FIB_LKUP_RET_NOT_FWDED;
|
return BPF_FIB_LKUP_RET_NOT_FWDED;
|
||||||
|
|
||||||
res.f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6,
|
err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res,
|
||||||
strict);
|
strict);
|
||||||
} else {
|
} else {
|
||||||
fl6.flowi6_mark = 0;
|
fl6.flowi6_mark = 0;
|
||||||
fl6.flowi6_secid = 0;
|
fl6.flowi6_secid = 0;
|
||||||
fl6.flowi6_tun_key.tun_id = 0;
|
fl6.flowi6_tun_key.tun_id = 0;
|
||||||
fl6.flowi6_uid = sock_net_uid(net, NULL);
|
fl6.flowi6_uid = sock_net_uid(net, NULL);
|
||||||
|
|
||||||
res.f6i = ipv6_stub->fib6_lookup(net, oif, &fl6, strict);
|
err = ipv6_stub->fib6_lookup(net, oif, &fl6, &res, strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(IS_ERR_OR_NULL(res.f6i) ||
|
if (unlikely(err || IS_ERR_OR_NULL(res.f6i) ||
|
||||||
res.f6i == net->ipv6.fib6_null_entry))
|
res.f6i == net->ipv6.fib6_null_entry))
|
||||||
return BPF_FIB_LKUP_RET_NOT_FWDED;
|
return BPF_FIB_LKUP_RET_NOT_FWDED;
|
||||||
|
|
||||||
|
@ -144,18 +144,19 @@ static struct fib6_table *eafnosupport_fib6_get_table(struct net *net, u32 id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fib6_info *
|
static int
|
||||||
eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table,
|
eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table,
|
||||||
int oif, struct flowi6 *fl6, int flags)
|
int oif, struct flowi6 *fl6,
|
||||||
|
struct fib6_result *res, int flags)
|
||||||
{
|
{
|
||||||
return NULL;
|
return -EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fib6_info *
|
static int
|
||||||
eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
||||||
int flags)
|
struct fib6_result *res, int flags)
|
||||||
{
|
{
|
||||||
return NULL;
|
return -EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -61,16 +61,16 @@ unsigned int fib6_rules_seq_read(struct net *net)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* called with rcu lock held; no reference taken on fib6_info */
|
/* called with rcu lock held; no reference taken on fib6_info */
|
||||||
struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
||||||
int flags)
|
struct fib6_result *res, int flags)
|
||||||
{
|
{
|
||||||
struct fib6_info *f6i;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (net->ipv6.fib6_has_custom_rules) {
|
if (net->ipv6.fib6_has_custom_rules) {
|
||||||
struct fib_lookup_arg arg = {
|
struct fib_lookup_arg arg = {
|
||||||
.lookup_ptr = fib6_table_lookup,
|
.lookup_ptr = fib6_table_lookup,
|
||||||
.lookup_data = &oif,
|
.lookup_data = &oif,
|
||||||
|
.result = res,
|
||||||
.flags = FIB_LOOKUP_NOREF,
|
.flags = FIB_LOOKUP_NOREF,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,19 +78,15 @@ struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
|||||||
|
|
||||||
err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
|
err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
|
||||||
flowi6_to_flowi(fl6), flags, &arg);
|
flowi6_to_flowi(fl6), flags, &arg);
|
||||||
if (err)
|
|
||||||
return ERR_PTR(err);
|
|
||||||
|
|
||||||
f6i = arg.result ? : net->ipv6.fib6_null_entry;
|
|
||||||
} else {
|
} else {
|
||||||
f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl,
|
err = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, oif,
|
||||||
oif, fl6, flags);
|
fl6, res, flags);
|
||||||
if (!f6i || f6i == net->ipv6.fib6_null_entry)
|
if (err || res->f6i == net->ipv6.fib6_null_entry)
|
||||||
f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
|
err = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
|
||||||
oif, fl6, flags);
|
oif, fl6, res, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return f6i;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
|
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
|
||||||
@ -157,10 +153,10 @@ static int fib6_rule_saddr(struct net *net, struct fib_rule *rule, int flags,
|
|||||||
static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
|
static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
|
||||||
int flags, struct fib_lookup_arg *arg)
|
int flags, struct fib_lookup_arg *arg)
|
||||||
{
|
{
|
||||||
|
struct fib6_result *res = arg->result;
|
||||||
struct flowi6 *flp6 = &flp->u.ip6;
|
struct flowi6 *flp6 = &flp->u.ip6;
|
||||||
struct net *net = rule->fr_net;
|
struct net *net = rule->fr_net;
|
||||||
struct fib6_table *table;
|
struct fib6_table *table;
|
||||||
struct fib6_info *f6i;
|
|
||||||
int err = -EAGAIN, *oif;
|
int err = -EAGAIN, *oif;
|
||||||
u32 tb_id;
|
u32 tb_id;
|
||||||
|
|
||||||
@ -182,14 +178,10 @@ static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
|
|||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
oif = (int *)arg->lookup_data;
|
oif = (int *)arg->lookup_data;
|
||||||
f6i = fib6_table_lookup(net, table, *oif, flp6, flags);
|
err = fib6_table_lookup(net, table, *oif, flp6, res, flags);
|
||||||
if (f6i != net->ipv6.fib6_null_entry) {
|
if (!err && res->f6i != net->ipv6.fib6_null_entry)
|
||||||
err = fib6_rule_saddr(net, rule, flags, flp6,
|
err = fib6_rule_saddr(net, rule, flags, flp6,
|
||||||
fib6_info_nh_dev(f6i));
|
res->nh->fib_nh_dev);
|
||||||
|
|
||||||
if (likely(!err))
|
|
||||||
arg->result = f6i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -354,10 +354,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* called with rcu lock held; no reference taken on fib6_info */
|
/* called with rcu lock held; no reference taken on fib6_info */
|
||||||
struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
|
||||||
int flags)
|
struct fib6_result *res, int flags)
|
||||||
{
|
{
|
||||||
return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6, flags);
|
return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6,
|
||||||
|
res, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_init fib6_tables_init(struct net *net)
|
static void __net_init fib6_tables_init(struct net *net)
|
||||||
|
@ -1839,11 +1839,10 @@ void rt6_age_exceptions(struct fib6_info *rt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* must be called with rcu lock held */
|
/* must be called with rcu lock held */
|
||||||
struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
|
int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
|
||||||
int oif, struct flowi6 *fl6, int strict)
|
struct flowi6 *fl6, struct fib6_result *res, int strict)
|
||||||
{
|
{
|
||||||
struct fib6_node *fn, *saved_fn;
|
struct fib6_node *fn, *saved_fn;
|
||||||
struct fib6_result res;
|
|
||||||
|
|
||||||
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
|
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
|
||||||
saved_fn = fn;
|
saved_fn = fn;
|
||||||
@ -1852,8 +1851,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
|
|||||||
oif = 0;
|
oif = 0;
|
||||||
|
|
||||||
redo_rt6_select:
|
redo_rt6_select:
|
||||||
rt6_select(net, fn, oif, &res, strict);
|
rt6_select(net, fn, oif, res, strict);
|
||||||
if (res.f6i == net->ipv6.fib6_null_entry) {
|
if (res->f6i == net->ipv6.fib6_null_entry) {
|
||||||
fn = fib6_backtrack(fn, &fl6->saddr);
|
fn = fib6_backtrack(fn, &fl6->saddr);
|
||||||
if (fn)
|
if (fn)
|
||||||
goto redo_rt6_select;
|
goto redo_rt6_select;
|
||||||
@ -1865,9 +1864,9 @@ redo_rt6_select:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_fib6_table_lookup(net, &res, table, fl6);
|
trace_fib6_table_lookup(net, res, table, fl6);
|
||||||
|
|
||||||
return res.f6i;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
||||||
@ -1885,7 +1884,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
|||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
res.f6i = fib6_table_lookup(net, table, oif, fl6, strict);
|
fib6_table_lookup(net, table, oif, fl6, &res, strict);
|
||||||
if (res.f6i == net->ipv6.fib6_null_entry) {
|
if (res.f6i == net->ipv6.fib6_null_entry) {
|
||||||
rt = net->ipv6.ip6_null_entry;
|
rt = net->ipv6.ip6_null_entry;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
Loading…
Reference in New Issue
Block a user