From: David Ahern <dsah...@gmail.com>

Add nexthop selection to fib_result and update FIB_RES macros to
use it. Right now, fib_nh in fib_result will point to a nexthop
within a fib_info. Later, fib_nh can point to data with a nexthop.

Signed-off-by: David Ahern <dsah...@gmail.com>
---
 include/net/ip_fib.h     | 21 +++++++++------------
 net/core/filter.c        |  2 +-
 net/ipv4/fib_frontend.c  |  4 ++--
 net/ipv4/fib_semantics.c |  4 ++--
 net/ipv4/fib_trie.c      |  4 ++--
 net/ipv4/route.c         | 18 +++++++++---------
 6 files changed, 25 insertions(+), 28 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index ce9b92485064..0b40c59b8a5f 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -141,6 +141,7 @@ struct fib_result {
        unsigned char   type;
        unsigned char   scope;
        u32             tclassid;
+       struct fib_nh   *nh;
        struct fib_info *fi;
        struct fib_table *table;
        struct hlist_head *fa_head;
@@ -161,11 +162,7 @@ struct fib_result_nl {
        int             err;
 };
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-#define FIB_RES_NH(res)                ((res).fi->fib_nh[(res).nh_sel])
-#else /* CONFIG_IP_ROUTE_MULTIPATH */
-#define FIB_RES_NH(res)                ((res).fi->fib_nh[0])
-#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+#define FIB_RES_NH(res)                ((res).nh)
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 #define FIB_TABLE_HASHSZ 256
@@ -177,13 +174,13 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct 
fib_nh *nh,
                                unsigned char scope);
 
 #define FIB_RES_SADDR(net, res)                                \
-       ((FIB_RES_NH(res).nh_saddr_genid ==             \
+       ((FIB_RES_NH(res)->nh_saddr_genid ==            \
          atomic_read(&(net)->ipv4.dev_addr_genid)) ?   \
-        FIB_RES_NH(res).nh_saddr :                     \
-        fib_info_update_nh_saddr((net), &FIB_RES_NH(res), (res).fi->fib_scope))
-#define FIB_RES_GW(res)                        (FIB_RES_NH(res).nh_gw)
-#define FIB_RES_DEV(res)               (FIB_RES_NH(res).nh_dev)
-#define FIB_RES_OIF(res)               (FIB_RES_NH(res).nh_oif)
+        FIB_RES_NH(res)->nh_saddr :                    \
+        fib_info_update_nh_saddr((net), FIB_RES_NH(res), (res).fi->fib_scope))
+#define FIB_RES_GW(res)                        (FIB_RES_NH(res)->nh_gw)
+#define FIB_RES_DEV(res)               (FIB_RES_NH(res)->nh_dev)
+#define FIB_RES_OIF(res)               (FIB_RES_NH(res)->nh_oif)
 
 #define FIB_RES_PREFSRC(net, res)      ((res).fi->fib_prefsrc ? : \
                                         FIB_RES_SADDR(net, res))
@@ -422,7 +419,7 @@ static inline void fib_combine_itag(u32 *itag, const struct 
fib_result *res)
 #ifdef CONFIG_IP_MULTIPLE_TABLES
        u32 rtag;
 #endif
-       *itag = FIB_RES_NH(*res).nh_tclassid<<16;
+       *itag = FIB_RES_NH(*res)->nh_tclassid << 16;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
        rtag = res->tclassid;
        if (*itag == 0)
diff --git a/net/core/filter.c b/net/core/filter.c
index c25eb36f1320..0ba4c477415d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4311,7 +4311,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct 
bpf_fib_lookup *params,
                        return BPF_FIB_LKUP_RET_FRAG_NEEDED;
        }
 
-       nh = &res.fi->fib_nh[res.nh_sel];
+       nh = res.nh;
 
        /* do not handle lwt encaps right now */
        if (nh->nh_lwtstate)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index b0910d8c8bd4..2f9bf1ec2678 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -380,7 +380,7 @@ static int __fib_validate_source(struct sk_buff *skb, 
__be32 src, __be32 dst,
                dev_match = true;
 #endif
        if (dev_match) {
-               ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+               ret = FIB_RES_NH(res)->nh_scope >= RT_SCOPE_HOST;
                return ret;
        }
        if (no_addr)
@@ -392,7 +392,7 @@ static int __fib_validate_source(struct sk_buff *skb, 
__be32 src, __be32 dst,
        ret = 0;
        if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
                if (res.type == RTN_UNICAST)
-                       ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+                       ret = FIB_RES_NH(res)->nh_scope >= RT_SCOPE_HOST;
        }
        return ret;
 
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 0d792666821a..53e38ecfdd58 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1728,7 +1728,7 @@ void fib_select_multipath(struct fib_result *res, int 
hash)
                        if (!fib_good_nh(nh))
                                continue;
                        if (!first) {
-                               res->nh_sel = nhsel;
+                               res->nh = &fi->fib_nh[nhsel];
                                first = true;
                        }
                }
@@ -1736,7 +1736,7 @@ void fib_select_multipath(struct fib_result *res, int 
hash)
                if (hash > atomic_read(&nh->nh_upper_bound))
                        continue;
 
-               res->nh_sel = nhsel;
+               res->nh = &fi->fib_nh[nhsel];
                return;
        } endfor_nexthops(fi);
 }
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 5bc0c89e81e4..51e7b38f3a7b 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1468,7 +1468,7 @@ int fib_table_lookup(struct fib_table *tb, const struct 
flowi4 *flp,
                if (fi->fib_flags & RTNH_F_DEAD)
                        continue;
                for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
-                       const struct fib_nh *nh = &fi->fib_nh[nhsel];
+                       struct fib_nh *nh = &fi->fib_nh[nhsel];
                        struct in_device *in_dev = __in_dev_get_rcu(nh->nh_dev);
 
                        if (nh->nh_flags & RTNH_F_DEAD)
@@ -1489,7 +1489,7 @@ int fib_table_lookup(struct fib_table *tb, const struct 
flowi4 *flp,
 
                        res->prefix = htonl(n->key);
                        res->prefixlen = KEYLENGTH - fa->fa_slen;
-                       res->nh_sel = nhsel;
+                       res->nh = nh;
                        res->type = fa->fa_type;
                        res->scope = fi->fib_scope;
                        res->fi = fi;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index b678466da451..1297c7c934a8 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -776,7 +776,7 @@ static void __ip_do_redirect(struct rtable *rt, struct 
sk_buff *skb, struct flow
                        neigh_event_send(n, NULL);
                } else {
                        if (fib_lookup(net, fl4, &res, 0) == 0) {
-                               struct fib_nh *nh = &FIB_RES_NH(res);
+                               struct fib_nh *nh = FIB_RES_NH(res);
 
                                update_or_create_fnhe(nh, fl4->daddr, new_gw,
                                                0, false,
@@ -1021,7 +1021,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct 
flowi4 *fl4, u32 mtu)
 
        rcu_read_lock();
        if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
-               struct fib_nh *nh = &FIB_RES_NH(res);
+               struct fib_nh *nh = FIB_RES_NH(res);
 
                update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock,
                                      jiffies + ip_rt_mtu_expires);
@@ -1350,7 +1350,7 @@ static struct fib_nh_exception *find_exception(struct 
fib_nh *nh, __be32 daddr)
 u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
 {
        struct fib_info *fi = res->fi;
-       struct fib_nh *nh = &fi->fib_nh[res->nh_sel];
+       struct fib_nh *nh = res->nh;
        struct net_device *dev = nh->nh_dev;
        u32 mtu = 0;
 
@@ -1527,7 +1527,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 
daddr,
        bool cached = false;
 
        if (fi) {
-               struct fib_nh *nh = &FIB_RES_NH(*res);
+               struct fib_nh *nh = FIB_RES_NH(*res);
 
                if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) {
                        rt->rt_gateway = nh->nh_gw;
@@ -1744,12 +1744,12 @@ static int __mkroute_input(struct sk_buff *skb,
                }
        }
 
-       fnhe = find_exception(&FIB_RES_NH(*res), daddr);
+       fnhe = find_exception(FIB_RES_NH(*res), daddr);
        if (do_cache) {
                if (fnhe)
                        rth = rcu_dereference(fnhe->fnhe_rth_input);
                else
-                       rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+                       rth = rcu_dereference(FIB_RES_NH(*res)->nh_rth_input);
                if (rt_cache_valid(rth)) {
                        skb_dst_set_noref(skb, &rth->dst);
                        goto out;
@@ -2039,7 +2039,7 @@ out:      return err;
        do_cache = false;
        if (res->fi) {
                if (!itag) {
-                       rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+                       rth = rcu_dereference(FIB_RES_NH(*res)->nh_rth_input);
                        if (rt_cache_valid(rth)) {
                                skb_dst_set_noref(skb, &rth->dst);
                                err = 0;
@@ -2069,7 +2069,7 @@ out:      return err;
        }
 
        if (do_cache) {
-               struct fib_nh *nh = &FIB_RES_NH(*res);
+               struct fib_nh *nh = FIB_RES_NH(*res);
 
                rth->dst.lwtstate = lwtstate_get(nh->nh_lwtstate);
                if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
@@ -2249,7 +2249,7 @@ static struct rtable *__mkroute_output(const struct 
fib_result *res,
        do_cache &= fi != NULL;
        if (fi) {
                struct rtable __rcu **prth;
-               struct fib_nh *nh = &FIB_RES_NH(*res);
+               struct fib_nh *nh = FIB_RES_NH(*res);
 
                fnhe = find_exception(nh, fl4->daddr);
                if (!do_cache)
-- 
2.11.0

Reply via email to