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

ipv6: Pass fib6_result to fib lookups

Change fib6_lookup and fib6_table_lookup to take a fib6_result and set
f6i and nh rather than returning a fib6_info. For now both always
return 0.

A later patch set can make these more like the IPv4 counterparts and
return EINVAL, EACCESS, etc based on fib6_type.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ahern and committed by
David S. Miller
effda4dd 8ff2e5b2

+46 -53
+5 -4
include/net/ip6_fib.h
··· 389 389 /* called with rcu lock held; can return error pointer 390 390 * caller needs to select path 391 391 */ 392 - struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 393 - int flags); 392 + int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 393 + struct fib6_result *res, int flags); 394 394 395 395 /* called with rcu lock held; caller needs to select path */ 396 - struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, 397 - int oif, struct flowi6 *fl6, int strict); 396 + int fib6_table_lookup(struct net *net, struct fib6_table *table, 397 + int oif, struct flowi6 *fl6, struct fib6_result *res, 398 + int strict); 398 399 399 400 void fib6_select_path(const struct net *net, struct fib6_result *res, 400 401 struct flowi6 *fl6, int oif, bool have_oif_match,
+5 -6
include/net/ipv6_stubs.h
··· 29 29 int (*ipv6_route_input)(struct sk_buff *skb); 30 30 31 31 struct fib6_table *(*fib6_get_table)(struct net *net, u32 id); 32 - struct fib6_info *(*fib6_lookup)(struct net *net, int oif, 33 - struct flowi6 *fl6, int flags); 34 - struct fib6_info *(*fib6_table_lookup)(struct net *net, 35 - struct fib6_table *table, 36 - int oif, struct flowi6 *fl6, 37 - int flags); 32 + int (*fib6_lookup)(struct net *net, int oif, struct flowi6 *fl6, 33 + struct fib6_result *res, int flags); 34 + int (*fib6_table_lookup)(struct net *net, struct fib6_table *table, 35 + int oif, struct flowi6 *fl6, 36 + struct fib6_result *res, int flags); 38 37 void (*fib6_select_path)(const struct net *net, struct fib6_result *res, 39 38 struct flowi6 *fl6, int oif, bool oif_match, 40 39 const struct sk_buff *skb, int strict);
+5 -5
net/core/filter.c
··· 4684 4684 struct inet6_dev *idev; 4685 4685 struct flowi6 fl6; 4686 4686 int strict = 0; 4687 - int oif; 4687 + int oif, err; 4688 4688 u32 mtu; 4689 4689 4690 4690 /* link local addresses are never forwarded */ ··· 4726 4726 if (unlikely(!tb)) 4727 4727 return BPF_FIB_LKUP_RET_NOT_FWDED; 4728 4728 4729 - res.f6i = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, 4730 - strict); 4729 + err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res, 4730 + strict); 4731 4731 } else { 4732 4732 fl6.flowi6_mark = 0; 4733 4733 fl6.flowi6_secid = 0; 4734 4734 fl6.flowi6_tun_key.tun_id = 0; 4735 4735 fl6.flowi6_uid = sock_net_uid(net, NULL); 4736 4736 4737 - res.f6i = ipv6_stub->fib6_lookup(net, oif, &fl6, strict); 4737 + err = ipv6_stub->fib6_lookup(net, oif, &fl6, &res, strict); 4738 4738 } 4739 4739 4740 - if (unlikely(IS_ERR_OR_NULL(res.f6i) || 4740 + if (unlikely(err || IS_ERR_OR_NULL(res.f6i) || 4741 4741 res.f6i == net->ipv6.fib6_null_entry)) 4742 4742 return BPF_FIB_LKUP_RET_NOT_FWDED; 4743 4743
+7 -6
net/ipv6/addrconf_core.c
··· 144 144 return NULL; 145 145 } 146 146 147 - static struct fib6_info * 147 + static int 148 148 eafnosupport_fib6_table_lookup(struct net *net, struct fib6_table *table, 149 - int oif, struct flowi6 *fl6, int flags) 149 + int oif, struct flowi6 *fl6, 150 + struct fib6_result *res, int flags) 150 151 { 151 - return NULL; 152 + return -EAFNOSUPPORT; 152 153 } 153 154 154 - static struct fib6_info * 155 + static int 155 156 eafnosupport_fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 156 - int flags) 157 + struct fib6_result *res, int flags) 157 158 { 158 - return NULL; 159 + return -EAFNOSUPPORT; 159 160 } 160 161 161 162 static void
+13 -21
net/ipv6/fib6_rules.c
··· 61 61 } 62 62 63 63 /* called with rcu lock held; no reference taken on fib6_info */ 64 - struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 65 - int flags) 64 + int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 65 + struct fib6_result *res, int flags) 66 66 { 67 - struct fib6_info *f6i; 68 67 int err; 69 68 70 69 if (net->ipv6.fib6_has_custom_rules) { 71 70 struct fib_lookup_arg arg = { 72 71 .lookup_ptr = fib6_table_lookup, 73 72 .lookup_data = &oif, 73 + .result = res, 74 74 .flags = FIB_LOOKUP_NOREF, 75 75 }; 76 76 ··· 78 78 79 79 err = fib_rules_lookup(net->ipv6.fib6_rules_ops, 80 80 flowi6_to_flowi(fl6), flags, &arg); 81 - if (err) 82 - return ERR_PTR(err); 83 - 84 - f6i = arg.result ? : net->ipv6.fib6_null_entry; 85 81 } else { 86 - f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, 87 - oif, fl6, flags); 88 - if (!f6i || f6i == net->ipv6.fib6_null_entry) 89 - f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl, 90 - oif, fl6, flags); 82 + err = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, oif, 83 + fl6, res, flags); 84 + if (err || res->f6i == net->ipv6.fib6_null_entry) 85 + err = fib6_table_lookup(net, net->ipv6.fib6_main_tbl, 86 + oif, fl6, res, flags); 91 87 } 92 88 93 - return f6i; 89 + return err; 94 90 } 95 91 96 92 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, ··· 153 157 static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp, 154 158 int flags, struct fib_lookup_arg *arg) 155 159 { 160 + struct fib6_result *res = arg->result; 156 161 struct flowi6 *flp6 = &flp->u.ip6; 157 162 struct net *net = rule->fr_net; 158 163 struct fib6_table *table; 159 - struct fib6_info *f6i; 160 164 int err = -EAGAIN, *oif; 161 165 u32 tb_id; 162 166 ··· 178 182 return -EAGAIN; 179 183 180 184 oif = (int *)arg->lookup_data; 181 - f6i = fib6_table_lookup(net, table, *oif, flp6, flags); 182 - if (f6i != net->ipv6.fib6_null_entry) { 185 + err = fib6_table_lookup(net, table, *oif, flp6, res, flags); 186 + if (!err && res->f6i != net->ipv6.fib6_null_entry) 183 187 err = fib6_rule_saddr(net, rule, flags, flp6, 184 - fib6_info_nh_dev(f6i)); 185 - 186 - if (likely(!err)) 187 - arg->result = f6i; 188 - } 188 + res->nh->fib_nh_dev); 189 189 190 190 return err; 191 191 }
+4 -3
net/ipv6/ip6_fib.c
··· 354 354 } 355 355 356 356 /* called with rcu lock held; no reference taken on fib6_info */ 357 - struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 358 - int flags) 357 + int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6, 358 + struct fib6_result *res, int flags) 359 359 { 360 - return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6, flags); 360 + return fib6_table_lookup(net, net->ipv6.fib6_main_tbl, oif, fl6, 361 + res, flags); 361 362 } 362 363 363 364 static void __net_init fib6_tables_init(struct net *net)
+7 -8
net/ipv6/route.c
··· 1839 1839 } 1840 1840 1841 1841 /* must be called with rcu lock held */ 1842 - struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table, 1843 - int oif, struct flowi6 *fl6, int strict) 1842 + int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif, 1843 + struct flowi6 *fl6, struct fib6_result *res, int strict) 1844 1844 { 1845 1845 struct fib6_node *fn, *saved_fn; 1846 - struct fib6_result res; 1847 1846 1848 1847 fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); 1849 1848 saved_fn = fn; ··· 1851 1852 oif = 0; 1852 1853 1853 1854 redo_rt6_select: 1854 - rt6_select(net, fn, oif, &res, strict); 1855 - if (res.f6i == net->ipv6.fib6_null_entry) { 1855 + rt6_select(net, fn, oif, res, strict); 1856 + if (res->f6i == net->ipv6.fib6_null_entry) { 1856 1857 fn = fib6_backtrack(fn, &fl6->saddr); 1857 1858 if (fn) 1858 1859 goto redo_rt6_select; ··· 1864 1865 } 1865 1866 } 1866 1867 1867 - trace_fib6_table_lookup(net, &res, table, fl6); 1868 + trace_fib6_table_lookup(net, res, table, fl6); 1868 1869 1869 - return res.f6i; 1870 + return 0; 1870 1871 } 1871 1872 1872 1873 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, ··· 1884 1885 1885 1886 rcu_read_lock(); 1886 1887 1887 - res.f6i = fib6_table_lookup(net, table, oif, fl6, strict); 1888 + fib6_table_lookup(net, table, oif, fl6, &res, strict); 1888 1889 if (res.f6i == net->ipv6.fib6_null_entry) { 1889 1890 rt = net->ipv6.ip6_null_entry; 1890 1891 rcu_read_unlock();