1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef _IP6_FIB_H
14#define _IP6_FIB_H
15
16#include <linux/ipv6_route.h>
17#include <linux/rtnetlink.h>
18#include <linux/spinlock.h>
19#include <linux/notifier.h>
20#include <net/dst.h>
21#include <net/flow.h>
22#include <net/netlink.h>
23#include <net/inetpeer.h>
24#include <net/fib_notifier.h>
25
26#ifdef CONFIG_IPV6_MULTIPLE_TABLES
27#define FIB6_TABLE_HASHSZ 256
28#else
29#define FIB6_TABLE_HASHSZ 1
30#endif
31
32#define RT6_DEBUG 2
33
34#if RT6_DEBUG >= 3
35#define RT6_TRACE(x...) pr_debug(x)
36#else
37#define RT6_TRACE(x...) do { ; } while (0)
38#endif
39
40struct rt6_info;
41struct fib6_info;
42
43struct fib6_config {
44 u32 fc_table;
45 u32 fc_metric;
46 int fc_dst_len;
47 int fc_src_len;
48 int fc_ifindex;
49 u32 fc_flags;
50 u32 fc_protocol;
51 u16 fc_type;
52 u16 fc_delete_all_nh : 1,
53 __unused : 15;
54
55 struct in6_addr fc_dst;
56 struct in6_addr fc_src;
57 struct in6_addr fc_prefsrc;
58 struct in6_addr fc_gateway;
59
60 unsigned long fc_expires;
61 struct nlattr *fc_mx;
62 int fc_mx_len;
63 int fc_mp_len;
64 struct nlattr *fc_mp;
65
66 struct nl_info fc_nlinfo;
67 struct nlattr *fc_encap;
68 u16 fc_encap_type;
69};
70
71struct fib6_node {
72 struct fib6_node __rcu *parent;
73 struct fib6_node __rcu *left;
74 struct fib6_node __rcu *right;
75#ifdef CONFIG_IPV6_SUBTREES
76 struct fib6_node __rcu *subtree;
77#endif
78 struct fib6_info __rcu *leaf;
79
80 __u16 fn_bit;
81 __u16 fn_flags;
82 int fn_sernum;
83 struct fib6_info __rcu *rr_ptr;
84 struct rcu_head rcu;
85};
86
87struct fib6_gc_args {
88 int timeout;
89 int more;
90};
91
92#ifndef CONFIG_IPV6_SUBTREES
93#define FIB6_SUBTREE(fn) NULL
94#else
95#define FIB6_SUBTREE(fn) (rcu_dereference_protected((fn)->subtree, 1))
96#endif
97
98
99
100
101
102
103struct rt6key {
104 struct in6_addr addr;
105 int plen;
106};
107
108struct fib6_table;
109
110struct rt6_exception_bucket {
111 struct hlist_head chain;
112 int depth;
113};
114
115struct rt6_exception {
116 struct hlist_node hlist;
117 struct rt6_info *rt6i;
118 unsigned long stamp;
119 struct rcu_head rcu;
120};
121
122#define FIB6_EXCEPTION_BUCKET_SIZE_SHIFT 10
123#define FIB6_EXCEPTION_BUCKET_SIZE (1 << FIB6_EXCEPTION_BUCKET_SIZE_SHIFT)
124#define FIB6_MAX_DEPTH 5
125
126struct fib6_nh {
127 struct in6_addr nh_gw;
128 struct net_device *nh_dev;
129 struct lwtunnel_state *nh_lwtstate;
130
131 unsigned int nh_flags;
132 atomic_t nh_upper_bound;
133 int nh_weight;
134};
135
136struct fib6_info {
137 struct fib6_table *fib6_table;
138 struct fib6_info __rcu *fib6_next;
139 struct fib6_node __rcu *fib6_node;
140
141
142
143
144
145
146 struct list_head fib6_siblings;
147 unsigned int fib6_nsiblings;
148
149 atomic_t fib6_ref;
150 unsigned long expires;
151 struct dst_metrics *fib6_metrics;
152#define fib6_pmtu fib6_metrics->metrics[RTAX_MTU-1]
153
154 struct rt6key fib6_dst;
155 u32 fib6_flags;
156 struct rt6key fib6_src;
157 struct rt6key fib6_prefsrc;
158
159 struct rt6_info * __percpu *rt6i_pcpu;
160 struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
161
162#ifdef CONFIG_IPV6_ROUTER_PREF
163 unsigned long last_probe;
164#endif
165
166 u32 fib6_metric;
167 u8 fib6_protocol;
168 u8 fib6_type;
169 u8 exception_bucket_flushed:1,
170 should_flush:1,
171 dst_nocount:1,
172 dst_nopolicy:1,
173 dst_host:1,
174 unused:3;
175
176 struct fib6_nh fib6_nh;
177 struct rcu_head rcu;
178};
179
180struct rt6_info {
181 struct dst_entry dst;
182 struct fib6_info __rcu *from;
183
184 struct rt6key rt6i_dst;
185 struct rt6key rt6i_src;
186 struct in6_addr rt6i_gateway;
187 struct inet6_dev *rt6i_idev;
188 u32 rt6i_flags;
189 struct rt6key rt6i_prefsrc;
190
191 struct list_head rt6i_uncached;
192 struct uncached_list *rt6i_uncached_list;
193
194
195 unsigned short rt6i_nfheader_len;
196};
197
198#define for_each_fib6_node_rt_rcu(fn) \
199 for (rt = rcu_dereference((fn)->leaf); rt; \
200 rt = rcu_dereference(rt->fib6_next))
201
202#define for_each_fib6_walker_rt(w) \
203 for (rt = (w)->leaf; rt; \
204 rt = rcu_dereference_protected(rt->fib6_next, 1))
205
206static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
207{
208 return ((struct rt6_info *)dst)->rt6i_idev;
209}
210
211static inline void fib6_clean_expires(struct fib6_info *f6i)
212{
213 f6i->fib6_flags &= ~RTF_EXPIRES;
214 f6i->expires = 0;
215}
216
217static inline void fib6_set_expires(struct fib6_info *f6i,
218 unsigned long expires)
219{
220 f6i->expires = expires;
221 f6i->fib6_flags |= RTF_EXPIRES;
222}
223
224static inline bool fib6_check_expired(const struct fib6_info *f6i)
225{
226 if (f6i->fib6_flags & RTF_EXPIRES)
227 return time_after(jiffies, f6i->expires);
228 return false;
229}
230
231
232
233
234
235
236static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i,
237 u32 *cookie)
238{
239 struct fib6_node *fn;
240 bool status = false;
241
242 fn = rcu_dereference(f6i->fib6_node);
243
244 if (fn) {
245 *cookie = fn->fn_sernum;
246
247 smp_rmb();
248 status = true;
249 }
250
251 return status;
252}
253
254static inline u32 rt6_get_cookie(const struct rt6_info *rt)
255{
256 struct fib6_info *from;
257 u32 cookie = 0;
258
259 rcu_read_lock();
260
261 from = rcu_dereference(rt->from);
262 if (from && (rt->rt6i_flags & RTF_PCPU ||
263 unlikely(!list_empty(&rt->rt6i_uncached))))
264 fib6_get_cookie_safe(from, &cookie);
265
266 rcu_read_unlock();
267
268 return cookie;
269}
270
271static inline void ip6_rt_put(struct rt6_info *rt)
272{
273
274
275
276 BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
277 dst_release(&rt->dst);
278}
279
280struct fib6_info *fib6_info_alloc(gfp_t gfp_flags);
281void fib6_info_destroy_rcu(struct rcu_head *head);
282
283static inline void fib6_info_hold(struct fib6_info *f6i)
284{
285 atomic_inc(&f6i->fib6_ref);
286}
287
288static inline bool fib6_info_hold_safe(struct fib6_info *f6i)
289{
290 return atomic_inc_not_zero(&f6i->fib6_ref);
291}
292
293static inline void fib6_info_release(struct fib6_info *f6i)
294{
295 if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
296 call_rcu(&f6i->rcu, fib6_info_destroy_rcu);
297}
298
299enum fib6_walk_state {
300#ifdef CONFIG_IPV6_SUBTREES
301 FWS_S,
302#endif
303 FWS_L,
304 FWS_R,
305 FWS_C,
306 FWS_U
307};
308
309struct fib6_walker {
310 struct list_head lh;
311 struct fib6_node *root, *node;
312 struct fib6_info *leaf;
313 enum fib6_walk_state state;
314 unsigned int skip;
315 unsigned int count;
316 int (*func)(struct fib6_walker *);
317 void *args;
318};
319
320struct rt6_statistics {
321 __u32 fib_nodes;
322 __u32 fib_route_nodes;
323 __u32 fib_rt_entries;
324 __u32 fib_rt_cache;
325 __u32 fib_discarded_routes;
326
327
328 atomic_t fib_rt_alloc;
329 atomic_t fib_rt_uncache;
330};
331
332#define RTN_TL_ROOT 0x0001
333#define RTN_ROOT 0x0002
334#define RTN_RTINFO 0x0004
335
336
337
338
339
340
341
342struct fib6_table {
343 struct hlist_node tb6_hlist;
344 u32 tb6_id;
345 spinlock_t tb6_lock;
346 struct fib6_node tb6_root;
347 struct inet_peer_base tb6_peers;
348 unsigned int flags;
349 unsigned int fib_seq;
350#define RT6_TABLE_HAS_DFLT_ROUTER BIT(0)
351};
352
353#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
354#define RT6_TABLE_MAIN RT_TABLE_MAIN
355#define RT6_TABLE_DFLT RT6_TABLE_MAIN
356#define RT6_TABLE_INFO RT6_TABLE_MAIN
357#define RT6_TABLE_PREFIX RT6_TABLE_MAIN
358
359#ifdef CONFIG_IPV6_MULTIPLE_TABLES
360#define FIB6_TABLE_MIN 1
361#define FIB6_TABLE_MAX RT_TABLE_MAX
362#define RT6_TABLE_LOCAL RT_TABLE_LOCAL
363#else
364#define FIB6_TABLE_MIN RT_TABLE_MAIN
365#define FIB6_TABLE_MAX FIB6_TABLE_MIN
366#define RT6_TABLE_LOCAL RT6_TABLE_MAIN
367#endif
368
369typedef struct rt6_info *(*pol_lookup_t)(struct net *,
370 struct fib6_table *,
371 struct flowi6 *,
372 const struct sk_buff *, int);
373
374struct fib6_entry_notifier_info {
375 struct fib_notifier_info info;
376 struct fib6_info *rt;
377};
378
379
380
381
382
383struct fib6_table *fib6_get_table(struct net *net, u32 id);
384struct fib6_table *fib6_new_table(struct net *net, u32 id);
385struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
386 const struct sk_buff *skb,
387 int flags, pol_lookup_t lookup);
388
389
390
391
392struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
393 int flags);
394
395
396struct fib6_info *fib6_table_lookup(struct net *net, struct fib6_table *table,
397 int oif, struct flowi6 *fl6, int strict);
398
399struct fib6_info *fib6_multipath_select(const struct net *net,
400 struct fib6_info *match,
401 struct flowi6 *fl6, int oif,
402 const struct sk_buff *skb, int strict);
403
404struct fib6_node *fib6_node_lookup(struct fib6_node *root,
405 const struct in6_addr *daddr,
406 const struct in6_addr *saddr);
407
408struct fib6_node *fib6_locate(struct fib6_node *root,
409 const struct in6_addr *daddr, int dst_len,
410 const struct in6_addr *saddr, int src_len,
411 bool exact_match);
412
413void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *arg),
414 void *arg);
415
416int fib6_add(struct fib6_node *root, struct fib6_info *rt,
417 struct nl_info *info, struct netlink_ext_ack *extack);
418int fib6_del(struct fib6_info *rt, struct nl_info *info);
419
420static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
421{
422 return f6i->fib6_nh.nh_dev;
423}
424
425static inline
426struct lwtunnel_state *fib6_info_nh_lwt(const struct fib6_info *f6i)
427{
428 return f6i->fib6_nh.nh_lwtstate;
429}
430
431void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
432 unsigned int flags);
433
434void fib6_run_gc(unsigned long expires, struct net *net, bool force);
435
436void fib6_gc_cleanup(void);
437
438int fib6_init(void);
439
440struct ipv6_route_iter {
441 struct seq_net_private p;
442 struct fib6_walker w;
443 loff_t skip;
444 struct fib6_table *tbl;
445 int sernum;
446};
447
448extern const struct seq_operations ipv6_route_seq_ops;
449
450int call_fib6_notifier(struct notifier_block *nb, struct net *net,
451 enum fib_event_type event_type,
452 struct fib_notifier_info *info);
453int call_fib6_notifiers(struct net *net, enum fib_event_type event_type,
454 struct fib_notifier_info *info);
455
456int __net_init fib6_notifier_init(struct net *net);
457void __net_exit fib6_notifier_exit(struct net *net);
458
459unsigned int fib6_tables_seq_read(struct net *net);
460int fib6_tables_dump(struct net *net, struct notifier_block *nb);
461
462void fib6_update_sernum(struct net *net, struct fib6_info *rt);
463void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt);
464
465void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val);
466static inline bool fib6_metric_locked(struct fib6_info *f6i, int metric)
467{
468 return !!(f6i->fib6_metrics->metrics[RTAX_LOCK - 1] & (1 << metric));
469}
470
471#ifdef CONFIG_IPV6_MULTIPLE_TABLES
472int fib6_rules_init(void);
473void fib6_rules_cleanup(void);
474bool fib6_rule_default(const struct fib_rule *rule);
475int fib6_rules_dump(struct net *net, struct notifier_block *nb);
476unsigned int fib6_rules_seq_read(struct net *net);
477
478static inline bool fib6_rules_early_flow_dissect(struct net *net,
479 struct sk_buff *skb,
480 struct flowi6 *fl6,
481 struct flow_keys *flkeys)
482{
483 unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
484
485 if (!net->ipv6.fib6_rules_require_fldissect)
486 return false;
487
488 skb_flow_dissect_flow_keys(skb, flkeys, flag);
489 fl6->fl6_sport = flkeys->ports.src;
490 fl6->fl6_dport = flkeys->ports.dst;
491 fl6->flowi6_proto = flkeys->basic.ip_proto;
492
493 return true;
494}
495#else
496static inline int fib6_rules_init(void)
497{
498 return 0;
499}
500static inline void fib6_rules_cleanup(void)
501{
502 return ;
503}
504static inline bool fib6_rule_default(const struct fib_rule *rule)
505{
506 return true;
507}
508static inline int fib6_rules_dump(struct net *net, struct notifier_block *nb)
509{
510 return 0;
511}
512static inline unsigned int fib6_rules_seq_read(struct net *net)
513{
514 return 0;
515}
516static inline bool fib6_rules_early_flow_dissect(struct net *net,
517 struct sk_buff *skb,
518 struct flowi6 *fl6,
519 struct flow_keys *flkeys)
520{
521 return false;
522}
523#endif
524#endif
525