diff options
author | David Ahern <dsahern@gmail.com> | 2019-04-16 17:36:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-04-18 02:10:47 -0400 |
commit | b7bc4b6a620becacbc70fc617b8bbdb16f401f85 (patch) | |
tree | 918c22664c7e9f3130542ad3a8b636d6ec28d0de | |
parent | 75ef7389dd2339e5f2a7347aadbdbded8dd8430f (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.c | 82 |
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 | ||
698 | static void __find_rr_leaf(struct fib6_info *rt_start, | 698 | static 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 | ||
724 | static struct fib6_info *find_rr_leaf(struct fib6_node *fn, | 726 | static 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 | ||
748 | static struct fib6_info *rt6_select(struct net *net, struct fib6_node *fn, | 747 | static 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; | 795 | out: |
796 | if (!res->f6i) { | ||
797 | res->f6i = net->ipv6.fib6_null_entry; | ||
798 | res->nh = &res->f6i->fib6_nh; | ||
799 | } | ||
796 | } | 800 | } |
797 | 801 | ||
798 | static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res) | 802 | static 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 | ||
1850 | redo_rt6_select: | 1854 | redo_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 | ||
1869 | struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, | 1873 | struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, |