Re: [RFC v2 bpf-next 5/9] net/ipv6: Add fib6_lookup

2018-05-01 Thread David Ahern
On 5/1/18 12:15 PM, Vincent Bernat wrote:
>  ❦ 29 avril 2018 11:07 -0700, David Ahern  :
> 
>> +struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
>> +  int flags)
> 
> Maybe an EXPORT_SYMBOL_GPL? There is one for __fib_lookup (fib_lookup is
> an inline function).
> 

There needs to be an in-tree user relying on it. My intention is to
convert rt6_lookup to fib6_lookup; as I recall all of those just want
the egress device and do not need a dst based response. That might
provide the in-tree user - depending on how the conversion is done.

And I presume you are asking for your benchmark modules. I can send you
my diffs and results.


Re: [RFC v2 bpf-next 5/9] net/ipv6: Add fib6_lookup

2018-05-01 Thread Vincent Bernat
 ❦ 29 avril 2018 11:07 -0700, David Ahern  :

> +struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
> +   int flags)

Maybe an EXPORT_SYMBOL_GPL? There is one for __fib_lookup (fib_lookup is
an inline function).
-- 
Use the "telephone test" for readability.
- The Elements of Programming Style (Kernighan & Plauger)


[RFC v2 bpf-next 5/9] net/ipv6: Add fib6_lookup

2018-04-29 Thread David Ahern
Add IPv6 equivalent to fib_lookup. Does a fib lookup, including rules,
but returns a FIB entry, fib6_info, rather than a dst based rt6_info.
fib6_lookup is on the order of 40% faster than any of the dst based
lookup methods without custom rules and 25% faster with custom rules.

Since the lookup function has a completely different signature,
fib6_rule_action is split into 2 paths: the existing one is
renamed __fib6_rule_action and a new one for the fib6_info path
is added. fib6_rule_action decides which to call based on the
lookup_ptr. If it is fib6_table_lookup then the new path is taken.

Caller must hold rcu lock as no reference is taken on the returned
fib entry.

Signed-off-by: David Ahern 
---
 include/net/ip6_fib.h |  6 
 net/ipv6/fib6_rules.c | 86 +--
 net/ipv6/ip6_fib.c|  7 +
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 4f7b8f59ea6d..d920dd00139b 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -376,6 +376,12 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct 
flowi6 *fl6,
   const struct sk_buff *skb,
   int flags, pol_lookup_t lookup);
 
+/* called with rcu lock held; can return error pointer
+ * caller needs to select path
+ */
+struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
+ int flags);
+
 /* called with rcu lock held; caller needs to select path */
 struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
int oif, struct flowi6 *fl6, int strict);
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d040c4bff3a0..f590446595d8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -60,6 +60,39 @@ unsigned int fib6_rules_seq_read(struct net *net)
return fib_rules_seq_read(net, AF_INET6);
 }
 
+/* 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 flags)
+{
+   struct fib6_info *f6i;
+   int err;
+
+   if (net->ipv6.fib6_has_custom_rules) {
+   struct fib_lookup_arg arg = {
+   .lookup_ptr = fib6_table_lookup,
+   .lookup_data = ,
+   .flags = FIB_LOOKUP_NOREF,
+   };
+
+   l3mdev_update_flow(net, flowi6_to_flowi(fl6));
+
+   err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
+  flowi6_to_flowi(fl6), flags, );
+   if (err)
+   return ERR_PTR(err);
+
+   f6i = arg.result ? : net->ipv6.fib6_null_entry;
+   } else {
+   f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl,
+   oif, fl6, flags);
+   if (!f6i || f6i == net->ipv6.fib6_null_entry)
+   f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
+   oif, fl6, flags);
+   }
+
+   return f6i;
+}
+
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
   const struct sk_buff *skb,
   int flags, pol_lookup_t lookup)
@@ -121,8 +154,48 @@ static int fib6_rule_saddr(struct net *net, struct 
fib_rule *rule, int flags,
return 0;
 }
 
-static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
-   int flags, struct fib_lookup_arg *arg)
+static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
+   int flags, struct fib_lookup_arg *arg)
+{
+   struct flowi6 *flp6 = >u.ip6;
+   struct net *net = rule->fr_net;
+   struct fib6_table *table;
+   struct fib6_info *f6i;
+   int err = -EAGAIN, *oif;
+   u32 tb_id;
+
+   switch (rule->action) {
+   case FR_ACT_TO_TBL:
+   break;
+   case FR_ACT_UNREACHABLE:
+   return -ENETUNREACH;
+   case FR_ACT_PROHIBIT:
+   return -EACCES;
+   case FR_ACT_BLACKHOLE:
+   default:
+   return -EINVAL;
+   }
+
+   tb_id = fib_rule_get_table(rule, arg);
+   table = fib6_get_table(net, tb_id);
+   if (!table)
+   return -EAGAIN;
+
+   oif = (int *)arg->lookup_data;
+   f6i = fib6_table_lookup(net, table, *oif, flp6, flags);
+   if (f6i != net->ipv6.fib6_null_entry) {
+   err = fib6_rule_saddr(net, rule, flags, flp6,
+ fib6_info_nh_dev(f6i));
+
+   if (likely(!err))
+   arg->result = f6i;
+   }
+
+   return err;
+}
+
+static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+