On 6/19/19 5:59 PM, Stefano Brivio wrote: > diff --git a/include/net/route.h b/include/net/route.h > index 065b47754f05..e7f65388a6d4 100644 > --- a/include/net/route.h > +++ b/include/net/route.h > @@ -44,6 +44,7 @@ > #define RT_CONN_FLAGS_TOS(sk,tos) (RT_TOS(tos) | sock_flag(sk, > SOCK_LOCALROUTE)) > > struct fib_nh; > +struct fib_alias; > struct fib_info; > struct uncached_list; > struct rtable {
we should not expose fib_alias to route.c. > @@ -230,6 +231,9 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 > new_metric); > void rt_add_uncached_list(struct rtable *rt); > void rt_del_uncached_list(struct rtable *rt); > > +int fnhe_dump_buckets(struct fib_alias *fa, int nhsel, struct sk_buff *skb, > + struct netlink_callback *cb, int *fa_index, int fa_start); > + > static inline void ip_rt_put(struct rtable *rt) > { > /* dst_release() accepts a NULL parameter. > diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c > index 94e5d83db4db..03f51e5192e5 100644 > --- a/net/ipv4/fib_trie.c > +++ b/net/ipv4/fib_trie.c > @@ -2078,28 +2078,51 @@ void fib_free_table(struct fib_table *tb) > call_rcu(&tb->rcu, __trie_free_rcu); > } > > +static int fib_dump_fnhe_from_leaf(struct fib_alias *fa, struct sk_buff *skb, > + struct netlink_callback *cb, > + int *fa_index, int fa_start) > +{ > + struct fib_info *fi = fa->fa_info; > + int nhsel; > + > + if (!fi || fi->fib_flags & RTNH_F_DEAD) > + return 0; > + > + for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) { > + int err; > + > + err = fnhe_dump_buckets(fa, nhsel, skb, cb, fa_index, fa_start); > + if (err) > + return err; > + } > + > + return 0; > +} fib_info would be the better argument to pass in to the fnhe dump, and I think the loop over where the bucket is should be in route.c as well. So how about fib_info_dump_fnhe() as the helper exposed from route.c, and it does the loop over nexthops and calls fnhe_dump_buckets. As for the loop, you could fill an skb without finishing a bucket inside of a nexthop so you need top track which nexthop is current as well.