]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-table.c
2 * BIRD -- Routing Tables
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 * Routing tables are probably the most important structures BIRD uses. They
13 * hold all the information about known networks, the associated routes and
16 * There are multiple routing tables (a primary one together with any
17 * number of secondary ones if requested by the configuration). Each table
18 * is basically a FIB containing entries describing the individual
19 * destination networks. For each network (represented by structure &net),
20 * there is a one-way linked list of route entries (&rte), the first entry
21 * on the list being the best one (i.e., the one we currently use
22 * for routing), the order of the other ones is undetermined.
24 * The &rte contains information specific to the route (preference, protocol
25 * metrics, time of last modification etc.) and a pointer to a &rta structure
26 * (see the route attribute module for a precise explanation) holding the
27 * remaining route attributes which are expected to be shared by multiple
28 * routes in order to conserve memory.
33 #include "nest/bird.h"
34 #include "nest/route.h"
35 #include "nest/protocol.h"
37 #include "nest/iface.h"
38 #include "lib/resource.h"
39 #include "lib/event.h"
40 #include "lib/string.h"
41 #include "conf/conf.h"
42 #include "filter/filter.h"
43 #include "lib/string.h"
44 #include "lib/alloca.h"
48 static slab
*rte_slab
;
49 static linpool
*rte_update_pool
;
51 static list routing_tables
;
53 static void rt_format_via(rte
*e
, byte
*via
);
54 static void rt_free_hostcache(rtable
*tab
);
55 static void rt_notify_hostcache(rtable
*tab
, net
*net
);
56 static void rt_update_hostcache(rtable
*tab
);
57 static void rt_next_hop_update(rtable
*tab
);
59 static inline void rt_schedule_gc(rtable
*tab
);
61 /* Like fib_route(), but skips empty net entries */
63 net_route(rtable
*tab
, ip_addr a
, int len
)
70 a0
= ipa_and(a
, ipa_mkmask(len
));
71 n
= fib_find(&tab
->fib
, &a0
, len
);
80 rte_init(struct fib_node
*N
)
89 * rte_find - find a route
93 * The rte_find() function returns a route for destination @net
94 * which belongs has been defined by protocol @p.
97 rte_find(net
*net
, struct proto
*p
)
101 while (e
&& e
->attrs
->proto
!= p
)
107 * rte_get_temp - get a temporary &rte
108 * @a: attributes to assign to the new route (a &rta; in case it's
109 * un-cached, rte_update() will create a cached copy automatically)
111 * Create a temporary &rte and bind it with the attributes @a.
112 * Also set route preference to the default preference set for
118 rte
*e
= sl_alloc(rte_slab
);
122 e
->pref
= a
->proto
->preference
;
129 rte
*e
= sl_alloc(rte_slab
);
131 memcpy(e
, r
, sizeof(rte
));
132 e
->attrs
= rta_clone(r
->attrs
);
137 static int /* Actually better or at least as good as */
138 rte_better(rte
*new, rte
*old
)
140 int (*better
)(rte
*, rte
*);
144 if (new->pref
> old
->pref
)
146 if (new->pref
< old
->pref
)
148 if (new->attrs
->proto
->proto
!= old
->attrs
->proto
->proto
)
151 * If the user has configured protocol preferences, so that two different protocols
152 * have the same preference, try to break the tie by comparing addresses. Not too
153 * useful, but keeps the ordering of routes unambiguous.
155 return new->attrs
->proto
->proto
> old
->attrs
->proto
->proto
;
157 if (better
= new->attrs
->proto
->rte_better
)
158 return better(new, old
);
163 rte_trace(struct proto
*p
, rte
*e
, int dir
, char *msg
)
165 byte via
[STD_ADDRESS_P_LENGTH
+32];
167 rt_format_via(e
, via
);
168 log(L_TRACE
"%s %c %s %I/%d %s", p
->name
, dir
, msg
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, via
);
172 rte_trace_in(unsigned int flag
, struct proto
*p
, rte
*e
, char *msg
)
175 rte_trace(p
, e
, '>', msg
);
179 rte_trace_out(unsigned int flag
, struct proto
*p
, rte
*e
, char *msg
)
182 rte_trace(p
, e
, '<', msg
);
186 export_filter(struct announce_hook
*ah
, rte
*rt0
, rte
**rt_free
, ea_list
**tmpa
, int silent
)
188 struct proto
*p
= ah
->proto
;
189 struct filter
*filter
= ah
->out_filter
;
190 struct proto_stats
*stats
= ah
->stats
;
191 ea_list
*tmpb
= NULL
;
198 /* If called does not care for eattrs, we prepare one internally */
201 struct proto
*src
= rt
->attrs
->proto
;
202 tmpb
= src
->make_tmp_attrs
? src
->make_tmp_attrs(rt
, rte_update_pool
) : NULL
;
206 v
= p
->import_control
? p
->import_control(p
, &rt
, tmpa
, rte_update_pool
) : 0;
212 stats
->exp_updates_rejected
++;
213 rte_trace_out(D_FILTERS
, p
, rt
, "rejected by protocol");
219 rte_trace_out(D_FILTERS
, p
, rt
, "forced accept by protocol");
223 v
= filter
&& ((filter
== FILTER_REJECT
) ||
224 (f_run(filter
, &rt
, tmpa
, rte_update_pool
, FF_FORCE_TMPATTR
) > F_ACCEPT
));
230 stats
->exp_updates_filtered
++;
231 rte_trace_out(D_FILTERS
, p
, rt
, "filtered out");
241 /* Discard temporary rte */
248 do_rt_notify(struct announce_hook
*ah
, net
*net
, rte
*new, rte
*old
, ea_list
*tmpa
, int refeed
)
250 struct proto
*p
= ah
->proto
;
251 struct proto_stats
*stats
= ah
->stats
;
254 stats
->exp_updates_accepted
++;
256 stats
->exp_withdraws_accepted
++;
258 /* Hack: We do not decrease exp_routes during refeed, we instead
259 reset exp_routes at the start of refeed. */
265 if (p
->debug
& D_ROUTES
)
268 rte_trace_out(D_ROUTES
, p
, new, "replaced");
270 rte_trace_out(D_ROUTES
, p
, new, "added");
272 rte_trace_out(D_ROUTES
, p
, old
, "removed");
275 p
->rt_notify(p
, ah
->table
, net
, NULL
, old
, NULL
);
281 t
->next
= new->attrs
->eattrs
;
282 p
->rt_notify(p
, ah
->table
, net
, new, old
, tmpa
);
286 p
->rt_notify(p
, ah
->table
, net
, new, old
, new->attrs
->eattrs
);
292 rt_notify_basic(struct announce_hook
*ah
, net
*net
, rte
*new, rte
*old
, ea_list
*tmpa
, int refeed
)
294 // struct proto *p = ah->proto;
295 struct proto_stats
*stats
= ah
->stats
;
297 rte
*new_free
= NULL
;
298 rte
*old_free
= NULL
;
301 stats
->exp_updates_received
++;
303 stats
->exp_withdraws_received
++;
306 * This is a tricky part - we don't know whether route 'old' was
307 * exported to protocol 'p' or was filtered by the export filter.
308 * We try to run the export filter to know this to have a correct
309 * value in 'old' argument of rte_update (and proper filter value)
311 * FIXME - this is broken because 'configure soft' may change
312 * filters but keep routes. Refeed is expected to be called after
313 * change of the filters and with old == new, therefore we do not
314 * even try to run the filter on an old route, This may lead to
315 * 'spurious withdraws' but ensure that there are no 'missing
318 * This is not completely safe as there is a window between
319 * reconfiguration and the end of refeed - if a newly filtered
320 * route disappears during this period, proper withdraw is not
321 * sent (because old would be also filtered) and the route is
322 * not refeeded (because it disappeared before that).
326 new = export_filter(ah
, new, &new_free
, &tmpa
, 0);
329 old
= export_filter(ah
, old
, &old_free
, NULL
, 1);
331 /* FIXME - This is broken because of incorrect 'old' value (see above) */
335 do_rt_notify(ah
, net
, new, old
, tmpa
, refeed
);
337 /* Discard temporary rte's */
345 rt_notify_accepted(struct announce_hook
*ah
, net
*net
, rte
*new_changed
, rte
*old_changed
, rte
*before_old
,
346 ea_list
*tmpa
, int feed
)
348 // struct proto *p = ah->proto;
349 struct proto_stats
*stats
= ah
->stats
;
351 rte
*new_best
= NULL
;
352 rte
*old_best
= NULL
;
353 rte
*new_free
= NULL
;
354 rte
*old_free
= NULL
;
357 /* Used to track whether we met old_changed position. If it is NULL
358 it was the first and met it implicitly before current best route. */
359 int old_meet
= (old_changed
&& !before_old
) ? 1 : 0;
362 stats
->exp_updates_received
++;
364 stats
->exp_withdraws_received
++;
366 /* First, find the new_best route - first accepted by filters */
367 for (r
=net
->routes
; r
; r
=r
->next
)
369 if (new_best
= export_filter(ah
, r
, &new_free
, &tmpa
, 0))
372 /* Note if we walked around the position of old_changed route */
378 * Second, handle the feed case. That means we do not care for
379 * old_best. It is NULL for feed, and the new_best for refeed.
380 * For refeed, there is a hack similar to one in rt_notify_basic()
381 * to ensure withdraws in case of changed filters
385 if (feed
== 2) /* refeed */
386 old_best
= new_best
? new_best
: net
->routes
;
390 if (!new_best
&& !old_best
)
397 * Now, we find the old_best route. Generally, it is the same as the
398 * new_best, unless new_best is the same as new_changed or
399 * old_changed is accepted before new_best.
401 * There are four cases:
403 * - We would find and accept old_changed before new_best, therefore
404 * old_changed is old_best. In remaining cases we suppose this
407 * - We found no new_best, therefore there is also no old_best and
408 * we ignore this withdraw.
410 * - We found new_best different than new_changed, therefore
411 * old_best is the same as new_best and we ignore this update.
413 * - We found new_best the same as new_changed, therefore it cannot
414 * be old_best and we have to continue search for old_best.
419 if (old_best
= export_filter(ah
, old_changed
, &old_free
, NULL
, 1))
426 /* Third case, we use r insead of new_best, because export_filter() could change it */
427 if (r
!= new_changed
)
437 if (old_best
= export_filter(ah
, r
, &old_free
, NULL
, 1))
441 if (old_best
= export_filter(ah
, old_changed
, &old_free
, NULL
, 1))
445 /* Implicitly, old_best is NULL and new_best is non-NULL */
448 do_rt_notify(ah
, net
, new_best
, old_best
, tmpa
, (feed
== 2));
450 /* Discard temporary rte's */
458 * rte_announce - announce a routing table change
459 * @tab: table the route has been added to
460 * @type: type of route announcement (RA_OPTIMAL or RA_ANY)
461 * @net: network in question
462 * @new: the new route to be announced
463 * @old: the previous route for the same network
464 * @tmpa: a list of temporary attributes belonging to the new route
466 * This function gets a routing table update and announces it
467 * to all protocols that acccepts given type of route announcement
468 * and are connected to the same table by their announcement hooks.
470 * Route announcement of type RA_OPTIMAL si generated when optimal
471 * route (in routing table @tab) changes. In that case @old stores the
474 * Route announcement of type RA_ANY si generated when any route (in
475 * routing table @tab) changes In that case @old stores the old route
476 * from the same protocol.
478 * For each appropriate protocol, we first call its import_control()
479 * hook which performs basic checks on the route (each protocol has a
480 * right to veto or force accept of the route before any filter is
481 * asked) and adds default values of attributes specific to the new
482 * protocol (metrics, tags etc.). Then it consults the protocol's
483 * export filter and if it accepts the route, the rt_notify() hook of
484 * the protocol gets called.
487 rte_announce(rtable
*tab
, unsigned type
, net
*net
, rte
*new, rte
*old
, rte
*before_old
, ea_list
*tmpa
)
489 struct announce_hook
*a
;
491 if (type
== RA_OPTIMAL
)
494 new->attrs
->proto
->stats
.pref_routes
++;
496 old
->attrs
->proto
->stats
.pref_routes
--;
499 rt_notify_hostcache(tab
, net
);
502 WALK_LIST(a
, tab
->hooks
)
504 ASSERT(a
->proto
->core_state
== FS_HAPPY
|| a
->proto
->core_state
== FS_FEEDING
);
505 if (a
->proto
->accept_ra_types
== type
)
506 if (type
== RA_ACCEPTED
)
507 rt_notify_accepted(a
, net
, new, old
, before_old
, tmpa
, 0);
509 rt_notify_basic(a
, net
, new, old
, tmpa
, 0);
519 if ((n
->n
.pxlen
> BITS_PER_IP_ADDRESS
) || !ip_is_prefix(n
->n
.prefix
,n
->n
.pxlen
))
521 log(L_WARN
"Ignoring bogus prefix %I/%d received via %s",
522 n
->n
.prefix
, n
->n
.pxlen
, e
->sender
->proto
->name
);
526 c
= ipa_classify_net(n
->n
.prefix
);
527 if ((c
< 0) || !(c
& IADDR_HOST
) || ((c
& IADDR_SCOPE_MASK
) <= SCOPE_LINK
))
529 log(L_WARN
"Ignoring bogus route %I/%d received via %s",
530 n
->n
.prefix
, n
->n
.pxlen
, e
->sender
->proto
->name
);
538 * rte_free - delete a &rte
539 * @e: &rte to be deleted
541 * rte_free() deletes the given &rte from the routing table it's linked to.
546 if (e
->attrs
->aflags
& RTAF_CACHED
)
548 sl_free(rte_slab
, e
);
552 rte_free_quick(rte
*e
)
555 sl_free(rte_slab
, e
);
559 rte_same(rte
*x
, rte
*y
)
562 x
->attrs
== y
->attrs
&&
563 x
->flags
== y
->flags
&&
564 x
->pflags
== y
->pflags
&&
565 x
->pref
== y
->pref
&&
566 (!x
->attrs
->proto
->rte_same
|| x
->attrs
->proto
->rte_same(x
, y
));
570 rte_recalculate(struct announce_hook
*ah
, net
*net
, rte
*new, ea_list
*tmpa
, struct proto
*src
)
572 struct proto
*p
= ah
->proto
;
573 struct rtable
*table
= ah
->table
;
574 struct proto_stats
*stats
= ah
->stats
;
575 rte
*before_old
= NULL
;
576 rte
*old_best
= net
->routes
;
580 k
= &net
->routes
; /* Find and remove original route from the same protocol */
583 if (old
->attrs
->proto
== src
)
585 /* If there is the same route in the routing table but from
586 * a different sender, then there are two paths from the
587 * source protocol to this routing table through transparent
588 * pipes, which is not allowed.
590 * We log that and ignore the route. If it is withdraw, we
591 * ignore it completely (there might be 'spurious withdraws',
592 * see FIXME in do_rte_announce())
594 if (old
->sender
->proto
!= p
)
598 log(L_ERR
"Pipe collision detected when sending %I/%d to table %s",
599 net
->n
.prefix
, net
->n
.pxlen
, table
->name
);
605 if (new && rte_same(old
, new))
607 /* No changes, ignore the new route */
608 stats
->imp_updates_ignored
++;
609 rte_trace_in(D_ROUTES
, p
, new, "ignored");
612 /* lastmod is used internally by RIP as the last time
613 when the route was received. */
614 if (src
->proto
== &proto_rip
)
631 stats
->imp_withdraws_ignored
++;
636 stats
->imp_updates_accepted
++;
638 stats
->imp_withdraws_accepted
++;
647 for (k
=&net
->routes
; *k
; k
=&(*k
)->next
)
648 if (rte_better(new, *k
))
655 rte_trace_in(D_ROUTES
, p
, new, net
->routes
== new ? "added [best]" : "added");
658 /* Log the route removal */
659 if (!new && (p
->debug
& D_ROUTES
))
662 rte_trace_in(D_ROUTES
, p
, old
, "removed");
663 else if (net
->routes
)
664 rte_trace_in(D_ROUTES
, p
, old
, "removed [replaced]");
666 rte_trace_in(D_ROUTES
, p
, old
, "removed [sole]");
669 rte_announce(table
, RA_ANY
, net
, new, old
, NULL
, tmpa
);
670 rte_announce(table
, RA_OPTIMAL
, net
, net
->routes
, old_best
, NULL
, tmpa
);
671 rte_announce(table
, RA_ACCEPTED
, net
, new, old
, before_old
, tmpa
);
674 (table
->gc_counter
++ >= table
->config
->gc_max_ops
) &&
675 (table
->gc_time
+ table
->config
->gc_min_time
<= now
))
676 rt_schedule_gc(table
);
681 p
->rte_remove(net
, old
);
687 p
->rte_insert(net
, new);
691 static int rte_update_nest_cnt
; /* Nesting counter to allow recursive updates */
694 rte_update_lock(void)
696 rte_update_nest_cnt
++;
700 rte_update_unlock(void)
702 if (!--rte_update_nest_cnt
)
703 lp_flush(rte_update_pool
);
707 * rte_update - enter a new update to a routing table
708 * @table: table to be updated
709 * @ah: pointer to table announce hook
711 * @p: protocol submitting the update
712 * @src: protocol originating the update
713 * @new: a &rte representing the new route or %NULL for route removal.
715 * This function is called by the routing protocols whenever they discover
716 * a new route or wish to update/remove an existing route. The right announcement
717 * sequence is to build route attributes first (either un-cached with @aflags set
718 * to zero or a cached one using rta_lookup(); in this case please note that
719 * you need to increase the use count of the attributes yourself by calling
720 * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
721 * the appropriate data and finally submit the new &rte by calling rte_update().
723 * @src specifies the protocol that originally created the route and the meaning
724 * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
725 * same value as @new->attrs->proto. @p specifies the protocol that called
726 * rte_update(). In most cases it is the same protocol as @src. rte_update()
727 * stores @p in @new->sender;
729 * When rte_update() gets any route, it automatically validates it (checks,
730 * whether the network and next hop address are valid IP addresses and also
731 * whether a normal routing protocol doesn't try to smuggle a host or link
732 * scope route to the table), converts all protocol dependent attributes stored
733 * in the &rte to temporary extended attributes, consults import filters of the
734 * protocol to see if the route should be accepted and/or its attributes modified,
735 * stores the temporary attributes back to the &rte.
737 * Now, having a "public" version of the route, we
738 * automatically find any old route defined by the protocol @src
739 * for network @n, replace it by the new one (or removing it if @new is %NULL),
740 * recalculate the optimal route for this destination and finally broadcast
741 * the change (if any) to all routing protocols by calling rte_announce().
743 * All memory used for attribute lists and other temporary allocations is taken
744 * from a special linear pool @rte_update_pool and freed when rte_update()
749 rte_update2(struct announce_hook
*ah
, net
*net
, rte
*new, struct proto
*src
)
751 struct proto
*p
= ah
->proto
;
752 struct proto_stats
*stats
= ah
->stats
;
753 struct filter
*filter
= ah
->in_filter
;
754 ea_list
*tmpa
= NULL
;
761 stats
->imp_updates_received
++;
762 if (!rte_validate(new))
764 rte_trace_in(D_FILTERS
, p
, new, "invalid");
765 stats
->imp_updates_invalid
++;
768 if (filter
== FILTER_REJECT
)
770 stats
->imp_updates_filtered
++;
771 rte_trace_in(D_FILTERS
, p
, new, "filtered out");
774 if (src
->make_tmp_attrs
)
775 tmpa
= src
->make_tmp_attrs(new, rte_update_pool
);
778 ea_list
*old_tmpa
= tmpa
;
779 int fr
= f_run(filter
, &new, &tmpa
, rte_update_pool
, 0);
782 stats
->imp_updates_filtered
++;
783 rte_trace_in(D_FILTERS
, p
, new, "filtered out");
786 if (tmpa
!= old_tmpa
&& src
->store_tmp_attrs
)
787 src
->store_tmp_attrs(new, tmpa
);
789 if (!(new->attrs
->aflags
& RTAF_CACHED
)) /* Need to copy attributes */
790 new->attrs
= rta_lookup(new->attrs
);
791 new->flags
|= REF_COW
;
794 stats
->imp_withdraws_received
++;
796 rte_recalculate(ah
, net
, new, tmpa
, src
);
802 rte_recalculate(ah
, net
, NULL
, NULL
, src
);
806 /* Independent call to rte_announce(), used from next hop
807 recalculation, outside of rte_update(). new must be non-NULL */
809 rte_announce_i(rtable
*tab
, unsigned type
, net
*n
, rte
*new, rte
*old
)
815 src
= new->attrs
->proto
;
816 tmpa
= src
->make_tmp_attrs
? src
->make_tmp_attrs(new, rte_update_pool
) : NULL
;
817 rte_announce(tab
, type
, n
, new, old
, NULL
, tmpa
);
822 rte_discard(rtable
*t
, rte
*old
) /* Non-filtered route deletion, used during garbage collection */
825 rte_recalculate(old
->sender
, old
->net
, NULL
, NULL
, old
->attrs
->proto
);
830 * rte_dump - dump a route
831 * @e: &rte to be dumped
833 * This functions dumps contents of a &rte to debug output.
840 debug("%-1I/%2d ", n
->n
.prefix
, n
->n
.pxlen
);
843 debug("KF=%02x PF=%02x pref=%d lm=%d ", n
->n
.flags
, e
->pflags
, e
->pref
, now
-e
->lastmod
);
845 if (e
->attrs
->proto
->proto
->dump_attrs
)
846 e
->attrs
->proto
->proto
->dump_attrs(e
);
851 * rt_dump - dump a routing table
852 * @t: routing table to be dumped
854 * This function dumps contents of a given routing table to debug output.
861 struct announce_hook
*a
;
863 debug("Dump of routing table <%s>\n", t
->name
);
867 FIB_WALK(&t
->fib
, fn
)
870 for(e
=n
->routes
; e
; e
=e
->next
)
874 WALK_LIST(a
, t
->hooks
)
875 debug("\tAnnounces routes to protocol %s\n", a
->proto
->name
);
880 * rt_dump_all - dump all routing tables
882 * This function dumps contents of all routing tables to debug output.
889 WALK_LIST(t
, routing_tables
)
894 rt_schedule_gc(rtable
*tab
)
896 if (tab
->gc_scheduled
)
899 tab
->gc_scheduled
= 1;
900 ev_schedule(tab
->rt_event
);
904 rt_schedule_hcu(rtable
*tab
)
906 if (tab
->hcu_scheduled
)
909 tab
->hcu_scheduled
= 1;
910 ev_schedule(tab
->rt_event
);
914 rt_schedule_nhu(rtable
*tab
)
916 if (tab
->nhu_state
== 0)
917 ev_schedule(tab
->rt_event
);
919 /* state change 0->1, 2->3 */
924 rt_prune_nets(rtable
*tab
)
926 struct fib_iterator fit
;
927 int ncnt
= 0, ndel
= 0;
930 fib_check(&tab
->fib
);
933 FIB_ITERATE_INIT(&fit
, &tab
->fib
);
935 FIB_ITERATE_START(&tab
->fib
, &fit
, f
)
939 if (!n
->routes
) /* Orphaned FIB entry */
941 FIB_ITERATE_PUT(&fit
, f
);
942 fib_delete(&tab
->fib
, f
);
948 DBG("Pruned %d of %d networks\n", ndel
, ncnt
);
952 tab
->gc_scheduled
= 0;
960 if (tab
->hcu_scheduled
)
961 rt_update_hostcache(tab
);
964 rt_next_hop_update(tab
);
966 if (tab
->gc_scheduled
)
971 rt_setup(pool
*p
, rtable
*t
, char *name
, struct rtable_config
*cf
)
973 bzero(t
, sizeof(*t
));
974 fib_init(&t
->fib
, p
, sizeof(net
), 0, rte_init
);
977 init_list(&t
->hooks
);
980 t
->rt_event
= ev_new(p
);
981 t
->rt_event
->hook
= rt_event
;
982 t
->rt_event
->data
= t
;
988 * rt_init - initialize routing tables
990 * This function is called during BIRD startup. It initializes the
991 * routing table module.
997 rt_table_pool
= rp_new(&root_pool
, "Routing tables");
998 rte_update_pool
= lp_new(rt_table_pool
, 4080);
999 rte_slab
= sl_new(rt_table_pool
, sizeof(rte
));
1000 init_list(&routing_tables
);
1004 /* Called from proto_schedule_flush_loop() only,
1005 ensuring that all prune states are zero */
1007 rt_schedule_prune_all(void)
1011 WALK_LIST(t
, routing_tables
)
1016 rt_prune_step(rtable
*tab
, int *max_feed
)
1018 struct fib_iterator
*fit
= &tab
->prune_fit
;
1020 DBG("Pruning route table %s\n", tab
->name
);
1022 fib_check(&tab
->fib
);
1025 if (tab
->prune_state
== 0)
1028 if (tab
->prune_state
== 1)
1030 FIB_ITERATE_INIT(fit
, &tab
->fib
);
1031 tab
->prune_state
= 2;
1035 FIB_ITERATE_START(&tab
->fib
, fit
, fn
)
1037 net
*n
= (net
*) fn
;
1041 for (e
=n
->routes
; e
; e
=e
->next
)
1042 if (e
->sender
->proto
->core_state
!= FS_HAPPY
&&
1043 e
->sender
->proto
->core_state
!= FS_FEEDING
)
1047 FIB_ITERATE_PUT(fit
, fn
);
1051 rte_discard(tab
, e
);
1056 if (!n
->routes
) /* Orphaned FIB entry */
1058 FIB_ITERATE_PUT(fit
, fn
);
1059 fib_delete(&tab
->fib
, fn
);
1063 FIB_ITERATE_END(fn
);
1066 fib_check(&tab
->fib
);
1069 tab
->prune_state
= 0;
1074 * rt_prune_loop - prune routing tables
1075 * @tab: routing table to be pruned
1077 * The prune loop scans routing tables and removes routes belonging to
1078 * inactive protocols and also stale network entries. Returns 1 when
1079 * all such routes are pruned. It is a part of the protocol flushing
1088 WALK_LIST(t
, routing_tables
)
1089 if (! rt_prune_step(t
, &max_feed
))
1096 rt_preconfig(struct config
*c
)
1098 struct symbol
*s
= cf_find_symbol("master");
1100 init_list(&c
->tables
);
1101 c
->master_rtc
= rt_new_table(s
);
1106 * Some functions for handing internal next hop updates
1107 * triggered by rt_schedule_nhu().
1111 rta_next_hop_outdated(rta
*a
)
1113 struct hostentry
*he
= a
->hostentry
;
1119 return a
->dest
!= RTD_UNREACHABLE
;
1121 return (a
->iface
!= he
->src
->iface
) || !ipa_equal(a
->gw
, he
->gw
) ||
1122 (a
->dest
!= he
->dest
) || (a
->igp_metric
!= he
->igp_metric
) ||
1123 !mpnh_same(a
->nexthops
, he
->src
->nexthops
);
1127 rta_apply_hostentry(rta
*a
, struct hostentry
*he
)
1130 a
->iface
= he
->src
? he
->src
->iface
: NULL
;
1133 a
->igp_metric
= he
->igp_metric
;
1134 a
->nexthops
= he
->src
? he
->src
->nexthops
: NULL
;
1138 rt_next_hop_update_rte(rtable
*tab
, rte
*old
)
1141 memcpy(&a
, old
->attrs
, sizeof(rta
));
1142 rta_apply_hostentry(&a
, old
->attrs
->hostentry
);
1145 rte
*e
= sl_alloc(rte_slab
);
1146 memcpy(e
, old
, sizeof(rte
));
1147 e
->attrs
= rta_lookup(&a
);
1153 rt_next_hop_update_net(rtable
*tab
, net
*n
)
1155 rte
**k
, *e
, *new, *old_best
, **new_best
;
1157 int free_old_best
= 0;
1159 old_best
= n
->routes
;
1163 for (k
= &n
->routes
; e
= *k
; k
= &e
->next
)
1164 if (rta_next_hop_outdated(e
->attrs
))
1166 new = rt_next_hop_update_rte(tab
, e
);
1169 rte_announce_i(tab
, RA_ANY
, n
, new, e
);
1170 rte_trace_in(D_ROUTES
, new->sender
->proto
, new, "updated");
1172 /* Call a pre-comparison hook */
1173 /* Not really an efficient way to compute this */
1174 if (e
->attrs
->proto
->rte_recalculate
)
1175 e
->attrs
->proto
->rte_recalculate(tab
, n
, new, e
, NULL
);
1179 else /* Freeing of the old best rte is postponed */
1189 /* Find the new best route */
1191 for (k
= &n
->routes
; e
= *k
; k
= &e
->next
)
1193 if (!new_best
|| rte_better(e
, *new_best
))
1197 /* Relink the new best route to the first position */
1199 if (new != n
->routes
)
1201 *new_best
= new->next
;
1202 new->next
= n
->routes
;
1206 /* Announce the new best route */
1207 if (new != old_best
)
1209 rte_announce_i(tab
, RA_OPTIMAL
, n
, new, old_best
);
1210 rte_trace_in(D_ROUTES
, new->sender
->proto
, new, "updated [best]");
1214 rte_free_quick(old_best
);
1220 rt_next_hop_update(rtable
*tab
)
1222 struct fib_iterator
*fit
= &tab
->nhu_fit
;
1225 if (tab
->nhu_state
== 0)
1228 if (tab
->nhu_state
== 1)
1230 FIB_ITERATE_INIT(fit
, &tab
->fib
);
1234 FIB_ITERATE_START(&tab
->fib
, fit
, fn
)
1238 FIB_ITERATE_PUT(fit
, fn
);
1239 ev_schedule(tab
->rt_event
);
1242 max_feed
-= rt_next_hop_update_net(tab
, (net
*) fn
);
1244 FIB_ITERATE_END(fn
);
1246 /* state change 2->0, 3->1 */
1247 tab
->nhu_state
&= 1;
1249 if (tab
->nhu_state
> 0)
1250 ev_schedule(tab
->rt_event
);
1254 struct rtable_config
*
1255 rt_new_table(struct symbol
*s
)
1257 struct rtable_config
*c
= cfg_allocz(sizeof(struct rtable_config
));
1259 cf_define_symbol(s
, SYM_TABLE
, c
);
1261 add_tail(&new_config
->tables
, &c
->n
);
1262 c
->gc_max_ops
= 1000;
1268 * rt_lock_table - lock a routing table
1269 * @r: routing table to be locked
1271 * Lock a routing table, because it's in use by a protocol,
1272 * preventing it from being freed when it gets undefined in a new
1276 rt_lock_table(rtable
*r
)
1282 * rt_unlock_table - unlock a routing table
1283 * @r: routing table to be unlocked
1285 * Unlock a routing table formerly locked by rt_lock_table(),
1286 * that is decrease its use count and delete it if it's scheduled
1287 * for deletion by configuration changes.
1290 rt_unlock_table(rtable
*r
)
1292 if (!--r
->use_count
&& r
->deleted
)
1294 struct config
*conf
= r
->deleted
;
1295 DBG("Deleting routing table %s\n", r
->name
);
1297 rt_free_hostcache(r
);
1302 config_del_obstacle(conf
);
1307 * rt_commit - commit new routing table configuration
1308 * @new: new configuration
1309 * @old: original configuration or %NULL if it's boot time config
1311 * Scan differences between @old and @new configuration and modify
1312 * the routing tables according to these changes. If @new defines a
1313 * previously unknown table, create it, if it omits a table existing
1314 * in @old, schedule it for deletion (it gets deleted when all protocols
1315 * disconnect from it by calling rt_unlock_table()), if it exists
1316 * in both configurations, leave it unchanged.
1319 rt_commit(struct config
*new, struct config
*old
)
1321 struct rtable_config
*o
, *r
;
1323 DBG("rt_commit:\n");
1326 WALK_LIST(o
, old
->tables
)
1328 rtable
*ot
= o
->table
;
1331 struct symbol
*sym
= cf_find_symbol(o
->name
);
1332 if (sym
&& sym
->class == SYM_TABLE
&& !new->shutdown
)
1334 DBG("\t%s: same\n", o
->name
);
1342 DBG("\t%s: deleted\n", o
->name
);
1344 config_add_obstacle(old
);
1346 rt_unlock_table(ot
);
1352 WALK_LIST(r
, new->tables
)
1355 rtable
*t
= mb_alloc(rt_table_pool
, sizeof(struct rtable
));
1356 DBG("\t%s: created\n", r
->name
);
1357 rt_setup(rt_table_pool
, t
, r
->name
, r
);
1358 add_tail(&routing_tables
, &t
->n
);
1365 do_feed_baby(struct proto
*p
, int type
, struct announce_hook
*h
, net
*n
, rte
*e
)
1367 struct proto
*src
= e
->attrs
->proto
;
1371 tmpa
= src
->make_tmp_attrs
? src
->make_tmp_attrs(e
, rte_update_pool
) : NULL
;
1372 if (type
== RA_ACCEPTED
)
1373 rt_notify_accepted(h
, n
, e
, NULL
, NULL
, tmpa
, p
->refeeding
? 2 : 1);
1375 rt_notify_basic(h
, n
, e
, p
->refeeding
? e
: NULL
, tmpa
, p
->refeeding
);
1376 rte_update_unlock();
1380 * rt_feed_baby - advertise routes to a new protocol
1381 * @p: protocol to be fed
1383 * This function performs one pass of advertisement of routes to a newly
1384 * initialized protocol. It's called by the protocol code as long as it
1385 * has something to do. (We avoid transferring all the routes in single
1386 * pass in order not to monopolize CPU time.)
1389 rt_feed_baby(struct proto
*p
)
1391 struct announce_hook
*h
;
1392 struct fib_iterator
*fit
;
1395 if (!p
->feed_ahook
) /* Need to initialize first */
1399 DBG("Announcing routes to new protocol %s\n", p
->name
);
1400 p
->feed_ahook
= p
->ahooks
;
1401 fit
= p
->feed_iterator
= mb_alloc(p
->pool
, sizeof(struct fib_iterator
));
1404 fit
= p
->feed_iterator
;
1408 FIB_ITERATE_START(&h
->table
->fib
, fit
, fn
)
1410 net
*n
= (net
*) fn
;
1414 FIB_ITERATE_PUT(fit
, fn
);
1418 if ((p
->accept_ra_types
== RA_OPTIMAL
) ||
1419 (p
->accept_ra_types
== RA_ACCEPTED
))
1422 if (p
->core_state
!= FS_FEEDING
)
1423 return 1; /* In the meantime, the protocol fell down. */
1424 do_feed_baby(p
, p
->accept_ra_types
, h
, n
, e
);
1428 if (p
->accept_ra_types
== RA_ANY
)
1429 for(e
= n
->routes
; e
!= NULL
; e
= e
->next
)
1431 if (p
->core_state
!= FS_FEEDING
)
1432 return 1; /* In the meantime, the protocol fell down. */
1433 do_feed_baby(p
, RA_ANY
, h
, n
, e
);
1437 FIB_ITERATE_END(fn
);
1438 p
->feed_ahook
= h
->next
;
1441 mb_free(p
->feed_iterator
);
1442 p
->feed_iterator
= NULL
;
1448 FIB_ITERATE_INIT(fit
, &h
->table
->fib
);
1453 * rt_feed_baby_abort - abort protocol feeding
1456 * This function is called by the protocol code when the protocol
1457 * stops or ceases to exist before the last iteration of rt_feed_baby()
1461 rt_feed_baby_abort(struct proto
*p
)
1465 /* Unlink the iterator and exit */
1466 fit_get(&p
->feed_ahook
->table
->fib
, p
->feed_iterator
);
1467 p
->feed_ahook
= NULL
;
1472 static inline unsigned
1475 uintptr_t p
= (uintptr_t) ptr
;
1476 return p
^ (p
<< 8) ^ (p
>> 16);
1479 static inline unsigned
1480 hc_hash(ip_addr a
, rtable
*dep
)
1482 return (ipa_hash(a
) ^ ptr_hash(dep
)) & 0xffff;
1486 hc_insert(struct hostcache
*hc
, struct hostentry
*he
)
1488 unsigned int k
= he
->hash_key
>> hc
->hash_shift
;
1489 he
->next
= hc
->hash_table
[k
];
1490 hc
->hash_table
[k
] = he
;
1494 hc_remove(struct hostcache
*hc
, struct hostentry
*he
)
1496 struct hostentry
**hep
;
1497 unsigned int k
= he
->hash_key
>> hc
->hash_shift
;
1499 for (hep
= &hc
->hash_table
[k
]; *hep
!= he
; hep
= &(*hep
)->next
);
1503 #define HC_DEF_ORDER 10
1504 #define HC_HI_MARK *4
1505 #define HC_HI_STEP 2
1506 #define HC_HI_ORDER 16 /* Must be at most 16 */
1507 #define HC_LO_MARK /5
1508 #define HC_LO_STEP 2
1509 #define HC_LO_ORDER 10
1512 hc_alloc_table(struct hostcache
*hc
, unsigned order
)
1514 unsigned hsize
= 1 << order
;
1515 hc
->hash_order
= order
;
1516 hc
->hash_shift
= 16 - order
;
1517 hc
->hash_max
= (order
>= HC_HI_ORDER
) ? ~0 : (hsize HC_HI_MARK
);
1518 hc
->hash_min
= (order
<= HC_LO_ORDER
) ? 0 : (hsize HC_LO_MARK
);
1520 hc
->hash_table
= mb_allocz(rt_table_pool
, hsize
* sizeof(struct hostentry
*));
1524 hc_resize(struct hostcache
*hc
, unsigned new_order
)
1526 unsigned old_size
= 1 << hc
->hash_order
;
1527 struct hostentry
**old_table
= hc
->hash_table
;
1528 struct hostentry
*he
, *hen
;
1531 hc_alloc_table(hc
, new_order
);
1532 for (i
= 0; i
< old_size
; i
++)
1533 for (he
= old_table
[i
]; he
!= NULL
; he
=hen
)
1541 static struct hostentry
*
1542 hc_new_hostentry(struct hostcache
*hc
, ip_addr a
, ip_addr ll
, rtable
*dep
, unsigned k
)
1544 struct hostentry
*he
= sl_alloc(hc
->slab
);
1553 add_tail(&hc
->hostentries
, &he
->ln
);
1557 if (hc
->hash_items
> hc
->hash_max
)
1558 hc_resize(hc
, hc
->hash_order
+ HC_HI_STEP
);
1564 hc_delete_hostentry(struct hostcache
*hc
, struct hostentry
*he
)
1570 sl_free(hc
->slab
, he
);
1573 if (hc
->hash_items
< hc
->hash_min
)
1574 hc_resize(hc
, hc
->hash_order
- HC_LO_STEP
);
1578 rt_init_hostcache(rtable
*tab
)
1580 struct hostcache
*hc
= mb_allocz(rt_table_pool
, sizeof(struct hostcache
));
1581 init_list(&hc
->hostentries
);
1584 hc_alloc_table(hc
, HC_DEF_ORDER
);
1585 hc
->slab
= sl_new(rt_table_pool
, sizeof(struct hostentry
));
1587 hc
->lp
= lp_new(rt_table_pool
, 1008);
1588 hc
->trie
= f_new_trie(hc
->lp
);
1590 tab
->hostcache
= hc
;
1594 rt_free_hostcache(rtable
*tab
)
1596 struct hostcache
*hc
= tab
->hostcache
;
1599 WALK_LIST(n
, hc
->hostentries
)
1601 struct hostentry
*he
= SKIP_BACK(struct hostentry
, ln
, n
);
1605 log(L_ERR
"Hostcache is not empty in table %s", tab
->name
);
1610 mb_free(hc
->hash_table
);
1615 rt_notify_hostcache(rtable
*tab
, net
*net
)
1617 struct hostcache
*hc
= tab
->hostcache
;
1619 if (tab
->hcu_scheduled
)
1622 if (trie_match_prefix(hc
->trie
, net
->n
.prefix
, net
->n
.pxlen
))
1623 rt_schedule_hcu(tab
);
1627 if_local_addr(ip_addr a
, struct iface
*i
)
1631 WALK_LIST(b
, i
->addrs
)
1632 if (ipa_equal(a
, b
->ip
))
1639 rt_get_igp_metric(rte
*rt
)
1641 eattr
*ea
= ea_find(rt
->attrs
->eattrs
, EA_GEN_IGP_METRIC
);
1649 if ((a
->source
== RTS_OSPF
) ||
1650 (a
->source
== RTS_OSPF_IA
) ||
1651 (a
->source
== RTS_OSPF_EXT1
))
1652 return rt
->u
.ospf
.metric1
;
1656 if (a
->source
== RTS_RIP
)
1657 return rt
->u
.rip
.metric
;
1661 if ((a
->dest
!= RTD_ROUTER
) && (a
->dest
!= RTD_MULTIPATH
))
1664 return IGP_METRIC_UNKNOWN
;
1668 rt_update_hostentry(rtable
*tab
, struct hostentry
*he
)
1670 rta
*old_src
= he
->src
;
1673 /* Reset the hostentry */
1676 he
->dest
= RTD_UNREACHABLE
;
1679 net
*n
= net_route(tab
, he
->addr
, MAX_PREFIX_LENGTH
);
1682 rta
*a
= n
->routes
->attrs
;
1687 /* Recursive route should not depend on another recursive route */
1688 log(L_WARN
"Next hop address %I resolvable through recursive route for %I/%d",
1689 he
->addr
, n
->n
.prefix
, pxlen
);
1693 if (a
->dest
== RTD_DEVICE
)
1695 if (if_local_addr(he
->addr
, a
->iface
))
1697 /* The host address is a local address, this is not valid */
1698 log(L_WARN
"Next hop address %I is a local address of iface %s",
1699 he
->addr
, a
->iface
->name
);
1703 /* The host is directly reachable, use link as a gateway */
1705 he
->dest
= RTD_ROUTER
;
1709 /* The host is reachable through some route entry */
1714 he
->src
= rta_clone(a
);
1715 he
->igp_metric
= rt_get_igp_metric(n
->routes
);
1719 /* Add a prefix range to the trie */
1720 trie_add_prefix(tab
->hostcache
->trie
, he
->addr
, MAX_PREFIX_LENGTH
, pxlen
, MAX_PREFIX_LENGTH
);
1723 return old_src
!= he
->src
;
1727 rt_update_hostcache(rtable
*tab
)
1729 struct hostcache
*hc
= tab
->hostcache
;
1730 struct hostentry
*he
;
1733 /* Reset the trie */
1735 hc
->trie
= f_new_trie(hc
->lp
);
1737 WALK_LIST_DELSAFE(n
, x
, hc
->hostentries
)
1739 he
= SKIP_BACK(struct hostentry
, ln
, n
);
1742 hc_delete_hostentry(hc
, he
);
1746 if (rt_update_hostentry(tab
, he
))
1747 rt_schedule_nhu(he
->tab
);
1750 tab
->hcu_scheduled
= 0;
1753 static struct hostentry
*
1754 rt_find_hostentry(rtable
*tab
, ip_addr a
, ip_addr ll
, rtable
*dep
)
1756 struct hostentry
*he
;
1758 if (!tab
->hostcache
)
1759 rt_init_hostcache(tab
);
1761 unsigned int k
= hc_hash(a
, dep
);
1762 struct hostcache
*hc
= tab
->hostcache
;
1763 for (he
= hc
->hash_table
[k
>> hc
->hash_shift
]; he
!= NULL
; he
= he
->next
)
1764 if (ipa_equal(he
->addr
, a
) && (he
->tab
== dep
))
1767 he
= hc_new_hostentry(hc
, a
, ll
, dep
, k
);
1768 rt_update_hostentry(tab
, he
);
1773 rta_set_recursive_next_hop(rtable
*dep
, rta
*a
, rtable
*tab
, ip_addr
*gw
, ip_addr
*ll
)
1775 rta_apply_hostentry(a
, rt_find_hostentry(tab
, *gw
, *ll
, dep
));
1783 rt_format_via(rte
*e
, byte
*via
)
1789 case RTD_ROUTER
: bsprintf(via
, "via %I on %s", a
->gw
, a
->iface
->name
); break;
1790 case RTD_DEVICE
: bsprintf(via
, "dev %s", a
->iface
->name
); break;
1791 case RTD_BLACKHOLE
: bsprintf(via
, "blackhole"); break;
1792 case RTD_UNREACHABLE
: bsprintf(via
, "unreachable"); break;
1793 case RTD_PROHIBIT
: bsprintf(via
, "prohibited"); break;
1794 case RTD_MULTIPATH
: bsprintf(via
, "multipath"); break;
1795 default: bsprintf(via
, "???");
1800 rt_show_rte(struct cli
*c
, byte
*ia
, rte
*e
, struct rt_show_data
*d
, ea_list
*tmpa
)
1802 byte via
[STD_ADDRESS_P_LENGTH
+32], from
[STD_ADDRESS_P_LENGTH
+8];
1803 byte tm
[TM_DATETIME_BUFFER_SIZE
], info
[256];
1805 int primary
= (e
->net
->routes
== e
);
1806 int sync_error
= (e
->net
->n
.flags
& KRF_SYNC_ERROR
);
1809 rt_format_via(e
, via
);
1810 tm_format_datetime(tm
, &config
->tf_route
, e
->lastmod
);
1811 if (ipa_nonzero(a
->from
) && !ipa_equal(a
->from
, a
->gw
))
1812 bsprintf(from
, " from %I", a
->from
);
1815 if (a
->proto
->proto
->get_route_info
|| d
->verbose
)
1817 /* Need to normalize the extended attributes */
1819 t
= ea_append(t
, a
->eattrs
);
1820 tmpa
= alloca(ea_scan(t
));
1824 if (a
->proto
->proto
->get_route_info
)
1825 a
->proto
->proto
->get_route_info(e
, info
, tmpa
);
1827 bsprintf(info
, " (%d)", e
->pref
);
1828 cli_printf(c
, -1007, "%-18s %s [%s %s%s]%s%s", ia
, via
, a
->proto
->name
,
1829 tm
, from
, primary
? (sync_error
? " !" : " *") : "", info
);
1830 for (nh
= a
->nexthops
; nh
; nh
= nh
->next
)
1831 cli_printf(c
, -1007, "\tvia %I on %s weight %d", nh
->gw
, nh
->iface
->name
, nh
->weight
+ 1);
1833 rta_show(c
, a
, tmpa
);
1837 rt_show_net(struct cli
*c
, net
*n
, struct rt_show_data
*d
)
1840 byte ia
[STD_ADDRESS_P_LENGTH
+8];
1841 struct announce_hook
*a
;
1844 bsprintf(ia
, "%I/%d", n
->n
.prefix
, n
->n
.pxlen
);
1847 for(e
=n
->routes
; e
; e
=e
->next
)
1849 struct ea_list
*tmpa
, *old_tmpa
;
1850 struct proto
*p0
= e
->attrs
->proto
;
1851 struct proto
*p1
= d
->export_protocol
;
1852 struct proto
*p2
= d
->show_protocol
;
1855 rte_update_lock(); /* We use the update buffer for filtering */
1856 old_tmpa
= tmpa
= p0
->make_tmp_attrs
? p0
->make_tmp_attrs(e
, rte_update_pool
) : NULL
;
1857 ok
= (d
->filter
== FILTER_ACCEPT
|| f_run(d
->filter
, &e
, &tmpa
, rte_update_pool
, FF_FORCE_TMPATTR
) <= F_ACCEPT
);
1858 if (p2
&& p2
!= p0
) ok
= 0;
1859 if (ok
&& d
->export_mode
)
1862 if ((ic
= p1
->import_control
? p1
->import_control(p1
, &e
, &tmpa
, rte_update_pool
) : 0) < 0)
1864 else if (!ic
&& d
->export_mode
> 1)
1866 /* FIXME - this shows what should be exported according
1867 to current filters, but not what was really exported.
1868 'configure soft' command may change the export filter
1869 and do not update routes */
1871 if ((a
= proto_find_announce_hook(p1
, d
->table
)) && ((a
->out_filter
== FILTER_REJECT
) ||
1872 (a
->out_filter
&& f_run(a
->out_filter
, &e
, &tmpa
, rte_update_pool
, FF_FORCE_TMPATTR
) > F_ACCEPT
)))
1880 rt_show_rte(c
, ia
, e
, d
, tmpa
);
1888 rte_update_unlock();
1889 if (d
->primary_only
)
1895 rt_show_cont(struct cli
*c
)
1897 struct rt_show_data
*d
= c
->rover
;
1903 struct fib
*fib
= &d
->table
->fib
;
1904 struct fib_iterator
*it
= &d
->fit
;
1906 FIB_ITERATE_START(fib
, it
, f
)
1909 if (d
->running_on_config
&& d
->running_on_config
!= config
)
1911 cli_printf(c
, 8004, "Stopped due to reconfiguration");
1914 if (d
->export_protocol
&&
1915 d
->export_protocol
->core_state
!= FS_HAPPY
&&
1916 d
->export_protocol
->core_state
!= FS_FEEDING
)
1918 cli_printf(c
, 8005, "Protocol is down");
1923 FIB_ITERATE_PUT(it
, f
);
1926 rt_show_net(c
, n
, d
);
1930 cli_printf(c
, 14, "%d of %d routes for %d networks", d
->show_counter
, d
->rt_counter
, d
->net_counter
);
1932 cli_printf(c
, 0, "");
1934 c
->cont
= c
->cleanup
= NULL
;
1938 rt_show_cleanup(struct cli
*c
)
1940 struct rt_show_data
*d
= c
->rover
;
1942 /* Unlink the iterator */
1943 fit_get(&d
->table
->fib
, &d
->fit
);
1947 rt_show(struct rt_show_data
*d
)
1951 if (d
->pxlen
== 256)
1953 FIB_ITERATE_INIT(&d
->fit
, &d
->table
->fib
);
1954 this_cli
->cont
= rt_show_cont
;
1955 this_cli
->cleanup
= rt_show_cleanup
;
1956 this_cli
->rover
= d
;
1961 n
= net_route(d
->table
, d
->prefix
, d
->pxlen
);
1963 n
= net_find(d
->table
, d
->prefix
, d
->pxlen
);
1966 rt_show_net(this_cli
, n
, d
);
1970 cli_msg(8001, "Network not in table");
1975 * Documentation for functions declared inline in route.h
1980 * net_find - find a network entry
1981 * @tab: a routing table
1982 * @addr: address of the network
1983 * @len: length of the network prefix
1985 * net_find() looks up the given network in routing table @tab and
1986 * returns a pointer to its &net entry or %NULL if no such network
1989 static inline net
*net_find(rtable
*tab
, ip_addr addr
, unsigned len
)
1993 * net_get - obtain a network entry
1994 * @tab: a routing table
1995 * @addr: address of the network
1996 * @len: length of the network prefix
1998 * net_get() looks up the given network in routing table @tab and
1999 * returns a pointer to its &net entry. If no such entry exists, it's
2002 static inline net
*net_get(rtable
*tab
, ip_addr addr
, unsigned len
)
2006 * rte_cow - copy a route for writing
2007 * @r: a route entry to be copied
2009 * rte_cow() takes a &rte and prepares it for modification. The exact action
2010 * taken depends on the flags of the &rte -- if it's a temporary entry, it's
2011 * just returned unchanged, else a new temporary entry with the same contents
2014 * The primary use of this function is inside the filter machinery -- when
2015 * a filter wants to modify &rte contents (to change the preference or to
2016 * attach another set of attributes), it must ensure that the &rte is not
2017 * shared with anyone else (and especially that it isn't stored in any routing
2020 * Result: a pointer to the new writable &rte.
2022 static inline rte
* rte_cow(rte
*r
)