summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2019-04-16 17:36:08 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-18 02:10:47 -0400
commitb7bc4b6a620becacbc70fc617b8bbdb16f401f85 (patch)
tree918c22664c7e9f3130542ad3a8b636d6ec28d0de
parent75ef7389dd2339e5f2a7347aadbdbded8dd8430f (diff)
ipv6: Pass fib6_result to rt6_select and find_rr_leaf
Pass fib6_result to rt6_select. Instead of returning the fib entry, it will set f6i and nh based on the lookup. find_rr_leaf is changed to remove the match option in favor of taking fib6_result and having __find_rr_leaf set f6i in the result. In the process, update fib6_info references in __find_rr_leaf to f6i names. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/route.c82
1 files changed, 43 insertions, 39 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 6bea5ac05982..a466e2e478e8 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -695,66 +695,68 @@ out:
695 return rc; 695 return rc;
696} 696}
697 697
698static void __find_rr_leaf(struct fib6_info *rt_start, 698static void __find_rr_leaf(struct fib6_info *f6i_start,
699 struct fib6_info *nomatch, u32 metric, 699 struct fib6_info *nomatch, u32 metric,
700 struct fib6_info **match, struct fib6_info **cont, 700 struct fib6_result *res, struct fib6_info **cont,
701 int oif, int strict, bool *do_rr, int *mpri) 701 int oif, int strict, bool *do_rr, int *mpri)
702{ 702{
703 struct fib6_info *rt; 703 struct fib6_info *f6i;
704 704
705 for (rt = rt_start; 705 for (f6i = f6i_start;
706 rt && rt != nomatch; 706 f6i && f6i != nomatch;
707 rt = rcu_dereference(rt->fib6_next)) { 707 f6i = rcu_dereference(f6i->fib6_next)) {
708 struct fib6_nh *nh; 708 struct fib6_nh *nh;
709 709
710 if (cont && rt->fib6_metric != metric) { 710 if (cont && f6i->fib6_metric != metric) {
711 *cont = rt; 711 *cont = f6i;
712 return; 712 return;
713 } 713 }
714 714
715 if (fib6_check_expired(rt)) 715 if (fib6_check_expired(f6i))
716 continue; 716 continue;
717 717
718 nh = &rt->fib6_nh; 718 nh = &f6i->fib6_nh;
719 if (find_match(nh, rt->fib6_flags, oif, strict, mpri, do_rr)) 719 if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
720 *match = rt; 720 res->f6i = f6i;
721 res->nh = nh;
722 }
721 } 723 }
722} 724}
723 725
724static struct fib6_info *find_rr_leaf(struct fib6_node *fn, 726static void find_rr_leaf(struct fib6_node *fn, struct fib6_info *leaf,
725 struct fib6_info *leaf, 727 struct fib6_info *rr_head, int oif, int strict,
726 struct fib6_info *rr_head, 728 bool *do_rr, struct fib6_result *res)
727 u32 metric, int oif, int strict,
728 bool *do_rr)
729{ 729{
730 struct fib6_info *match = NULL, *cont = NULL; 730 u32 metric = rr_head->fib6_metric;
731 struct fib6_info *cont = NULL;
731 int mpri = -1; 732 int mpri = -1;
732 733
733 __find_rr_leaf(rr_head, NULL, metric, &match, &cont, 734 __find_rr_leaf(rr_head, NULL, metric, res, &cont,
734 oif, strict, do_rr, &mpri); 735 oif, strict, do_rr, &mpri);
735 736
736 __find_rr_leaf(leaf, rr_head, metric, &match, &cont, 737 __find_rr_leaf(leaf, rr_head, metric, res, &cont,
737 oif, strict, do_rr, &mpri); 738 oif, strict, do_rr, &mpri);
738 739
739 if (match || !cont) 740 if (res->f6i || !cont)
740 return match; 741 return;
741 742
742 __find_rr_leaf(cont, NULL, metric, &match, NULL, 743 __find_rr_leaf(cont, NULL, metric, res, NULL,
743 oif, strict, do_rr, &mpri); 744 oif, strict, do_rr, &mpri);
744
745 return match;
746} 745}
747 746
748static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn, 747static void rt6_select(struct net *net, struct fib6_node *fn, int oif,
749 int oif, int strict) 748 struct fib6_result *res, int strict)
750{ 749{
751 struct fib6_info *leaf = rcu_dereference(fn->leaf); 750 struct fib6_info *leaf = rcu_dereference(fn->leaf);
752 struct fib6_info *match, *rt0; 751 struct fib6_info *rt0;
753 bool do_rr = false; 752 bool do_rr = false;
754 int key_plen; 753 int key_plen;
755 754
755 /* make sure this function or its helpers sets f6i */
756 res->f6i = NULL;
757
756 if (!leaf || leaf == net->ipv6.fib6_null_entry) 758 if (!leaf || leaf == net->ipv6.fib6_null_entry)
757 return net->ipv6.fib6_null_entry; 759 goto out;
758 760
759 rt0 = rcu_dereference(fn->rr_ptr); 761 rt0 = rcu_dereference(fn->rr_ptr);
760 if (!rt0) 762 if (!rt0)
@@ -771,11 +773,9 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
771 key_plen = rt0->fib6_src.plen; 773 key_plen = rt0->fib6_src.plen;
772#endif 774#endif
773 if (fn->fn_bit != key_plen) 775 if (fn->fn_bit != key_plen)
774 return net->ipv6.fib6_null_entry; 776 goto out;
775
776 match = find_rr_leaf(fn, leaf, rt0, rt0->fib6_metric, oif, strict,
777 &do_rr);
778 777
778 find_rr_leaf(fn, leaf, rt0, oif, strict, &do_rr, res);
779 if (do_rr) { 779 if (do_rr) {
780 struct fib6_info *next = rcu_dereference(rt0->fib6_next); 780 struct fib6_info *next = rcu_dereference(rt0->fib6_next);
781 781
@@ -792,7 +792,11 @@ static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn,
792 } 792 }
793 } 793 }
794 794
795 return match ? match : net->ipv6.fib6_null_entry; 795out:
796 if (!res->f6i) {
797 res->f6i = net->ipv6.fib6_null_entry;
798 res->nh = &res->f6i->fib6_nh;
799 }
796} 800}
797 801
798static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res) 802static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res)
@@ -1839,7 +1843,7 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
1839 int oif, struct flowi6 *fl6, int strict) 1843 int oif, struct flowi6 *fl6, int strict)
1840{ 1844{
1841 struct fib6_node *fn, *saved_fn; 1845 struct fib6_node *fn, *saved_fn;
1842 struct fib6_info *f6i; 1846 struct fib6_result res;
1843 1847
1844 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 1848 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
1845 saved_fn = fn; 1849 saved_fn = fn;
@@ -1848,8 +1852,8 @@ struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
1848 oif = 0; 1852 oif = 0;
1849 1853
1850redo_rt6_select: 1854redo_rt6_select:
1851 f6i = rt6_select(net, fn, oif, strict); 1855 rt6_select(net, fn, oif, &res, strict);
1852 if (f6i == net->ipv6.fib6_null_entry) { 1856 if (res.f6i == net->ipv6.fib6_null_entry) {
1853 fn = fib6_backtrack(fn, &fl6->saddr); 1857 fn = fib6_backtrack(fn, &fl6->saddr);
1854 if (fn) 1858 if (fn)
1855 goto redo_rt6_select; 1859 goto redo_rt6_select;
@@ -1861,9 +1865,9 @@ redo_rt6_select:
1861 } 1865 }
1862 } 1866 }
1863 1867
1864 trace_fib6_table_lookup(net, f6i, table, fl6); 1868 trace_fib6_table_lookup(net, res.f6i, table, fl6);
1865 1869
1866 return f6i; 1870 return res.f6i;
1867} 1871}
1868 1872
1869struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, 1873struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,