~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv6/ip6_fib.c

Version: ~ [ linux-5.2-rc1 ] ~ [ linux-5.1.2 ] ~ [ linux-5.0.16 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.43 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.119 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.176 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.179 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.139 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.67 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      Linux INET6 implementation
  3  *      Forwarding Information Database
  4  *
  5  *      Authors:
  6  *      Pedro Roque             <roque@di.fc.ul.pt>
  7  *
  8  *      This program is free software; you can redistribute it and/or
  9  *      modify it under the terms of the GNU General Public License
 10  *      as published by the Free Software Foundation; either version
 11  *      2 of the License, or (at your option) any later version.
 12  *
 13  *      Changes:
 14  *      Yuji SEKIYA @USAGI:     Support default route on router node;
 15  *                              remove ip6_null_entry from the top of
 16  *                              routing table.
 17  *      Ville Nuorvala:         Fixed routing subtrees.
 18  */
 19 
 20 #define pr_fmt(fmt) "IPv6: " fmt
 21 
 22 #include <linux/errno.h>
 23 #include <linux/types.h>
 24 #include <linux/net.h>
 25 #include <linux/route.h>
 26 #include <linux/netdevice.h>
 27 #include <linux/in6.h>
 28 #include <linux/init.h>
 29 #include <linux/list.h>
 30 #include <linux/slab.h>
 31 
 32 #include <net/ipv6.h>
 33 #include <net/ndisc.h>
 34 #include <net/addrconf.h>
 35 
 36 #include <net/ip6_fib.h>
 37 #include <net/ip6_route.h>
 38 
 39 #define RT6_DEBUG 2
 40 
 41 #if RT6_DEBUG >= 3
 42 #define RT6_TRACE(x...) pr_debug(x)
 43 #else
 44 #define RT6_TRACE(x...) do { ; } while (0)
 45 #endif
 46 
 47 static struct kmem_cache *fib6_node_kmem __read_mostly;
 48 
 49 struct fib6_cleaner {
 50         struct fib6_walker w;
 51         struct net *net;
 52         int (*func)(struct rt6_info *, void *arg);
 53         int sernum;
 54         void *arg;
 55 };
 56 
 57 static DEFINE_RWLOCK(fib6_walker_lock);
 58 
 59 #ifdef CONFIG_IPV6_SUBTREES
 60 #define FWS_INIT FWS_S
 61 #else
 62 #define FWS_INIT FWS_L
 63 #endif
 64 
 65 static void fib6_prune_clones(struct net *net, struct fib6_node *fn);
 66 static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn);
 67 static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn);
 68 static int fib6_walk(struct fib6_walker *w);
 69 static int fib6_walk_continue(struct fib6_walker *w);
 70 
 71 /*
 72  *      A routing update causes an increase of the serial number on the
 73  *      affected subtree. This allows for cached routes to be asynchronously
 74  *      tested when modifications are made to the destination cache as a
 75  *      result of redirects, path MTU changes, etc.
 76  */
 77 
 78 static void fib6_gc_timer_cb(unsigned long arg);
 79 
 80 static LIST_HEAD(fib6_walkers);
 81 #define FOR_WALKERS(w) list_for_each_entry(w, &fib6_walkers, lh)
 82 
 83 static void fib6_walker_link(struct fib6_walker *w)
 84 {
 85         write_lock_bh(&fib6_walker_lock);
 86         list_add(&w->lh, &fib6_walkers);
 87         write_unlock_bh(&fib6_walker_lock);
 88 }
 89 
 90 static void fib6_walker_unlink(struct fib6_walker *w)
 91 {
 92         write_lock_bh(&fib6_walker_lock);
 93         list_del(&w->lh);
 94         write_unlock_bh(&fib6_walker_lock);
 95 }
 96 
 97 static int fib6_new_sernum(struct net *net)
 98 {
 99         int new, old;
100 
101         do {
102                 old = atomic_read(&net->ipv6.fib6_sernum);
103                 new = old < INT_MAX ? old + 1 : 1;
104         } while (atomic_cmpxchg(&net->ipv6.fib6_sernum,
105                                 old, new) != old);
106         return new;
107 }
108 
109 enum {
110         FIB6_NO_SERNUM_CHANGE = 0,
111 };
112 
113 /*
114  *      Auxiliary address test functions for the radix tree.
115  *
116  *      These assume a 32bit processor (although it will work on
117  *      64bit processors)
118  */
119 
120 /*
121  *      test bit
122  */
123 #if defined(__LITTLE_ENDIAN)
124 # define BITOP_BE32_SWIZZLE     (0x1F & ~7)
125 #else
126 # define BITOP_BE32_SWIZZLE     0
127 #endif
128 
129 static __be32 addr_bit_set(const void *token, int fn_bit)
130 {
131         const __be32 *addr = token;
132         /*
133          * Here,
134          *      1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)
135          * is optimized version of
136          *      htonl(1 << ((~fn_bit)&0x1F))
137          * See include/asm-generic/bitops/le.h.
138          */
139         return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) &
140                addr[fn_bit >> 5];
141 }
142 
143 static struct fib6_node *node_alloc(void)
144 {
145         struct fib6_node *fn;
146 
147         fn = kmem_cache_zalloc(fib6_node_kmem, GFP_ATOMIC);
148 
149         return fn;
150 }
151 
152 static void node_free(struct fib6_node *fn)
153 {
154         kmem_cache_free(fib6_node_kmem, fn);
155 }
156 
157 static void rt6_release(struct rt6_info *rt)
158 {
159         if (atomic_dec_and_test(&rt->rt6i_ref))
160                 dst_free(&rt->dst);
161 }
162 
163 static void fib6_free_table(struct fib6_table *table)
164 {
165         inetpeer_invalidate_tree(&table->tb6_peers);
166         kfree(table);
167 }
168 
169 static void fib6_link_table(struct net *net, struct fib6_table *tb)
170 {
171         unsigned int h;
172 
173         /*
174          * Initialize table lock at a single place to give lockdep a key,
175          * tables aren't visible prior to being linked to the list.
176          */
177         rwlock_init(&tb->tb6_lock);
178 
179         h = tb->tb6_id & (FIB6_TABLE_HASHSZ - 1);
180 
181         /*
182          * No protection necessary, this is the only list mutatation
183          * operation, tables never disappear once they exist.
184          */
185         hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]);
186 }
187 
188 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
189 
190 static struct fib6_table *fib6_alloc_table(struct net *net, u32 id)
191 {
192         struct fib6_table *table;
193 
194         table = kzalloc(sizeof(*table), GFP_ATOMIC);
195         if (table) {
196                 table->tb6_id = id;
197                 table->tb6_root.leaf = net->ipv6.ip6_null_entry;
198                 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
199                 inet_peer_base_init(&table->tb6_peers);
200         }
201 
202         return table;
203 }
204 
205 struct fib6_table *fib6_new_table(struct net *net, u32 id)
206 {
207         struct fib6_table *tb;
208 
209         if (id == 0)
210                 id = RT6_TABLE_MAIN;
211         tb = fib6_get_table(net, id);
212         if (tb)
213                 return tb;
214 
215         tb = fib6_alloc_table(net, id);
216         if (tb)
217                 fib6_link_table(net, tb);
218 
219         return tb;
220 }
221 
222 struct fib6_table *fib6_get_table(struct net *net, u32 id)
223 {
224         struct fib6_table *tb;
225         struct hlist_head *head;
226         unsigned int h;
227 
228         if (id == 0)
229                 id = RT6_TABLE_MAIN;
230         h = id & (FIB6_TABLE_HASHSZ - 1);
231         rcu_read_lock();
232         head = &net->ipv6.fib_table_hash[h];
233         hlist_for_each_entry_rcu(tb, head, tb6_hlist) {
234                 if (tb->tb6_id == id) {
235                         rcu_read_unlock();
236                         return tb;
237                 }
238         }
239         rcu_read_unlock();
240 
241         return NULL;
242 }
243 
244 static void __net_init fib6_tables_init(struct net *net)
245 {
246         fib6_link_table(net, net->ipv6.fib6_main_tbl);
247         fib6_link_table(net, net->ipv6.fib6_local_tbl);
248 }
249 #else
250 
251 struct fib6_table *fib6_new_table(struct net *net, u32 id)
252 {
253         return fib6_get_table(net, id);
254 }
255 
256 struct fib6_table *fib6_get_table(struct net *net, u32 id)
257 {
258           return net->ipv6.fib6_main_tbl;
259 }
260 
261 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
262                                    int flags, pol_lookup_t lookup)
263 {
264         return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
265 }
266 
267 static void __net_init fib6_tables_init(struct net *net)
268 {
269         fib6_link_table(net, net->ipv6.fib6_main_tbl);
270 }
271 
272 #endif
273 
274 static int fib6_dump_node(struct fib6_walker *w)
275 {
276         int res;
277         struct rt6_info *rt;
278 
279         for (rt = w->leaf; rt; rt = rt->dst.rt6_next) {
280                 res = rt6_dump_route(rt, w->args);
281                 if (res < 0) {
282                         /* Frame is full, suspend walking */
283                         w->leaf = rt;
284                         return 1;
285                 }
286         }
287         w->leaf = NULL;
288         return 0;
289 }
290 
291 static void fib6_dump_end(struct netlink_callback *cb)
292 {
293         struct fib6_walker *w = (void *)cb->args[2];
294 
295         if (w) {
296                 if (cb->args[4]) {
297                         cb->args[4] = 0;
298                         fib6_walker_unlink(w);
299                 }
300                 cb->args[2] = 0;
301                 kfree(w);
302         }
303         cb->done = (void *)cb->args[3];
304         cb->args[1] = 3;
305 }
306 
307 static int fib6_dump_done(struct netlink_callback *cb)
308 {
309         fib6_dump_end(cb);
310         return cb->done ? cb->done(cb) : 0;
311 }
312 
313 static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
314                            struct netlink_callback *cb)
315 {
316         struct fib6_walker *w;
317         int res;
318 
319         w = (void *)cb->args[2];
320         w->root = &table->tb6_root;
321 
322         if (cb->args[4] == 0) {
323                 w->count = 0;
324                 w->skip = 0;
325 
326                 read_lock_bh(&table->tb6_lock);
327                 res = fib6_walk(w);
328                 read_unlock_bh(&table->tb6_lock);
329                 if (res > 0) {
330                         cb->args[4] = 1;
331                         cb->args[5] = w->root->fn_sernum;
332                 }
333         } else {
334                 if (cb->args[5] != w->root->fn_sernum) {
335                         /* Begin at the root if the tree changed */
336                         cb->args[5] = w->root->fn_sernum;
337                         w->state = FWS_INIT;
338                         w->node = w->root;
339                         w->skip = w->count;
340                 } else
341                         w->skip = 0;
342 
343                 read_lock_bh(&table->tb6_lock);
344                 res = fib6_walk_continue(w);
345                 read_unlock_bh(&table->tb6_lock);
346                 if (res <= 0) {
347                         fib6_walker_unlink(w);
348                         cb->args[4] = 0;
349                 }
350         }
351 
352         return res;
353 }
354 
355 static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
356 {
357         struct net *net = sock_net(skb->sk);
358         unsigned int h, s_h;
359         unsigned int e = 0, s_e;
360         struct rt6_rtnl_dump_arg arg;
361         struct fib6_walker *w;
362         struct fib6_table *tb;
363         struct hlist_head *head;
364         int res = 0;
365 
366         s_h = cb->args[0];
367         s_e = cb->args[1];
368 
369         w = (void *)cb->args[2];
370         if (!w) {
371                 /* New dump:
372                  *
373                  * 1. hook callback destructor.
374                  */
375                 cb->args[3] = (long)cb->done;
376                 cb->done = fib6_dump_done;
377 
378                 /*
379                  * 2. allocate and initialize walker.
380                  */
381                 w = kzalloc(sizeof(*w), GFP_ATOMIC);
382                 if (!w)
383                         return -ENOMEM;
384                 w->func = fib6_dump_node;
385                 cb->args[2] = (long)w;
386         }
387 
388         arg.skb = skb;
389         arg.cb = cb;
390         arg.net = net;
391         w->args = &arg;
392 
393         rcu_read_lock();
394         for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
395                 e = 0;
396                 head = &net->ipv6.fib_table_hash[h];
397                 hlist_for_each_entry_rcu(tb, head, tb6_hlist) {
398                         if (e < s_e)
399                                 goto next;
400                         res = fib6_dump_table(tb, skb, cb);
401                         if (res != 0)
402                                 goto out;
403 next:
404                         e++;
405                 }
406         }
407 out:
408         rcu_read_unlock();
409         cb->args[1] = e;
410         cb->args[0] = h;
411 
412         res = res < 0 ? res : skb->len;
413         if (res <= 0)
414                 fib6_dump_end(cb);
415         return res;
416 }
417 
418 /*
419  *      Routing Table
420  *
421  *      return the appropriate node for a routing tree "add" operation
422  *      by either creating and inserting or by returning an existing
423  *      node.
424  */
425 
426 static struct fib6_node *fib6_add_1(struct fib6_node *root,
427                                      struct in6_addr *addr, int plen,
428                                      int offset, int allow_create,
429                                      int replace_required, int sernum)
430 {
431         struct fib6_node *fn, *in, *ln;
432         struct fib6_node *pn = NULL;
433         struct rt6key *key;
434         int     bit;
435         __be32  dir = 0;
436 
437         RT6_TRACE("fib6_add_1\n");
438 
439         /* insert node in tree */
440 
441         fn = root;
442 
443         do {
444                 key = (struct rt6key *)((u8 *)fn->leaf + offset);
445 
446                 /*
447                  *      Prefix match
448                  */
449                 if (plen < fn->fn_bit ||
450                     !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit)) {
451                         if (!allow_create) {
452                                 if (replace_required) {
453                                         pr_warn("Can't replace route, no match found\n");
454                                         return ERR_PTR(-ENOENT);
455                                 }
456                                 pr_warn("NLM_F_CREATE should be set when creating new route\n");
457                         }
458                         goto insert_above;
459                 }
460 
461                 /*
462                  *      Exact match ?
463                  */
464 
465                 if (plen == fn->fn_bit) {
466                         /* clean up an intermediate node */
467                         if (!(fn->fn_flags & RTN_RTINFO)) {
468                                 rt6_release(fn->leaf);
469                                 fn->leaf = NULL;
470                         }
471 
472                         fn->fn_sernum = sernum;
473 
474                         return fn;
475                 }
476 
477                 /*
478                  *      We have more bits to go
479                  */
480 
481                 /* Try to walk down on tree. */
482                 fn->fn_sernum = sernum;
483                 dir = addr_bit_set(addr, fn->fn_bit);
484                 pn = fn;
485                 fn = dir ? fn->right : fn->left;
486         } while (fn);
487 
488         if (!allow_create) {
489                 /* We should not create new node because
490                  * NLM_F_REPLACE was specified without NLM_F_CREATE
491                  * I assume it is safe to require NLM_F_CREATE when
492                  * REPLACE flag is used! Later we may want to remove the
493                  * check for replace_required, because according
494                  * to netlink specification, NLM_F_CREATE
495                  * MUST be specified if new route is created.
496                  * That would keep IPv6 consistent with IPv4
497                  */
498                 if (replace_required) {
499                         pr_warn("Can't replace route, no match found\n");
500                         return ERR_PTR(-ENOENT);
501                 }
502                 pr_warn("NLM_F_CREATE should be set when creating new route\n");
503         }
504         /*
505          *      We walked to the bottom of tree.
506          *      Create new leaf node without children.
507          */
508 
509         ln = node_alloc();
510 
511         if (!ln)
512                 return ERR_PTR(-ENOMEM);
513         ln->fn_bit = plen;
514 
515         ln->parent = pn;
516         ln->fn_sernum = sernum;
517 
518         if (dir)
519                 pn->right = ln;
520         else
521                 pn->left  = ln;
522 
523         return ln;
524 
525 
526 insert_above:
527         /*
528          * split since we don't have a common prefix anymore or
529          * we have a less significant route.
530          * we've to insert an intermediate node on the list
531          * this new node will point to the one we need to create
532          * and the current
533          */
534 
535         pn = fn->parent;
536 
537         /* find 1st bit in difference between the 2 addrs.
538 
539            See comment in __ipv6_addr_diff: bit may be an invalid value,
540            but if it is >= plen, the value is ignored in any case.
541          */
542 
543         bit = __ipv6_addr_diff(addr, &key->addr, sizeof(*addr));
544 
545         /*
546          *              (intermediate)[in]
547          *                /        \
548          *      (new leaf node)[ln] (old node)[fn]
549          */
550         if (plen > bit) {
551                 in = node_alloc();
552                 ln = node_alloc();
553 
554                 if (!in || !ln) {
555                         if (in)
556                                 node_free(in);
557                         if (ln)
558                                 node_free(ln);
559                         return ERR_PTR(-ENOMEM);
560                 }
561 
562                 /*
563                  * new intermediate node.
564                  * RTN_RTINFO will
565                  * be off since that an address that chooses one of
566                  * the branches would not match less specific routes
567                  * in the other branch
568                  */
569 
570                 in->fn_bit = bit;
571 
572                 in->parent = pn;
573                 in->leaf = fn->leaf;
574                 atomic_inc(&in->leaf->rt6i_ref);
575 
576                 in->fn_sernum = sernum;
577 
578                 /* update parent pointer */
579                 if (dir)
580                         pn->right = in;
581                 else
582                         pn->left  = in;
583 
584                 ln->fn_bit = plen;
585 
586                 ln->parent = in;
587                 fn->parent = in;
588 
589                 ln->fn_sernum = sernum;
590 
591                 if (addr_bit_set(addr, bit)) {
592                         in->right = ln;
593                         in->left  = fn;
594                 } else {
595                         in->left  = ln;
596                         in->right = fn;
597                 }
598         } else { /* plen <= bit */
599 
600                 /*
601                  *              (new leaf node)[ln]
602                  *                /        \
603                  *           (old node)[fn] NULL
604                  */
605 
606                 ln = node_alloc();
607 
608                 if (!ln)
609                         return ERR_PTR(-ENOMEM);
610 
611                 ln->fn_bit = plen;
612 
613                 ln->parent = pn;
614 
615                 ln->fn_sernum = sernum;
616 
617                 if (dir)
618                         pn->right = ln;
619                 else
620                         pn->left  = ln;
621 
622                 if (addr_bit_set(&key->addr, plen))
623                         ln->right = fn;
624                 else
625                         ln->left  = fn;
626 
627                 fn->parent = ln;
628         }
629         return ln;
630 }
631 
632 static bool rt6_qualify_for_ecmp(struct rt6_info *rt)
633 {
634         return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
635                RTF_GATEWAY;
636 }
637 
638 static void fib6_copy_metrics(u32 *mp, const struct mx6_config *mxc)
639 {
640         int i;
641 
642         for (i = 0; i < RTAX_MAX; i++) {
643                 if (test_bit(i, mxc->mx_valid))
644                         mp[i] = mxc->mx[i];
645         }
646 }
647 
648 static int fib6_commit_metrics(struct dst_entry *dst, struct mx6_config *mxc)
649 {
650         if (!mxc->mx)
651                 return 0;
652 
653         if (dst->flags & DST_HOST) {
654                 u32 *mp = dst_metrics_write_ptr(dst);
655 
656                 if (unlikely(!mp))
657                         return -ENOMEM;
658 
659                 fib6_copy_metrics(mp, mxc);
660         } else {
661                 dst_init_metrics(dst, mxc->mx, false);
662 
663                 /* We've stolen mx now. */
664                 mxc->mx = NULL;
665         }
666 
667         return 0;
668 }
669 
670 static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn,
671                           struct net *net)
672 {
673         if (atomic_read(&rt->rt6i_ref) != 1) {
674                 /* This route is used as dummy address holder in some split
675                  * nodes. It is not leaked, but it still holds other resources,
676                  * which must be released in time. So, scan ascendant nodes
677                  * and replace dummy references to this route with references
678                  * to still alive ones.
679                  */
680                 while (fn) {
681                         if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) {
682                                 fn->leaf = fib6_find_prefix(net, fn);
683                                 atomic_inc(&fn->leaf->rt6i_ref);
684                                 rt6_release(rt);
685                         }
686                         fn = fn->parent;
687                 }
688                 /* No more references are possible at this point. */
689                 BUG_ON(atomic_read(&rt->rt6i_ref) != 1);
690         }
691 }
692 
693 /*
694  *      Insert routing information in a node.
695  */
696 
697 static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
698                             struct nl_info *info, struct mx6_config *mxc)
699 {
700         struct rt6_info *iter = NULL;
701         struct rt6_info **ins;
702         struct rt6_info **fallback_ins = NULL;
703         int replace = (info->nlh &&
704                        (info->nlh->nlmsg_flags & NLM_F_REPLACE));
705         int add = (!info->nlh ||
706                    (info->nlh->nlmsg_flags & NLM_F_CREATE));
707         int found = 0;
708         bool rt_can_ecmp = rt6_qualify_for_ecmp(rt);
709         int err;
710 
711         ins = &fn->leaf;
712 
713         for (iter = fn->leaf; iter; iter = iter->dst.rt6_next) {
714                 /*
715                  *      Search for duplicates
716                  */
717 
718                 if (iter->rt6i_metric == rt->rt6i_metric) {
719                         /*
720                          *      Same priority level
721                          */
722                         if (info->nlh &&
723                             (info->nlh->nlmsg_flags & NLM_F_EXCL))
724                                 return -EEXIST;
725                         if (replace) {
726                                 if (rt_can_ecmp == rt6_qualify_for_ecmp(iter)) {
727                                         found++;
728                                         break;
729                                 }
730                                 if (rt_can_ecmp)
731                                         fallback_ins = fallback_ins ?: ins;
732                                 goto next_iter;
733                         }
734 
735                         if (iter->dst.dev == rt->dst.dev &&
736                             iter->rt6i_idev == rt->rt6i_idev &&
737                             ipv6_addr_equal(&iter->rt6i_gateway,
738                                             &rt->rt6i_gateway)) {
739                                 if (rt->rt6i_nsiblings)
740                                         rt->rt6i_nsiblings = 0;
741                                 if (!(iter->rt6i_flags & RTF_EXPIRES))
742                                         return -EEXIST;
743                                 if (!(rt->rt6i_flags & RTF_EXPIRES))
744                                         rt6_clean_expires(iter);
745                                 else
746                                         rt6_set_expires(iter, rt->dst.expires);
747                                 return -EEXIST;
748                         }
749                         /* If we have the same destination and the same metric,
750                          * but not the same gateway, then the route we try to
751                          * add is sibling to this route, increment our counter
752                          * of siblings, and later we will add our route to the
753                          * list.
754                          * Only static routes (which don't have flag
755                          * RTF_EXPIRES) are used for ECMPv6.
756                          *
757                          * To avoid long list, we only had siblings if the
758                          * route have a gateway.
759                          */
760                         if (rt_can_ecmp &&
761                             rt6_qualify_for_ecmp(iter))
762                                 rt->rt6i_nsiblings++;
763                 }
764 
765                 if (iter->rt6i_metric > rt->rt6i_metric)
766                         break;
767 
768 next_iter:
769                 ins = &iter->dst.rt6_next;
770         }
771 
772         if (fallback_ins && !found) {
773                 /* No ECMP-able route found, replace first non-ECMP one */
774                 ins = fallback_ins;
775                 iter = *ins;
776                 found++;
777         }
778 
779         /* Reset round-robin state, if necessary */
780         if (ins == &fn->leaf)
781                 fn->rr_ptr = NULL;
782 
783         /* Link this route to others same route. */
784         if (rt->rt6i_nsiblings) {
785                 unsigned int rt6i_nsiblings;
786                 struct rt6_info *sibling, *temp_sibling;
787 
788                 /* Find the first route that have the same metric */
789                 sibling = fn->leaf;
790                 while (sibling) {
791                         if (sibling->rt6i_metric == rt->rt6i_metric &&
792                             rt6_qualify_for_ecmp(sibling)) {
793                                 list_add_tail(&rt->rt6i_siblings,
794                                               &sibling->rt6i_siblings);
795                                 break;
796                         }
797                         sibling = sibling->dst.rt6_next;
798                 }
799                 /* For each sibling in the list, increment the counter of
800                  * siblings. BUG() if counters does not match, list of siblings
801                  * is broken!
802                  */
803                 rt6i_nsiblings = 0;
804                 list_for_each_entry_safe(sibling, temp_sibling,
805                                          &rt->rt6i_siblings, rt6i_siblings) {
806                         sibling->rt6i_nsiblings++;
807                         BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
808                         rt6i_nsiblings++;
809                 }
810                 BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
811         }
812 
813         /*
814          *      insert node
815          */
816         if (!replace) {
817                 if (!add)
818                         pr_warn("NLM_F_CREATE should be set when creating new route\n");
819 
820 add:
821                 err = fib6_commit_metrics(&rt->dst, mxc);
822                 if (err)
823                         return err;
824 
825                 rt->dst.rt6_next = iter;
826                 *ins = rt;
827                 rt->rt6i_node = fn;
828                 atomic_inc(&rt->rt6i_ref);
829                 inet6_rt_notify(RTM_NEWROUTE, rt, info);
830                 info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
831 
832                 if (!(fn->fn_flags & RTN_RTINFO)) {
833                         info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
834                         fn->fn_flags |= RTN_RTINFO;
835                 }
836 
837         } else {
838                 int nsiblings;
839 
840                 if (!found) {
841                         if (add)
842                                 goto add;
843                         pr_warn("NLM_F_REPLACE set, but no existing node found!\n");
844                         return -ENOENT;
845                 }
846 
847                 err = fib6_commit_metrics(&rt->dst, mxc);
848                 if (err)
849                         return err;
850 
851                 *ins = rt;
852                 rt->rt6i_node = fn;
853                 rt->dst.rt6_next = iter->dst.rt6_next;
854                 atomic_inc(&rt->rt6i_ref);
855                 inet6_rt_notify(RTM_NEWROUTE, rt, info);
856                 if (!(fn->fn_flags & RTN_RTINFO)) {
857                         info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
858                         fn->fn_flags |= RTN_RTINFO;
859                 }
860                 nsiblings = iter->rt6i_nsiblings;
861                 fib6_purge_rt(iter, fn, info->nl_net);
862                 if (fn->rr_ptr == iter)
863                         fn->rr_ptr = NULL;
864                 rt6_release(iter);
865 
866                 if (nsiblings) {
867                         /* Replacing an ECMP route, remove all siblings */
868                         ins = &rt->dst.rt6_next;
869                         iter = *ins;
870                         while (iter) {
871                                 if (iter->rt6i_metric > rt->rt6i_metric)
872                                         break;
873                                 if (rt6_qualify_for_ecmp(iter)) {
874                                         *ins = iter->dst.rt6_next;
875                                         fib6_purge_rt(iter, fn, info->nl_net);
876                                         if (fn->rr_ptr == iter)
877                                                 fn->rr_ptr = NULL;
878                                         rt6_release(iter);
879                                         nsiblings--;
880                                 } else {
881                                         ins = &iter->dst.rt6_next;
882                                 }
883                                 iter = *ins;
884                         }
885                         WARN_ON(nsiblings != 0);
886                 }
887         }
888 
889         return 0;
890 }
891 
892 static void fib6_start_gc(struct net *net, struct rt6_info *rt)
893 {
894         if (!timer_pending(&net->ipv6.ip6_fib_timer) &&
895             (rt->rt6i_flags & (RTF_EXPIRES | RTF_CACHE)))
896                 mod_timer(&net->ipv6.ip6_fib_timer,
897                           jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
898 }
899 
900 void fib6_force_start_gc(struct net *net)
901 {
902         if (!timer_pending(&net->ipv6.ip6_fib_timer))
903                 mod_timer(&net->ipv6.ip6_fib_timer,
904                           jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
905 }
906 
907 /*
908  *      Add routing information to the routing tree.
909  *      <destination addr>/<source addr>
910  *      with source addr info in sub-trees
911  */
912 
913 int fib6_add(struct fib6_node *root, struct rt6_info *rt,
914              struct nl_info *info, struct mx6_config *mxc)
915 {
916         struct fib6_node *fn, *pn = NULL;
917         int err = -ENOMEM;
918         int allow_create = 1;
919         int replace_required = 0;
920         int sernum = fib6_new_sernum(info->nl_net);
921 
922         if (info->nlh) {
923                 if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
924                         allow_create = 0;
925                 if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
926                         replace_required = 1;
927         }
928         if (!allow_create && !replace_required)
929                 pr_warn("RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n");
930 
931         fn = fib6_add_1(root, &rt->rt6i_dst.addr, rt->rt6i_dst.plen,
932                         offsetof(struct rt6_info, rt6i_dst), allow_create,
933                         replace_required, sernum);
934         if (IS_ERR(fn)) {
935                 err = PTR_ERR(fn);
936                 fn = NULL;
937                 goto out;
938         }
939 
940         pn = fn;
941 
942 #ifdef CONFIG_IPV6_SUBTREES
943         if (rt->rt6i_src.plen) {
944                 struct fib6_node *sn;
945 
946                 if (!fn->subtree) {
947                         struct fib6_node *sfn;
948 
949                         /*
950                          * Create subtree.
951                          *
952                          *              fn[main tree]
953                          *              |
954                          *              sfn[subtree root]
955                          *                 \
956                          *                  sn[new leaf node]
957                          */
958 
959                         /* Create subtree root node */
960                         sfn = node_alloc();
961                         if (!sfn)
962                                 goto st_failure;
963 
964                         sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
965                         atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
966                         sfn->fn_flags = RTN_ROOT;
967                         sfn->fn_sernum = sernum;
968 
969                         /* Now add the first leaf node to new subtree */
970 
971                         sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
972                                         rt->rt6i_src.plen,
973                                         offsetof(struct rt6_info, rt6i_src),
974                                         allow_create, replace_required, sernum);
975 
976                         if (IS_ERR(sn)) {
977                                 /* If it is failed, discard just allocated
978                                    root, and then (in st_failure) stale node
979                                    in main tree.
980                                  */
981                                 node_free(sfn);
982                                 err = PTR_ERR(sn);
983                                 goto st_failure;
984                         }
985 
986                         /* Now link new subtree to main tree */
987                         sfn->parent = fn;
988                         fn->subtree = sfn;
989                 } else {
990                         sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
991                                         rt->rt6i_src.plen,
992                                         offsetof(struct rt6_info, rt6i_src),
993                                         allow_create, replace_required, sernum);
994 
995                         if (IS_ERR(sn)) {
996                                 err = PTR_ERR(sn);
997                                 goto st_failure;
998                         }
999                 }
1000 
1001                 if (!fn->leaf) {
1002                         fn->leaf = rt;
1003                         atomic_inc(&rt->rt6i_ref);
1004                 }
1005                 fn = sn;
1006         }
1007 #endif
1008 
1009         err = fib6_add_rt2node(fn, rt, info, mxc);
1010         if (!err) {
1011                 fib6_start_gc(info->nl_net, rt);
1012                 if (!(rt->rt6i_flags & RTF_CACHE))
1013                         fib6_prune_clones(info->nl_net, pn);
1014         }
1015 
1016 out:
1017         if (err) {
1018 #ifdef CONFIG_IPV6_SUBTREES
1019                 /*
1020                  * If fib6_add_1 has cleared the old leaf pointer in the
1021                  * super-tree leaf node we have to find a new one for it.
1022                  */
1023                 if (pn != fn && pn->leaf == rt) {
1024                         pn->leaf = NULL;
1025                         atomic_dec(&rt->rt6i_ref);
1026                 }
1027                 if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
1028                         pn->leaf = fib6_find_prefix(info->nl_net, pn);
1029 #if RT6_DEBUG >= 2
1030                         if (!pn->leaf) {
1031                                 WARN_ON(pn->leaf == NULL);
1032                                 pn->leaf = info->nl_net->ipv6.ip6_null_entry;
1033                         }
1034 #endif
1035                         atomic_inc(&pn->leaf->rt6i_ref);
1036                 }
1037 #endif
1038                 dst_free(&rt->dst);
1039         }
1040         return err;
1041 
1042 #ifdef CONFIG_IPV6_SUBTREES
1043         /* Subtree creation failed, probably main tree node
1044            is orphan. If it is, shoot it.
1045          */
1046 st_failure:
1047         if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
1048                 fib6_repair_tree(info->nl_net, fn);
1049         dst_free(&rt->dst);
1050         return err;
1051 #endif
1052 }
1053 
1054 /*
1055  *      Routing tree lookup
1056  *
1057  */
1058 
1059 struct lookup_args {
1060         int                     offset;         /* key offset on rt6_info       */
1061         const struct in6_addr   *addr;          /* search key                   */
1062 };
1063 
1064 static struct fib6_node *fib6_lookup_1(struct fib6_node *root,
1065                                        struct lookup_args *args)
1066 {
1067         struct fib6_node *fn;
1068         __be32 dir;
1069 
1070         if (unlikely(args->offset == 0))
1071                 return NULL;
1072 
1073         /*
1074          *      Descend on a tree
1075          */
1076 
1077         fn = root;
1078 
1079         for (;;) {
1080                 struct fib6_node *next;
1081 
1082                 dir = addr_bit_set(args->addr, fn->fn_bit);
1083 
1084                 next = dir ? fn->right : fn->left;
1085 
1086                 if (next) {
1087                         fn = next;
1088                         continue;
1089                 }
1090                 break;
1091         }
1092 
1093         while (fn) {
1094                 if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) {
1095                         struct rt6key *key;
1096 
1097                         key = (struct rt6key *) ((u8 *) fn->leaf +
1098                                                  args->offset);
1099 
1100                         if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
1101 #ifdef CONFIG_IPV6_SUBTREES
1102                                 if (fn->subtree) {
1103                                         struct fib6_node *sfn;
1104                                         sfn = fib6_lookup_1(fn->subtree,
1105                                                             args + 1);
1106                                         if (!sfn)
1107                                                 goto backtrack;
1108                                         fn = sfn;
1109                                 }
1110 #endif
1111                                 if (fn->fn_flags & RTN_RTINFO)
1112                                         return fn;
1113                         }
1114                 }
1115 #ifdef CONFIG_IPV6_SUBTREES
1116 backtrack:
1117 #endif
1118                 if (fn->fn_flags & RTN_ROOT)
1119                         break;
1120 
1121                 fn = fn->parent;
1122         }
1123 
1124         return NULL;
1125 }
1126 
1127 struct fib6_node *fib6_lookup(struct fib6_node *root, const struct in6_addr *daddr,
1128                               const struct in6_addr *saddr)
1129 {
1130         struct fib6_node *fn;
1131         struct lookup_args args[] = {
1132                 {
1133                         .offset = offsetof(struct rt6_info, rt6i_dst),
1134                         .addr = daddr,
1135                 },
1136 #ifdef CONFIG_IPV6_SUBTREES
1137                 {
1138                         .offset = offsetof(struct rt6_info, rt6i_src),
1139                         .addr = saddr,
1140                 },
1141 #endif
1142                 {
1143                         .offset = 0,    /* sentinel */
1144                 }
1145         };
1146 
1147         fn = fib6_lookup_1(root, daddr ? args : args + 1);
1148         if (!fn || fn->fn_flags & RTN_TL_ROOT)
1149                 fn = root;
1150 
1151         return fn;
1152 }
1153 
1154 /*
1155  *      Get node with specified destination prefix (and source prefix,
1156  *      if subtrees are used)
1157  */
1158 
1159 
1160 static struct fib6_node *fib6_locate_1(struct fib6_node *root,
1161                                        const struct in6_addr *addr,
1162                                        int plen, int offset)
1163 {
1164         struct fib6_node *fn;
1165 
1166         for (fn = root; fn ; ) {
1167                 struct rt6key *key = (struct rt6key *)((u8 *)fn->leaf + offset);
1168 
1169                 /*
1170                  *      Prefix match
1171                  */
1172                 if (plen < fn->fn_bit ||
1173                     !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
1174                         return NULL;
1175 
1176                 if (plen == fn->fn_bit)
1177                         return fn;
1178 
1179                 /*
1180                  *      We have more bits to go
1181                  */
1182                 if (addr_bit_set(addr, fn->fn_bit))
1183                         fn = fn->right;
1184                 else
1185                         fn = fn->left;
1186         }
1187         return NULL;
1188 }
1189 
1190 struct fib6_node *fib6_locate(struct fib6_node *root,
1191                               const struct in6_addr *daddr, int dst_len,
1192                               const struct in6_addr *saddr, int src_len)
1193 {
1194         struct fib6_node *fn;
1195 
1196         fn = fib6_locate_1(root, daddr, dst_len,
1197                            offsetof(struct rt6_info, rt6i_dst));
1198 
1199 #ifdef CONFIG_IPV6_SUBTREES
1200         if (src_len) {
1201                 WARN_ON(saddr == NULL);
1202                 if (fn && fn->subtree)
1203                         fn = fib6_locate_1(fn->subtree, saddr, src_len,
1204                                            offsetof(struct rt6_info, rt6i_src));
1205         }
1206 #endif
1207 
1208         if (fn && fn->fn_flags & RTN_RTINFO)
1209                 return fn;
1210 
1211         return NULL;
1212 }
1213 
1214 
1215 /*
1216  *      Deletion
1217  *
1218  */
1219 
1220 static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
1221 {
1222         if (fn->fn_flags & RTN_ROOT)
1223                 return net->ipv6.ip6_null_entry;
1224 
1225         while (fn) {
1226                 if (fn->left)
1227                         return fn->left->leaf;
1228                 if (fn->right)
1229                         return fn->right->leaf;
1230 
1231                 fn = FIB6_SUBTREE(fn);
1232         }
1233         return NULL;
1234 }
1235 
1236 /*
1237  *      Called to trim the tree of intermediate nodes when possible. "fn"
1238  *      is the node we want to try and remove.
1239  */
1240 
1241 static struct fib6_node *fib6_repair_tree(struct net *net,
1242                                            struct fib6_node *fn)
1243 {
1244         int children;
1245         int nstate;
1246         struct fib6_node *child, *pn;
1247         struct fib6_walker *w;
1248         int iter = 0;
1249 
1250         for (;;) {
1251                 RT6_TRACE("fixing tree: plen=%d iter=%d\n", fn->fn_bit, iter);
1252                 iter++;
1253 
1254                 WARN_ON(fn->fn_flags & RTN_RTINFO);
1255                 WARN_ON(fn->fn_flags & RTN_TL_ROOT);
1256                 WARN_ON(fn->leaf);
1257 
1258                 children = 0;
1259                 child = NULL;
1260                 if (fn->right)
1261                         child = fn->right, children |= 1;
1262                 if (fn->left)
1263                         child = fn->left, children |= 2;
1264 
1265                 if (children == 3 || FIB6_SUBTREE(fn)
1266 #ifdef CONFIG_IPV6_SUBTREES
1267                     /* Subtree root (i.e. fn) may have one child */
1268                     || (children && fn->fn_flags & RTN_ROOT)
1269 #endif
1270                     ) {
1271                         fn->leaf = fib6_find_prefix(net, fn);
1272 #if RT6_DEBUG >= 2
1273                         if (!fn->leaf) {
1274                                 WARN_ON(!fn->leaf);
1275                                 fn->leaf = net->ipv6.ip6_null_entry;
1276                         }
1277 #endif
1278                         atomic_inc(&fn->leaf->rt6i_ref);
1279                         return fn->parent;
1280                 }
1281 
1282                 pn = fn->parent;
1283 #ifdef CONFIG_IPV6_SUBTREES
1284                 if (FIB6_SUBTREE(pn) == fn) {
1285                         WARN_ON(!(fn->fn_flags & RTN_ROOT));
1286                         FIB6_SUBTREE(pn) = NULL;
1287                         nstate = FWS_L;
1288                 } else {
1289                         WARN_ON(fn->fn_flags & RTN_ROOT);
1290 #endif
1291                         if (pn->right == fn)
1292                                 pn->right = child;
1293                         else if (pn->left == fn)
1294                                 pn->left = child;
1295 #if RT6_DEBUG >= 2
1296                         else
1297                                 WARN_ON(1);
1298 #endif
1299                         if (child)
1300                                 child->parent = pn;
1301                         nstate = FWS_R;
1302 #ifdef CONFIG_IPV6_SUBTREES
1303                 }
1304 #endif
1305 
1306                 read_lock(&fib6_walker_lock);
1307                 FOR_WALKERS(w) {
1308                         if (!child) {
1309                                 if (w->root == fn) {
1310                                         w->root = w->node = NULL;
1311                                         RT6_TRACE("W %p adjusted by delroot 1\n", w);
1312                                 } else if (w->node == fn) {
1313                                         RT6_TRACE("W %p adjusted by delnode 1, s=%d/%d\n", w, w->state, nstate);
1314                                         w->node = pn;
1315                                         w->state = nstate;
1316                                 }
1317                         } else {
1318                                 if (w->root == fn) {
1319                                         w->root = child;
1320                                         RT6_TRACE("W %p adjusted by delroot 2\n", w);
1321                                 }
1322                                 if (w->node == fn) {
1323                                         w->node = child;
1324                                         if (children&2) {
1325                                                 RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state);
1326                                                 w->state = w->state >= FWS_R ? FWS_U : FWS_INIT;
1327                                         } else {
1328                                                 RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state);
1329                                                 w->state = w->state >= FWS_C ? FWS_U : FWS_INIT;
1330                                         }
1331                                 }
1332                         }
1333                 }
1334                 read_unlock(&fib6_walker_lock);
1335 
1336                 node_free(fn);
1337                 if (pn->fn_flags & RTN_RTINFO || FIB6_SUBTREE(pn))
1338                         return pn;
1339 
1340                 rt6_release(pn->leaf);
1341                 pn->leaf = NULL;
1342                 fn = pn;
1343         }
1344 }
1345 
1346 static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
1347                            struct nl_info *info)
1348 {
1349         struct fib6_walker *w;
1350         struct rt6_info *rt = *rtp;
1351         struct net *net = info->nl_net;
1352 
1353         RT6_TRACE("fib6_del_route\n");
1354 
1355         /* Unlink it */
1356         *rtp = rt->dst.rt6_next;
1357         rt->rt6i_node = NULL;
1358         net->ipv6.rt6_stats->fib_rt_entries--;
1359         net->ipv6.rt6_stats->fib_discarded_routes++;
1360 
1361         /* Reset round-robin state, if necessary */
1362         if (fn->rr_ptr == rt)
1363                 fn->rr_ptr = NULL;
1364 
1365         /* Remove this entry from other siblings */
1366         if (rt->rt6i_nsiblings) {
1367                 struct rt6_info *sibling, *next_sibling;
1368 
1369                 list_for_each_entry_safe(sibling, next_sibling,
1370                                          &rt->rt6i_siblings, rt6i_siblings)
1371                         sibling->rt6i_nsiblings--;
1372                 rt->rt6i_nsiblings = 0;
1373                 list_del_init(&rt->rt6i_siblings);
1374         }
1375 
1376         /* Adjust walkers */
1377         read_lock(&fib6_walker_lock);
1378         FOR_WALKERS(w) {
1379                 if (w->state == FWS_C && w->leaf == rt) {
1380                         RT6_TRACE("walker %p adjusted by delroute\n", w);
1381                         w->leaf = rt->dst.rt6_next;
1382                         if (!w->leaf)
1383                                 w->state = FWS_U;
1384                 }
1385         }
1386         read_unlock(&fib6_walker_lock);
1387 
1388         rt->dst.rt6_next = NULL;
1389 
1390         /* If it was last route, expunge its radix tree node */
1391         if (!fn->leaf) {
1392                 fn->fn_flags &= ~RTN_RTINFO;
1393                 net->ipv6.rt6_stats->fib_route_nodes--;
1394                 fn = fib6_repair_tree(net, fn);
1395         }
1396 
1397         fib6_purge_rt(rt, fn, net);
1398 
1399         inet6_rt_notify(RTM_DELROUTE, rt, info);
1400         rt6_release(rt);
1401 }
1402 
1403 int fib6_del(struct rt6_info *rt, struct nl_info *info)
1404 {
1405         struct net *net = info->nl_net;
1406         struct fib6_node *fn = rt->rt6i_node;
1407         struct rt6_info **rtp;
1408 
1409 #if RT6_DEBUG >= 2
1410         if (rt->dst.obsolete > 0) {
1411                 WARN_ON(fn);
1412                 return -ENOENT;
1413         }
1414 #endif
1415         if (!fn || rt == net->ipv6.ip6_null_entry)
1416                 return -ENOENT;
1417 
1418         WARN_ON(!(fn->fn_flags & RTN_RTINFO));
1419 
1420         if (!(rt->rt6i_flags & RTF_CACHE)) {
1421                 struct fib6_node *pn = fn;
1422 #ifdef CONFIG_IPV6_SUBTREES
1423                 /* clones of this route might be in another subtree */
1424                 if (rt->rt6i_src.plen) {
1425                         while (!(pn->fn_flags & RTN_ROOT))
1426                                 pn = pn->parent;
1427                         pn = pn->parent;
1428                 }
1429 #endif
1430                 fib6_prune_clones(info->nl_net, pn);
1431         }
1432 
1433         /*
1434          *      Walk the leaf entries looking for ourself
1435          */
1436 
1437         for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) {
1438                 if (*rtp == rt) {
1439                         fib6_del_route(fn, rtp, info);
1440                         return 0;
1441                 }
1442         }
1443         return -ENOENT;
1444 }
1445 
1446 /*
1447  *      Tree traversal function.
1448  *
1449  *      Certainly, it is not interrupt safe.
1450  *      However, it is internally reenterable wrt itself and fib6_add/fib6_del.
1451  *      It means, that we can modify tree during walking
1452  *      and use this function for garbage collection, clone pruning,
1453  *      cleaning tree when a device goes down etc. etc.
1454  *
1455  *      It guarantees that every node will be traversed,
1456  *      and that it will be traversed only once.
1457  *
1458  *      Callback function w->func may return:
1459  *      0 -> continue walking.
1460  *      positive value -> walking is suspended (used by tree dumps,
1461  *      and probably by gc, if it will be split to several slices)
1462  *      negative value -> terminate walking.
1463  *
1464  *      The function itself returns:
1465  *      0   -> walk is complete.
1466  *      >0  -> walk is incomplete (i.e. suspended)
1467  *      <0  -> walk is terminated by an error.
1468  */
1469 
1470 static int fib6_walk_continue(struct fib6_walker *w)
1471 {
1472         struct fib6_node *fn, *pn;
1473 
1474         for (;;) {
1475                 fn = w->node;
1476                 if (!fn)
1477                         return 0;
1478 
1479                 if (w->prune && fn != w->root &&
1480                     fn->fn_flags & RTN_RTINFO && w->state < FWS_C) {
1481                         w->state = FWS_C;
1482                         w->leaf = fn->leaf;
1483                 }
1484                 switch (w->state) {
1485 #ifdef CONFIG_IPV6_SUBTREES
1486                 case FWS_S:
1487                         if (FIB6_SUBTREE(fn)) {
1488                                 w->node = FIB6_SUBTREE(fn);
1489                                 continue;
1490                         }
1491                         w->state = FWS_L;
1492 #endif
1493                 case FWS_L:
1494                         if (fn->left) {
1495                                 w->node = fn->left;
1496                                 w->state = FWS_INIT;
1497                                 continue;
1498                         }
1499                         w->state = FWS_R;
1500                 case FWS_R:
1501                         if (fn->right) {
1502                                 w->node = fn->right;
1503                                 w->state = FWS_INIT;
1504                                 continue;
1505                         }
1506                         w->state = FWS_C;
1507                         w->leaf = fn->leaf;
1508                 case FWS_C:
1509                         if (w->leaf && fn->fn_flags & RTN_RTINFO) {
1510                                 int err;
1511 
1512                                 if (w->skip) {
1513                                         w->skip--;
1514                                         goto skip;
1515                                 }
1516 
1517                                 err = w->func(w);
1518                                 if (err)
1519                                         return err;
1520 
1521                                 w->count++;
1522                                 continue;
1523                         }
1524 skip:
1525                         w->state = FWS_U;
1526                 case FWS_U:
1527                         if (fn == w->root)
1528                                 return 0;
1529                         pn = fn->parent;
1530                         w->node = pn;
1531 #ifdef CONFIG_IPV6_SUBTREES
1532                         if (FIB6_SUBTREE(pn) == fn) {
1533                                 WARN_ON(!(fn->fn_flags & RTN_ROOT));
1534                                 w->state = FWS_L;
1535                                 continue;
1536                         }
1537 #endif
1538                         if (pn->left == fn) {
1539                                 w->state = FWS_R;
1540                                 continue;
1541                         }
1542                         if (pn->right == fn) {
1543                                 w->state = FWS_C;
1544                                 w->leaf = w->node->leaf;
1545                                 continue;
1546                         }
1547 #if RT6_DEBUG >= 2
1548                         WARN_ON(1);
1549 #endif
1550                 }
1551         }
1552 }
1553 
1554 static int fib6_walk(struct fib6_walker *w)
1555 {
1556         int res;
1557 
1558         w->state = FWS_INIT;
1559         w->node = w->root;
1560 
1561         fib6_walker_link(w);
1562         res = fib6_walk_continue(w);
1563         if (res <= 0)
1564                 fib6_walker_unlink(w);
1565         return res;
1566 }
1567 
1568 static int fib6_clean_node(struct fib6_walker *w)
1569 {
1570         int res;
1571         struct rt6_info *rt;
1572         struct fib6_cleaner *c = container_of(w, struct fib6_cleaner, w);
1573         struct nl_info info = {
1574                 .nl_net = c->net,
1575         };
1576 
1577         if (c->sernum != FIB6_NO_SERNUM_CHANGE &&
1578             w->node->fn_sernum != c->sernum)
1579                 w->node->fn_sernum = c->sernum;
1580 
1581         if (!c->func) {
1582                 WARN_ON_ONCE(c->sernum == FIB6_NO_SERNUM_CHANGE);
1583                 w->leaf = NULL;
1584                 return 0;
1585         }
1586 
1587         for (rt = w->leaf; rt; rt = rt->dst.rt6_next) {
1588                 res = c->func(rt, c->arg);
1589                 if (res < 0) {
1590                         w->leaf = rt;
1591                         res = fib6_del(rt, &info);
1592                         if (res) {
1593 #if RT6_DEBUG >= 2
1594                                 pr_debug("%s: del failed: rt=%p@%p err=%d\n",
1595                                          __func__, rt, rt->rt6i_node, res);
1596 #endif
1597                                 continue;
1598                         }
1599                         return 0;
1600                 }
1601                 WARN_ON(res != 0);
1602         }
1603         w->leaf = rt;
1604         return 0;
1605 }
1606 
1607 /*
1608  *      Convenient frontend to tree walker.
1609  *
1610  *      func is called on each route.
1611  *              It may return -1 -> delete this route.
1612  *                            0  -> continue walking
1613  *
1614  *      prune==1 -> only immediate children of node (certainly,
1615  *      ignoring pure split nodes) will be scanned.
1616  */
1617 
1618 static void fib6_clean_tree(struct net *net, struct fib6_node *root,
1619                             int (*func)(struct rt6_info *, void *arg),
1620                             bool prune, int sernum, void *arg)
1621 {
1622         struct fib6_cleaner c;
1623 
1624         c.w.root = root;
1625         c.w.func = fib6_clean_node;
1626         c.w.prune = prune;
1627         c.w.count = 0;
1628         c.w.skip = 0;
1629         c.func = func;
1630         c.sernum = sernum;
1631         c.arg = arg;
1632         c.net = net;
1633 
1634         fib6_walk(&c.w);
1635 }
1636 
1637 static void __fib6_clean_all(struct net *net,
1638                              int (*func)(struct rt6_info *, void *),
1639                              int sernum, void *arg)
1640 {
1641         struct fib6_table *table;
1642         struct hlist_head *head;
1643         unsigned int h;
1644 
1645         rcu_read_lock();
1646         for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
1647                 head = &net->ipv6.fib_table_hash[h];
1648                 hlist_for_each_entry_rcu(table, head, tb6_hlist) {
1649                         write_lock_bh(&table->tb6_lock);
1650                         fib6_clean_tree(net, &table->tb6_root,
1651                                         func, false, sernum, arg);
1652                         write_unlock_bh(&table->tb6_lock);
1653                 }
1654         }
1655         rcu_read_unlock();
1656 }
1657 
1658 void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *),
1659                     void *arg)
1660 {
1661         __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg);
1662 }
1663 
1664 static int fib6_prune_clone(struct rt6_info *rt, void *arg)
1665 {
1666         if (rt->rt6i_flags & RTF_CACHE) {
1667                 RT6_TRACE("pruning clone %p\n", rt);
1668                 return -1;
1669         }
1670 
1671         return 0;
1672 }
1673 
1674 static void fib6_prune_clones(struct net *net, struct fib6_node *fn)
1675 {
1676         fib6_clean_tree(net, fn, fib6_prune_clone, true,
1677                         FIB6_NO_SERNUM_CHANGE, NULL);
1678 }
1679 
1680 static void fib6_flush_trees(struct net *net)
1681 {
1682         int new_sernum = fib6_new_sernum(net);
1683 
1684         __fib6_clean_all(net, NULL, new_sernum, NULL);
1685 }
1686 
1687 /*
1688  *      Garbage collection
1689  */
1690 
1691 static struct fib6_gc_args
1692 {
1693         int                     timeout;
1694         int                     more;
1695 } gc_args;
1696 
1697 static int fib6_age(struct rt6_info *rt, void *arg)
1698 {
1699         unsigned long now = jiffies;
1700 
1701         /*
1702          *      check addrconf expiration here.
1703          *      Routes are expired even if they are in use.
1704          *
1705          *      Also age clones. Note, that clones are aged out
1706          *      only if they are not in use now.
1707          */
1708 
1709         if (rt->rt6i_flags & RTF_EXPIRES && rt->dst.expires) {
1710                 if (time_after(now, rt->dst.expires)) {
1711                         RT6_TRACE("expiring %p\n", rt);
1712                         return -1;
1713                 }
1714                 gc_args.more++;
1715         } else if (rt->rt6i_flags & RTF_CACHE) {
1716                 if (atomic_read(&rt->dst.__refcnt) == 0 &&
1717                     time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) {
1718                         RT6_TRACE("aging clone %p\n", rt);
1719                         return -1;
1720                 } else if (rt->rt6i_flags & RTF_GATEWAY) {
1721                         struct neighbour *neigh;
1722                         __u8 neigh_flags = 0;
1723 
1724                         neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
1725                         if (neigh) {
1726                                 neigh_flags = neigh->flags;
1727                                 neigh_release(neigh);
1728                         }
1729                         if (!(neigh_flags & NTF_ROUTER)) {
1730                                 RT6_TRACE("purging route %p via non-router but gateway\n",
1731                                           rt);
1732                                 return -1;
1733                         }
1734                 }
1735                 gc_args.more++;
1736         }
1737 
1738         return 0;
1739 }
1740 
1741 static DEFINE_SPINLOCK(fib6_gc_lock);
1742 
1743 void fib6_run_gc(unsigned long expires, struct net *net, bool force)
1744 {
1745         unsigned long now;
1746 
1747         if (force) {
1748                 spin_lock_bh(&fib6_gc_lock);
1749         } else if (!spin_trylock_bh(&fib6_gc_lock)) {
1750                 mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
1751                 return;
1752         }
1753         gc_args.timeout = expires ? (int)expires :
1754                           net->ipv6.sysctl.ip6_rt_gc_interval;
1755 
1756         gc_args.more = icmp6_dst_gc();
1757 
1758         fib6_clean_all(net, fib6_age, NULL);
1759         now = jiffies;
1760         net->ipv6.ip6_rt_last_gc = now;
1761 
1762         if (gc_args.more)
1763                 mod_timer(&net->ipv6.ip6_fib_timer,
1764                           round_jiffies(now
1765                                         + net->ipv6.sysctl.ip6_rt_gc_interval));
1766         else
1767                 del_timer(&net->ipv6.ip6_fib_timer);
1768         spin_unlock_bh(&fib6_gc_lock);
1769 }
1770 
1771 static void fib6_gc_timer_cb(unsigned long arg)
1772 {
1773         fib6_run_gc(0, (struct net *)arg, true);
1774 }
1775 
1776 static int __net_init fib6_net_init(struct net *net)
1777 {
1778         size_t size = sizeof(struct hlist_head) * FIB6_TABLE_HASHSZ;
1779 
1780         setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net);
1781 
1782         net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
1783         if (!net->ipv6.rt6_stats)
1784                 goto out_timer;
1785 
1786         /* Avoid false sharing : Use at least a full cache line */
1787         size = max_t(size_t, size, L1_CACHE_BYTES);
1788 
1789         net->ipv6.fib_table_hash = kzalloc(size, GFP_KERNEL);
1790         if (!net->ipv6.fib_table_hash)
1791                 goto out_rt6_stats;
1792 
1793         net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
1794                                           GFP_KERNEL);
1795         if (!net->ipv6.fib6_main_tbl)
1796                 goto out_fib_table_hash;
1797 
1798         net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
1799         net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
1800         net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
1801                 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1802         inet_peer_base_init(&net->ipv6.fib6_main_tbl->tb6_peers);
1803 
1804 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
1805         net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl),
1806                                            GFP_KERNEL);
1807         if (!net->ipv6.fib6_local_tbl)
1808                 goto out_fib6_main_tbl;
1809         net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
1810         net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
1811         net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
1812                 RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
1813         inet_peer_base_init(&net->ipv6.fib6_local_tbl->tb6_peers);
1814 #endif
1815         fib6_tables_init(net);
1816 
1817         return 0;
1818 
1819 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
1820 out_fib6_main_tbl:
1821         kfree(net->ipv6.fib6_main_tbl);
1822 #endif
1823 out_fib_table_hash:
1824         kfree(net->ipv6.fib_table_hash);
1825 out_rt6_stats:
1826         kfree(net->ipv6.rt6_stats);
1827 out_timer:
1828         return -ENOMEM;
1829 }
1830 
1831 static void fib6_net_exit(struct net *net)
1832 {
1833         unsigned int i;
1834 
1835         rt6_ifdown(net, NULL);
1836         del_timer_sync(&net->ipv6.ip6_fib_timer);
1837 
1838         for (i = 0; i < FIB6_TABLE_HASHSZ; i++) {
1839                 struct hlist_head *head = &net->ipv6.fib_table_hash[i];
1840                 struct hlist_node *tmp;
1841                 struct fib6_table *tb;
1842 
1843                 hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) {
1844                         hlist_del(&tb->tb6_hlist);
1845                         fib6_free_table(tb);
1846                 }
1847         }
1848 
1849         kfree(net->ipv6.fib_table_hash);
1850         kfree(net->ipv6.rt6_stats);
1851 }
1852 
1853 static struct pernet_operations fib6_net_ops = {
1854         .init = fib6_net_init,
1855         .exit = fib6_net_exit,
1856 };
1857 
1858 int __init fib6_init(void)
1859 {
1860         int ret = -ENOMEM;
1861 
1862         fib6_node_kmem = kmem_cache_create("fib6_nodes",
1863                                            sizeof(struct fib6_node),
1864                                            0, SLAB_HWCACHE_ALIGN,
1865                                            NULL);
1866         if (!fib6_node_kmem)
1867                 goto out;
1868 
1869         ret = register_pernet_subsys(&fib6_net_ops);
1870         if (ret)
1871                 goto out_kmem_cache_create;
1872 
1873         ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib,
1874                               NULL);
1875         if (ret)
1876                 goto out_unregister_subsys;
1877 
1878         __fib6_flush_trees = fib6_flush_trees;
1879 out:
1880         return ret;
1881 
1882 out_unregister_subsys:
1883         unregister_pernet_subsys(&fib6_net_ops);
1884 out_kmem_cache_create:
1885         kmem_cache_destroy(fib6_node_kmem);
1886         goto out;
1887 }
1888 
1889 void fib6_gc_cleanup(void)
1890 {
1891         unregister_pernet_subsys(&fib6_net_ops);
1892         kmem_cache_destroy(fib6_node_kmem);
1893 }
1894 
1895 #ifdef CONFIG_PROC_FS
1896 
1897 struct ipv6_route_iter {
1898         struct seq_net_private p;
1899         struct fib6_walker w;
1900         loff_t skip;
1901         struct fib6_table *tbl;
1902         int sernum;
1903 };
1904 
1905 static int ipv6_route_seq_show(struct seq_file *seq, void *v)
1906 {
1907         struct rt6_info *rt = v;
1908         struct ipv6_route_iter *iter = seq->private;
1909 
1910         seq_printf(seq, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
1911 
1912 #ifdef CONFIG_IPV6_SUBTREES
1913         seq_printf(seq, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
1914 #else
1915         seq_puts(seq, "00000000000000000000000000000000 00 ");
1916 #endif
1917         if (rt->rt6i_flags & RTF_GATEWAY)
1918                 seq_printf(seq, "%pi6", &rt->rt6i_gateway);
1919         else
1920                 seq_puts(seq, "00000000000000000000000000000000");
1921 
1922         seq_printf(seq, " %08x %08x %08x %08x %8s\n",
1923                    rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
1924                    rt->dst.__use, rt->rt6i_flags,
1925                    rt->dst.dev ? rt->dst.dev->name : "");
1926         iter->w.leaf = NULL;
1927         return 0;
1928 }
1929 
1930 static int ipv6_route_yield(struct fib6_walker *w)
1931 {
1932         struct ipv6_route_iter *iter = w->args;
1933 
1934         if (!iter->skip)
1935                 return 1;
1936 
1937         do {
1938                 iter->w.leaf = iter->w.leaf->dst.rt6_next;
1939                 iter->skip--;
1940                 if (!iter->skip && iter->w.leaf)
1941                         return 1;
1942         } while (iter->w.leaf);
1943 
1944         return 0;
1945 }
1946 
1947 static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter)
1948 {
1949         memset(&iter->w, 0, sizeof(iter->w));
1950         iter->w.func = ipv6_route_yield;
1951         iter->w.root = &iter->tbl->tb6_root;
1952         iter->w.state = FWS_INIT;
1953         iter->w.node = iter->w.root;
1954         iter->w.args = iter;
1955         iter->sernum = iter->w.root->fn_sernum;
1956         INIT_LIST_HEAD(&iter->w.lh);
1957         fib6_walker_link(&iter->w);
1958 }
1959 
1960 static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl,
1961                                                     struct net *net)
1962 {
1963         unsigned int h;
1964         struct hlist_node *node;
1965 
1966         if (tbl) {
1967                 h = (tbl->tb6_id & (FIB6_TABLE_HASHSZ - 1)) + 1;
1968                 node = rcu_dereference_bh(hlist_next_rcu(&tbl->tb6_hlist));
1969         } else {
1970                 h = 0;
1971                 node = NULL;
1972         }
1973 
1974         while (!node && h < FIB6_TABLE_HASHSZ) {
1975                 node = rcu_dereference_bh(
1976                         hlist_first_rcu(&net->ipv6.fib_table_hash[h++]));
1977         }
1978         return hlist_entry_safe(node, struct fib6_table, tb6_hlist);
1979 }
1980 
1981 static void ipv6_route_check_sernum(struct ipv6_route_iter *iter)
1982 {
1983         if (iter->sernum != iter->w.root->fn_sernum) {
1984                 iter->sernum = iter->w.root->fn_sernum;
1985                 iter->w.state = FWS_INIT;
1986                 iter->w.node = iter->w.root;
1987                 WARN_ON(iter->w.skip);
1988                 iter->w.skip = iter->w.count;
1989         }
1990 }
1991 
1992 static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1993 {
1994         int r;
1995         struct rt6_info *n;
1996         struct net *net = seq_file_net(seq);
1997         struct ipv6_route_iter *iter = seq->private;
1998 
1999         if (!v)
2000                 goto iter_table;
2001 
2002         n = ((struct rt6_info *)v)->dst.rt6_next;
2003         if (n) {
2004                 ++*pos;
2005                 return n;
2006         }
2007 
2008 iter_table:
2009         ipv6_route_check_sernum(iter);
2010         read_lock(&iter->tbl->tb6_lock);
2011         r = fib6_walk_continue(&iter->w);
2012         read_unlock(&iter->tbl->tb6_lock);
2013         if (r > 0) {
2014                 if (v)
2015                         ++*pos;
2016                 return iter->w.leaf;
2017         } else if (r < 0) {
2018                 fib6_walker_unlink(&iter->w);
2019                 return NULL;
2020         }
2021         fib6_walker_unlink(&iter->w);
2022 
2023         iter->tbl = ipv6_route_seq_next_table(iter->tbl, net);
2024         if (!iter->tbl)
2025                 return NULL;
2026 
2027         ipv6_route_seq_setup_walk(iter);
2028         goto iter_table;
2029 }
2030 
2031 static void *ipv6_route_seq_start(struct seq_file *seq, loff_t *pos)
2032         __acquires(RCU_BH)
2033 {
2034         struct net *net = seq_file_net(seq);
2035         struct ipv6_route_iter *iter = seq->private;
2036 
2037         rcu_read_lock_bh();
2038         iter->tbl = ipv6_route_seq_next_table(NULL, net);
2039         iter->skip = *pos;
2040 
2041         if (iter->tbl) {
2042                 ipv6_route_seq_setup_walk(iter);
2043                 return ipv6_route_seq_next(seq, NULL, pos);
2044         } else {
2045                 return NULL;
2046         }
2047 }
2048 
2049 static bool ipv6_route_iter_active(struct ipv6_route_iter *iter)
2050 {
2051         struct fib6_walker *w = &iter->w;
2052         return w->node && !(w->state == FWS_U && w->node == w->root);
2053 }
2054 
2055 static void ipv6_route_seq_stop(struct seq_file *seq, void *v)
2056         __releases(RCU_BH)
2057 {
2058         struct ipv6_route_iter *iter = seq->private;
2059 
2060         if (ipv6_route_iter_active(iter))
2061                 fib6_walker_unlink(&iter->w);
2062 
2063         rcu_read_unlock_bh();
2064 }
2065 
2066 static const struct seq_operations ipv6_route_seq_ops = {
2067         .start  = ipv6_route_seq_start,
2068         .next   = ipv6_route_seq_next,
2069         .stop   = ipv6_route_seq_stop,
2070         .show   = ipv6_route_seq_show
2071 };
2072 
2073 int ipv6_route_open(struct inode *inode, struct file *file)
2074 {
2075         return seq_open_net(inode, file, &ipv6_route_seq_ops,
2076                             sizeof(struct ipv6_route_iter));
2077 }
2078 
2079 #endif /* CONFIG_PROC_FS */
2080 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp