Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/ipv6: Pass skb to route lookup

IPv6 does path selection for multipath routes deep in the lookup
functions. The next patch adds L4 hash option and needs the skb
for the forward path. To get the skb to the relevant FIB lookup
functions it needs to go through the fib rules layer, so add a
lookup_data argument to the fib_lookup_arg struct.

Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ahern and committed by
David S. Miller
b75cc8f9 3192dac6

+83 -54
+1 -1
drivers/infiniband/core/cma.c
··· 1334 1334 IPV6_ADDR_LINKLOCAL; 1335 1335 struct rt6_info *rt = rt6_lookup(dev_net(net_dev), &dst_addr->sin6_addr, 1336 1336 &src_addr->sin6_addr, net_dev->ifindex, 1337 - strict); 1337 + NULL, strict); 1338 1338 bool ret; 1339 1339 1340 1340 if (!rt)
+2 -1
drivers/net/ipvlan/ipvlan_core.c
··· 817 817 }; 818 818 819 819 skb_dst_drop(skb); 820 - dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, flags); 820 + dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, 821 + skb, flags); 821 822 skb_dst_set(skb, dst); 822 823 break; 823 824 }
+4 -3
drivers/net/vrf.c
··· 941 941 const struct net_device *dev, 942 942 struct flowi6 *fl6, 943 943 int ifindex, 944 + const struct sk_buff *skb, 944 945 int flags) 945 946 { 946 947 struct net_vrf *vrf = netdev_priv(dev); ··· 960 959 if (!table) 961 960 return NULL; 962 961 963 - return ip6_pol_route(net, table, ifindex, fl6, flags); 962 + return ip6_pol_route(net, table, ifindex, fl6, skb, flags); 964 963 } 965 964 966 965 static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev, ··· 978 977 struct net *net = dev_net(vrf_dev); 979 978 struct rt6_info *rt6; 980 979 981 - rt6 = vrf_ip6_route_lookup(net, vrf_dev, &fl6, ifindex, 980 + rt6 = vrf_ip6_route_lookup(net, vrf_dev, &fl6, ifindex, skb, 982 981 RT6_LOOKUP_F_HAS_SADDR | RT6_LOOKUP_F_IFACE); 983 982 if (unlikely(!rt6)) 984 983 return; ··· 1111 1110 if (!ipv6_addr_any(&fl6->saddr)) 1112 1111 flags |= RT6_LOOKUP_F_HAS_SADDR; 1113 1112 1114 - rt = vrf_ip6_route_lookup(net, dev, fl6, fl6->flowi6_oif, flags); 1113 + rt = vrf_ip6_route_lookup(net, dev, fl6, fl6->flowi6_oif, NULL, flags); 1115 1114 if (rt) 1116 1115 dst = &rt->dst; 1117 1116
+1
include/net/fib_rules.h
··· 47 47 48 48 struct fib_lookup_arg { 49 49 void *lookup_ptr; 50 + const void *lookup_data; 50 51 void *result; 51 52 struct fib_rule *rule; 52 53 u32 table;
+3 -1
include/net/ip6_fib.h
··· 350 350 351 351 typedef struct rt6_info *(*pol_lookup_t)(struct net *, 352 352 struct fib6_table *, 353 - struct flowi6 *, int); 353 + struct flowi6 *, 354 + const struct sk_buff *, int); 354 355 355 356 struct fib6_entry_notifier_info { 356 357 struct fib_notifier_info info; /* must be first */ ··· 365 364 struct fib6_table *fib6_get_table(struct net *net, u32 id); 366 365 struct fib6_table *fib6_new_table(struct net *net, u32 id); 367 366 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, 367 + const struct sk_buff *skb, 368 368 int flags, pol_lookup_t lookup); 369 369 370 370 struct fib6_node *fib6_lookup(struct fib6_node *root,
+7 -4
include/net/ip6_route.h
··· 75 75 void ip6_route_input(struct sk_buff *skb); 76 76 struct dst_entry *ip6_route_input_lookup(struct net *net, 77 77 struct net_device *dev, 78 - struct flowi6 *fl6, int flags); 78 + struct flowi6 *fl6, 79 + const struct sk_buff *skb, int flags); 79 80 80 81 struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, 81 82 struct flowi6 *fl6, int flags); ··· 89 88 } 90 89 91 90 struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, 92 - int flags); 91 + const struct sk_buff *skb, int flags); 93 92 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, 94 - int ifindex, struct flowi6 *fl6, int flags); 93 + int ifindex, struct flowi6 *fl6, 94 + const struct sk_buff *skb, int flags); 95 95 96 96 void ip6_route_init_special_entries(void); 97 97 int ip6_route_init(void); ··· 128 126 } 129 127 130 128 struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, 131 - const struct in6_addr *saddr, int oif, int flags); 129 + const struct in6_addr *saddr, int oif, 130 + const struct sk_buff *skb, int flags); 132 131 u32 rt6_multipath_hash(const struct flowi6 *fl6, const struct sk_buff *skb, 133 132 struct flow_keys *hkeys); 134 133
+1 -1
net/ipv6/anycast.c
··· 78 78 if (ifindex == 0) { 79 79 struct rt6_info *rt; 80 80 81 - rt = rt6_lookup(net, addr, NULL, 0, 0); 81 + rt = rt6_lookup(net, addr, NULL, 0, NULL, 0); 82 82 if (rt) { 83 83 dev = rt->dst.dev; 84 84 ip6_rt_put(rt);
+5 -3
net/ipv6/fib6_rules.c
··· 61 61 } 62 62 63 63 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, 64 + const struct sk_buff *skb, 64 65 int flags, pol_lookup_t lookup) 65 66 { 66 67 if (net->ipv6.fib6_has_custom_rules) { 67 68 struct fib_lookup_arg arg = { 68 69 .lookup_ptr = lookup, 70 + .lookup_data = skb, 69 71 .flags = FIB_LOOKUP_NOREF, 70 72 }; 71 73 ··· 82 80 } else { 83 81 struct rt6_info *rt; 84 82 85 - rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, flags); 83 + rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, skb, flags); 86 84 if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN) 87 85 return &rt->dst; 88 86 ip6_rt_put(rt); 89 - rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); 87 + rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags); 90 88 if (rt->dst.error != -EAGAIN) 91 89 return &rt->dst; 92 90 ip6_rt_put(rt); ··· 132 130 goto out; 133 131 } 134 132 135 - rt = lookup(net, table, flp6, flags); 133 + rt = lookup(net, table, flp6, arg->lookup_data, flags); 136 134 if (rt != net->ipv6.ip6_null_entry) { 137 135 struct fib6_rule *r = (struct fib6_rule *)rule; 138 136
+2 -1
net/ipv6/icmp.c
··· 629 629 skb_pull(skb2, nhs); 630 630 skb_reset_network_header(skb2); 631 631 632 - rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0); 632 + rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 633 + skb, 0); 633 634 634 635 if (rt && rt->dst.dev) 635 636 skb2->dev = rt->dst.dev;
+2 -1
net/ipv6/ip6_fib.c
··· 299 299 } 300 300 301 301 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, 302 + const struct sk_buff *skb, 302 303 int flags, pol_lookup_t lookup) 303 304 { 304 305 struct rt6_info *rt; 305 306 306 - rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); 307 + rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags); 307 308 if (rt->dst.error == -EAGAIN) { 308 309 ip6_rt_put(rt); 309 310 rt = net->ipv6.ip6_null_entry;
+1 -1
net/ipv6/ip6_gre.c
··· 1053 1053 1054 1054 struct rt6_info *rt = rt6_lookup(t->net, 1055 1055 &p->raddr, &p->laddr, 1056 - p->link, strict); 1056 + p->link, NULL, strict); 1057 1057 1058 1058 if (!rt) 1059 1059 return;
+2 -2
net/ipv6/ip6_tunnel.c
··· 679 679 680 680 /* Try to guess incoming interface */ 681 681 rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, 682 - NULL, 0, 0); 682 + NULL, 0, skb2, 0); 683 683 684 684 if (rt && rt->dst.dev) 685 685 skb2->dev = rt->dst.dev; ··· 1444 1444 1445 1445 struct rt6_info *rt = rt6_lookup(t->net, 1446 1446 &p->raddr, &p->laddr, 1447 - p->link, strict); 1447 + p->link, NULL, strict); 1448 1448 1449 1449 if (!rt) 1450 1450 return;
+1 -1
net/ipv6/ip6_vti.c
··· 645 645 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); 646 646 struct rt6_info *rt = rt6_lookup(t->net, 647 647 &p->raddr, &p->laddr, 648 - p->link, strict); 648 + p->link, NULL, strict); 649 649 650 650 if (rt) 651 651 tdev = rt->dst.dev;
+2 -2
net/ipv6/mcast.c
··· 165 165 166 166 if (ifindex == 0) { 167 167 struct rt6_info *rt; 168 - rt = rt6_lookup(net, addr, NULL, 0, 0); 168 + rt = rt6_lookup(net, addr, NULL, 0, NULL, 0); 169 169 if (rt) { 170 170 dev = rt->dst.dev; 171 171 ip6_rt_put(rt); ··· 254 254 struct inet6_dev *idev = NULL; 255 255 256 256 if (ifindex == 0) { 257 - struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0); 257 + struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, NULL, 0); 258 258 259 259 if (rt) { 260 260 dev = rt->dst.dev;
+1 -1
net/ipv6/netfilter/ip6t_rpfilter.c
··· 53 53 lookup_flags |= RT6_LOOKUP_F_IFACE; 54 54 } 55 55 56 - rt = (void *) ip6_route_lookup(net, &fl6, lookup_flags); 56 + rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags); 57 57 if (rt->dst.error) 58 58 goto out; 59 59
+2 -1
net/ipv6/netfilter/nft_fib_ipv6.c
··· 181 181 182 182 *dest = 0; 183 183 again: 184 - rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, lookup_flags); 184 + rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb, 185 + lookup_flags); 185 186 if (rt->dst.error) 186 187 goto put_rt_err; 187 188
+44 -28
net/ipv6/route.c
··· 452 452 453 453 static struct rt6_info *rt6_multipath_select(struct rt6_info *match, 454 454 struct flowi6 *fl6, int oif, 455 + const struct sk_buff *skb, 455 456 int strict) 456 457 { 457 458 struct rt6_info *sibling, *next_sibling; ··· 461 460 * case it will always be non-zero. Otherwise now is the time to do it. 462 461 */ 463 462 if (!fl6->mp_hash) 464 - fl6->mp_hash = rt6_multipath_hash(fl6, NULL, NULL); 463 + fl6->mp_hash = rt6_multipath_hash(fl6, skb, NULL); 465 464 466 465 if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound)) 467 466 return match; ··· 915 914 916 915 static struct rt6_info *ip6_pol_route_lookup(struct net *net, 917 916 struct fib6_table *table, 918 - struct flowi6 *fl6, int flags) 917 + struct flowi6 *fl6, 918 + const struct sk_buff *skb, 919 + int flags) 919 920 { 920 921 struct rt6_info *rt, *rt_cache; 921 922 struct fib6_node *fn; ··· 932 929 rt = rt6_device_match(net, rt, &fl6->saddr, 933 930 fl6->flowi6_oif, flags); 934 931 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) 935 - rt = rt6_multipath_select(rt, fl6, 936 - fl6->flowi6_oif, flags); 932 + rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, 933 + skb, flags); 937 934 } 938 935 if (rt == net->ipv6.ip6_null_entry) { 939 936 fn = fib6_backtrack(fn, &fl6->saddr); ··· 957 954 } 958 955 959 956 struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, 960 - int flags) 957 + const struct sk_buff *skb, int flags) 961 958 { 962 - return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup); 959 + return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_lookup); 963 960 } 964 961 EXPORT_SYMBOL_GPL(ip6_route_lookup); 965 962 966 963 struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, 967 - const struct in6_addr *saddr, int oif, int strict) 964 + const struct in6_addr *saddr, int oif, 965 + const struct sk_buff *skb, int strict) 968 966 { 969 967 struct flowi6 fl6 = { 970 968 .flowi6_oif = oif, ··· 979 975 flags |= RT6_LOOKUP_F_HAS_SADDR; 980 976 } 981 977 982 - dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup); 978 + dst = fib6_rule_lookup(net, &fl6, skb, flags, ip6_pol_route_lookup); 983 979 if (dst->error == 0) 984 980 return (struct rt6_info *) dst; 985 981 ··· 1651 1647 } 1652 1648 1653 1649 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, 1654 - int oif, struct flowi6 *fl6, int flags) 1650 + int oif, struct flowi6 *fl6, 1651 + const struct sk_buff *skb, int flags) 1655 1652 { 1656 1653 struct fib6_node *fn, *saved_fn; 1657 1654 struct rt6_info *rt, *rt_cache; ··· 1674 1669 redo_rt6_select: 1675 1670 rt = rt6_select(net, fn, oif, strict); 1676 1671 if (rt->rt6i_nsiblings) 1677 - rt = rt6_multipath_select(rt, fl6, oif, strict); 1672 + rt = rt6_multipath_select(rt, fl6, oif, skb, strict); 1678 1673 if (rt == net->ipv6.ip6_null_entry) { 1679 1674 fn = fib6_backtrack(fn, &fl6->saddr); 1680 1675 if (fn) ··· 1773 1768 } 1774 1769 EXPORT_SYMBOL_GPL(ip6_pol_route); 1775 1770 1776 - static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, 1777 - struct flowi6 *fl6, int flags) 1771 + static struct rt6_info *ip6_pol_route_input(struct net *net, 1772 + struct fib6_table *table, 1773 + struct flowi6 *fl6, 1774 + const struct sk_buff *skb, 1775 + int flags) 1778 1776 { 1779 - return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); 1777 + return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, skb, flags); 1780 1778 } 1781 1779 1782 1780 struct dst_entry *ip6_route_input_lookup(struct net *net, 1783 1781 struct net_device *dev, 1784 - struct flowi6 *fl6, int flags) 1782 + struct flowi6 *fl6, 1783 + const struct sk_buff *skb, 1784 + int flags) 1785 1785 { 1786 1786 if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG) 1787 1787 flags |= RT6_LOOKUP_F_IFACE; 1788 1788 1789 - return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input); 1789 + return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_input); 1790 1790 } 1791 1791 EXPORT_SYMBOL_GPL(ip6_route_input_lookup); 1792 1792 ··· 1886 1876 if (unlikely(fl6.flowi6_proto == IPPROTO_ICMPV6)) 1887 1877 fl6.mp_hash = rt6_multipath_hash(&fl6, skb, flkeys); 1888 1878 skb_dst_drop(skb); 1889 - skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags)); 1879 + skb_dst_set(skb, 1880 + ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags)); 1890 1881 } 1891 1882 1892 - static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, 1893 - struct flowi6 *fl6, int flags) 1883 + static struct rt6_info *ip6_pol_route_output(struct net *net, 1884 + struct fib6_table *table, 1885 + struct flowi6 *fl6, 1886 + const struct sk_buff *skb, 1887 + int flags) 1894 1888 { 1895 - return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); 1889 + return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags); 1896 1890 } 1897 1891 1898 1892 struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, ··· 1924 1910 else if (sk) 1925 1911 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); 1926 1912 1927 - return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); 1913 + return fib6_rule_lookup(net, fl6, NULL, flags, ip6_pol_route_output); 1928 1914 } 1929 1915 EXPORT_SYMBOL_GPL(ip6_route_output_flags); 1930 1916 ··· 2173 2159 static struct rt6_info *__ip6_route_redirect(struct net *net, 2174 2160 struct fib6_table *table, 2175 2161 struct flowi6 *fl6, 2162 + const struct sk_buff *skb, 2176 2163 int flags) 2177 2164 { 2178 2165 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; ··· 2247 2232 }; 2248 2233 2249 2234 static struct dst_entry *ip6_route_redirect(struct net *net, 2250 - const struct flowi6 *fl6, 2251 - const struct in6_addr *gateway) 2235 + const struct flowi6 *fl6, 2236 + const struct sk_buff *skb, 2237 + const struct in6_addr *gateway) 2252 2238 { 2253 2239 int flags = RT6_LOOKUP_F_HAS_SADDR; 2254 2240 struct ip6rd_flowi rdfl; ··· 2257 2241 rdfl.fl6 = *fl6; 2258 2242 rdfl.gateway = *gateway; 2259 2243 2260 - return fib6_rule_lookup(net, &rdfl.fl6, 2244 + return fib6_rule_lookup(net, &rdfl.fl6, skb, 2261 2245 flags, __ip6_route_redirect); 2262 2246 } 2263 2247 ··· 2277 2261 fl6.flowlabel = ip6_flowinfo(iph); 2278 2262 fl6.flowi6_uid = uid; 2279 2263 2280 - dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr); 2264 + dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr); 2281 2265 rt6_do_redirect(dst, NULL, skb); 2282 2266 dst_release(dst); 2283 2267 } ··· 2299 2283 fl6.saddr = iph->daddr; 2300 2284 fl6.flowi6_uid = sock_net_uid(net, NULL); 2301 2285 2302 - dst = ip6_route_redirect(net, &fl6, &iph->saddr); 2286 + dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr); 2303 2287 rt6_do_redirect(dst, NULL, skb); 2304 2288 dst_release(dst); 2305 2289 } ··· 2501 2485 flags |= RT6_LOOKUP_F_HAS_SADDR; 2502 2486 2503 2487 flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE; 2504 - rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags); 2488 + rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, NULL, flags); 2505 2489 2506 2490 /* if table lookup failed, fall back to full lookup */ 2507 2491 if (rt == net->ipv6.ip6_null_entry) { ··· 2564 2548 } 2565 2549 2566 2550 if (!grt) 2567 - grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); 2551 + grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, NULL, 1); 2568 2552 2569 2553 if (!grt) 2570 2554 goto out; ··· 4629 4613 if (!ipv6_addr_any(&fl6.saddr)) 4630 4614 flags |= RT6_LOOKUP_F_HAS_SADDR; 4631 4615 4632 - dst = ip6_route_input_lookup(net, dev, &fl6, flags); 4616 + dst = ip6_route_input_lookup(net, dev, &fl6, NULL, flags); 4633 4617 4634 4618 rcu_read_unlock(); 4635 4619 } else {
+2 -2
net/ipv6/seg6_local.c
··· 161 161 fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH; 162 162 163 163 if (!tbl_id) { 164 - dst = ip6_route_input_lookup(net, skb->dev, &fl6, flags); 164 + dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags); 165 165 } else { 166 166 struct fib6_table *table; 167 167 ··· 169 169 if (!table) 170 170 goto out; 171 171 172 - rt = ip6_pol_route(net, table, 0, &fl6, flags); 172 + rt = ip6_pol_route(net, table, 0, &fl6, skb, flags); 173 173 dst = &rt->dst; 174 174 } 175 175