2 * BIRD -- UNIX Kernel Synchronization
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 * DOC: Kernel synchronization
12 * This system dependent module implements the Kernel and Device protocol,
13 * that is synchronization of interface lists and routing tables with the
16 * The whole kernel synchronization is a bit messy and touches some internals
17 * of the routing table engine, because routing table maintenance is a typical
18 * example of the proverbial compatibility between different Unices and we want
19 * to keep the overhead of our KRT business as low as possible and avoid maintaining
20 * a local routing table copy.
22 * The kernel syncer can work in three different modes (according to system config header):
23 * Either with a single routing table and single KRT protocol [traditional UNIX]
24 * or with many routing tables and separate KRT protocols for all of them
25 * or with many routing tables, but every scan including all tables, so we start
26 * separate KRT protocols which cooperate with each other [Linux 2.2].
27 * In this case, we keep only a single scan timer.
29 * We use FIB node flags in the routing table to keep track of route
30 * synchronization status. We also attach temporary &rte's to the routing table,
31 * but it cannot do any harm to the rest of BIRD since table synchronization is
34 * When starting up, we cheat by looking if there is another
35 * KRT instance to be initialized later and performing table scan
36 * only once for all the instances.
40 * If you are brave enough, continue now. You cannot say you haven't been warned.
45 #include "nest/bird.h"
46 #include "nest/iface.h"
47 #include "nest/route.h"
48 #include "nest/protocol.h"
49 #include "lib/timer.h"
50 #include "conf/conf.h"
51 #include "lib/string.h"
56 static int krt_uptodate(rte
*k
, rte
*e
);
67 krt_pool
= rp_new(&root_pool
, "Kernel Syncer");
75 struct proto_config
*cf_kif
;
77 static struct kif_proto
*kif_proto
;
78 static timer
*kif_scan_timer
;
79 static bird_clock_t kif_last_shot
;
82 kif_preconfig(struct protocol
*P UNUSED
, struct config
*c UNUSED
)
90 struct kif_proto
*p
= t
->data
;
92 KRT_TRACE(p
, D_EVENTS
, "Scanning interfaces");
100 if (kif_proto
&& kif_last_shot
+ 2 < now
)
102 kif_scan(kif_scan_timer
);
103 tm_start(kif_scan_timer
, ((struct kif_config
*) kif_proto
->p
.cf
)->scan_time
);
107 static struct proto
*
108 kif_init(struct proto_config
*c
)
110 struct kif_proto
*p
= proto_new(c
, sizeof(struct kif_proto
));
115 kif_start(struct proto
*P
)
117 struct kif_proto
*p
= (struct kif_proto
*) P
;
122 /* Start periodic interface scanning */
123 kif_scan_timer
= tm_new(P
->pool
);
124 kif_scan_timer
->hook
= kif_scan
;
125 kif_scan_timer
->data
= p
;
126 kif_scan_timer
->recurrent
= KIF_CF
->scan_time
;
127 kif_scan(kif_scan_timer
);
128 tm_start(kif_scan_timer
, KIF_CF
->scan_time
);
134 kif_shutdown(struct proto
*P
)
136 struct kif_proto
*p
= (struct kif_proto
*) P
;
138 tm_stop(kif_scan_timer
);
147 prefer_scope(struct ifa
*a
, struct ifa
*b
)
148 { return (a
->scope
> SCOPE_LINK
) && (b
->scope
<= SCOPE_LINK
); }
151 prefer_addr(struct ifa
*a
, struct ifa
*b
)
152 { return ipa_compare(a
->ip
, b
->ip
) < 0; }
154 static inline struct ifa
*
155 find_preferred_ifa(struct iface
*i
, ip_addr prefix
, ip_addr mask
)
157 struct ifa
*a
, *b
= NULL
;
159 WALK_LIST(a
, i
->addrs
)
161 if (!(a
->flags
& IA_SECONDARY
) &&
162 ipa_equal(ipa_and(a
->ip
, mask
), prefix
) &&
163 (!b
|| prefer_scope(a
, b
) || prefer_addr(a
, b
)))
171 kif_choose_primary(struct iface
*i
)
173 struct kif_config
*cf
= (struct kif_config
*) (kif_proto
->p
.cf
);
174 struct kif_primary_item
*it
;
177 WALK_LIST(it
, cf
->primary
)
179 if (!it
->pattern
|| patmatch(it
->pattern
, i
->name
))
180 if (a
= find_preferred_ifa(i
, it
->prefix
, ipa_mkmask(it
->pxlen
)))
184 return find_preferred_ifa(i
, IPA_NONE
, IPA_NONE
);
189 kif_reconfigure(struct proto
*p
, struct proto_config
*new)
191 struct kif_config
*o
= (struct kif_config
*) p
->cf
;
192 struct kif_config
*n
= (struct kif_config
*) new;
194 if (!kif_params_same(&o
->iface
, &n
->iface
))
197 if (o
->scan_time
!= n
->scan_time
)
199 tm_stop(kif_scan_timer
);
200 kif_scan_timer
->recurrent
= n
->scan_time
;
201 kif_scan(kif_scan_timer
);
202 tm_start(kif_scan_timer
, n
->scan_time
);
205 if (!EMPTY_LIST(o
->primary
) || !EMPTY_LIST(n
->primary
))
207 /* This is hack, we have to update a configuration
208 * to the new value just now, because it is used
209 * for recalculation of primary addresses.
213 ifa_recalc_all_primary_addresses();
219 struct protocol proto_unix_iface
= {
221 template: "device%d",
222 preconfig
: kif_preconfig
,
225 shutdown
: kif_shutdown
,
226 reconfigure
: kif_reconfigure
,
234 krt_trace_in(struct krt_proto
*p
, rte
*e
, char *msg
)
236 if (p
->p
.debug
& D_PACKETS
)
237 log(L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
241 krt_trace_in_rl(struct rate_limit
*rl
, struct krt_proto
*p
, rte
*e
, char *msg
)
243 if (p
->p
.debug
& D_PACKETS
)
244 log_rl(rl
, L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
251 #ifdef KRT_ALLOW_LEARN
253 static struct rate_limit rl_alien_seen
, rl_alien_updated
, rl_alien_created
, rl_alien_ignored
;
256 krt_same_key(rte
*a
, rte
*b
)
258 return a
->u
.krt
.proto
== b
->u
.krt
.proto
&&
259 a
->u
.krt
.metric
== b
->u
.krt
.metric
&&
260 a
->u
.krt
.type
== b
->u
.krt
.type
;
264 krt_learn_announce_update(struct krt_proto
*p
, rte
*e
)
267 rta
*aa
= rta_clone(e
->attrs
);
268 rte
*ee
= rte_get_temp(aa
);
269 net
*nn
= net_get(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
272 ee
->pref
= p
->p
.preference
;
273 ee
->u
.krt
= e
->u
.krt
;
274 rte_update(p
->p
.table
, nn
, &p
->p
, &p
->p
, ee
);
278 krt_learn_announce_delete(struct krt_proto
*p
, net
*n
)
280 n
= net_find(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
282 rte_update(p
->p
.table
, n
, &p
->p
, &p
->p
, NULL
);
286 krt_learn_scan(struct krt_proto
*p
, rte
*e
)
289 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
292 e
->attrs
->source
= RTS_INHERIT
;
294 for(mm
=&n
->routes
; m
= *mm
; mm
=&m
->next
)
295 if (krt_same_key(m
, e
))
299 if (krt_uptodate(m
, e
))
301 krt_trace_in_rl(&rl_alien_seen
, p
, e
, "[alien] seen");
307 krt_trace_in_rl(&rl_alien_updated
, p
, e
, "[alien] updated");
314 krt_trace_in_rl(&rl_alien_created
, p
, e
, "[alien] created");
317 e
->attrs
= rta_lookup(e
->attrs
);
325 krt_learn_prune(struct krt_proto
*p
)
327 struct fib
*fib
= &p
->krt_table
.fib
;
328 struct fib_iterator fit
;
330 KRT_TRACE(p
, D_EVENTS
, "Pruning inherited routes");
332 FIB_ITERATE_INIT(&fit
, fib
);
334 FIB_ITERATE_START(fib
, &fit
, f
)
337 rte
*e
, **ee
, *best
, **pbest
, *old_best
;
339 old_best
= n
->routes
;
351 if (!best
|| best
->u
.krt
.metric
> e
->u
.krt
.metric
)
361 DBG("%I/%d: deleting\n", n
->n
.prefix
, n
->n
.pxlen
);
364 krt_learn_announce_delete(p
, n
);
365 n
->n
.flags
&= ~KRF_INSTALLED
;
367 FIB_ITERATE_PUT(&fit
, f
);
372 best
->next
= n
->routes
;
374 if (best
!= old_best
|| !(n
->n
.flags
& KRF_INSTALLED
))
376 DBG("%I/%d: announcing (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
377 krt_learn_announce_update(p
, best
);
378 n
->n
.flags
|= KRF_INSTALLED
;
381 DBG("%I/%d: uptodate (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
387 krt_learn_async(struct krt_proto
*p
, rte
*e
, int new)
390 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
391 rte
*g
, **gg
, *best
, **bestp
, *old_best
;
393 e
->attrs
->source
= RTS_INHERIT
;
395 old_best
= n
->routes
;
396 for(gg
=&n
->routes
; g
= *gg
; gg
= &g
->next
)
397 if (krt_same_key(g
, e
))
403 if (krt_uptodate(g
, e
))
405 krt_trace_in(p
, e
, "[alien async] same");
409 krt_trace_in(p
, e
, "[alien async] updated");
414 krt_trace_in(p
, e
, "[alien async] created");
415 e
->attrs
= rta_lookup(e
->attrs
);
421 krt_trace_in(p
, e
, "[alien async] delete failed");
427 krt_trace_in(p
, e
, "[alien async] removed");
434 for(gg
=&n
->routes
; g
=*gg
; gg
=&g
->next
)
435 if (best
->u
.krt
.metric
> g
->u
.krt
.metric
)
443 best
->next
= n
->routes
;
446 if (best
!= old_best
)
448 DBG("krt_learn_async: distributing change\n");
451 krt_learn_announce_update(p
, best
);
452 n
->n
.flags
|= KRF_INSTALLED
;
457 krt_learn_announce_delete(p
, n
);
458 n
->n
.flags
&= ~KRF_INSTALLED
;
464 krt_learn_init(struct krt_proto
*p
)
467 rt_setup(p
->p
.pool
, &p
->krt_table
, "Inherited", NULL
);
471 krt_dump(struct proto
*P
)
473 struct krt_proto
*p
= (struct krt_proto
*) P
;
477 debug("KRT: Table of inheritable routes\n");
478 rt_dump(&p
->krt_table
);
482 krt_dump_attrs(rte
*e
)
484 debug(" [m=%d,p=%d,t=%d]", e
->u
.krt
.metric
, e
->u
.krt
.proto
, e
->u
.krt
.type
);
493 #ifdef CONFIG_ALL_TABLES_AT_ONCE
494 static timer
*krt_scan_timer
;
495 static int krt_instance_count
;
496 static list krt_instance_list
;
500 krt_flush_routes(struct krt_proto
*p
)
502 struct rtable
*t
= p
->p
.table
;
504 KRT_TRACE(p
, D_EVENTS
, "Flushing kernel routes");
512 if ((n
->n
.flags
& KRF_INSTALLED
) &&
513 a
->source
!= RTS_DEVICE
&& a
->source
!= RTS_INHERIT
)
515 krt_set_notify(p
, e
->net
, NULL
, e
);
516 n
->n
.flags
&= ~KRF_INSTALLED
;
524 krt_uptodate(rte
*k
, rte
*e
)
526 rta
*ka
= k
->attrs
, *ea
= e
->attrs
;
528 if (ka
->dest
!= ea
->dest
)
533 return ipa_equal(ka
->gw
, ea
->gw
);
535 return !strcmp(ka
->iface
->name
, ea
->iface
->name
);
542 * This gets called back when the low-level scanning code discovers a route.
543 * We expect that the route is a temporary rte and its attributes are uncached.
547 krt_got_route(struct krt_proto
*p
, rte
*e
)
553 #ifdef KRT_ALLOW_LEARN
554 switch (e
->u
.krt
.src
)
557 verdict
= KRF_IGNORE
;
560 case KRT_SRC_REDIRECT
:
561 verdict
= KRF_DELETE
;
566 krt_learn_scan(p
, e
);
569 krt_trace_in_rl(&rl_alien_ignored
, p
, e
, "[alien] ignored");
575 /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
577 if (net
->n
.flags
& KRF_VERDICT_MASK
)
579 /* Route to this destination was already seen. Strange, but it happens... */
580 krt_trace_in(p
, e
, "already seen");
585 if (net
->n
.flags
& KRF_INSTALLED
)
589 if (krt_uptodate(e
, old
))
592 verdict
= KRF_UPDATE
;
595 verdict
= KRF_DELETE
;
598 krt_trace_in(p
, e
, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict
]);
599 net
->n
.flags
= (net
->n
.flags
& ~KRF_VERDICT_MASK
) | verdict
;
600 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
602 /* Get a cached copy of attributes and link the route */
604 a
->source
= RTS_DUMMY
;
605 e
->attrs
= rta_lookup(a
);
606 e
->next
= net
->routes
;
614 krt_prune(struct krt_proto
*p
)
616 struct rtable
*t
= p
->p
.table
;
618 KRT_TRACE(p
, D_EVENTS
, "Pruning table %s", t
->name
);
622 int verdict
= f
->flags
& KRF_VERDICT_MASK
;
625 if (verdict
!= KRF_CREATE
&& verdict
!= KRF_SEEN
&& verdict
!= KRF_IGNORE
)
628 n
->routes
= old
->next
;
637 if (new && (f
->flags
& KRF_INSTALLED
))
639 krt_trace_in(p
, new, "reinstalling");
640 krt_set_notify(p
, n
, new, NULL
);
645 /* Nothing happens */
648 krt_trace_in(p
, new, "updating");
649 krt_set_notify(p
, n
, new, old
);
652 krt_trace_in(p
, old
, "deleting");
653 krt_set_notify(p
, n
, NULL
, old
);
656 bug("krt_prune: invalid route status");
660 f
->flags
&= ~KRF_VERDICT_MASK
;
664 #ifdef KRT_ALLOW_LEARN
672 krt_got_route_async(struct krt_proto
*p
, rte
*e
, int new)
676 switch (e
->u
.krt
.src
)
679 ASSERT(0); /* Should be filtered by the back end */
681 case KRT_SRC_REDIRECT
:
684 krt_trace_in(p
, e
, "[redirect] deleting");
685 krt_set_notify(p
, net
, NULL
, e
);
687 /* If !new, it is probably echo of our deletion */
690 #ifdef KRT_ALLOW_LEARN
694 krt_learn_async(p
, e
, new);
707 krt_scan(timer
*t UNUSED
)
712 #ifdef CONFIG_ALL_TABLES_AT_ONCE
715 /* We need some node to decide whether to print the debug messages or not */
716 p
= SKIP_BACK(struct krt_proto
, instance_node
, HEAD(krt_instance_list
));
717 if (p
->instance_node
.next
)
718 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
720 WALK_LIST(q
, krt_instance_list
)
722 p
= SKIP_BACK(struct krt_proto
, instance_node
, q
);
728 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
739 krt_notify(struct proto
*P
, struct rtable
*table UNUSED
, net
*net
,
740 rte
*new, rte
*old
, struct ea_list
*attrs UNUSED
)
742 struct krt_proto
*p
= (struct krt_proto
*) P
;
746 if (new && (!krt_capable(new) || new->attrs
->source
== RTS_INHERIT
))
748 if (!(net
->n
.flags
& KRF_INSTALLED
))
751 net
->n
.flags
|= KRF_INSTALLED
;
753 net
->n
.flags
&= ~KRF_INSTALLED
;
754 if (p
->initialized
) /* Before first scan we don't touch the routes */
755 krt_set_notify(p
, net
, new, old
);
762 struct proto_config
*cf_krt
;
765 krt_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
768 krt_scan_preconfig(c
);
772 krt_postconfig(struct proto_config
*C
)
774 struct krt_config
*c
= (struct krt_config
*) C
;
776 #ifdef CONFIG_ALL_TABLES_AT_ONCE
777 struct krt_config
*first
= (struct krt_config
*) cf_krt
;
778 if (first
->scan_time
!= c
->scan_time
)
779 cf_error("All kernel syncers must use the same table scan interval");
782 if (C
->table
->krt_attached
)
783 cf_error("Kernel syncer (%s) already attached to table %s", C
->table
->krt_attached
->name
, C
->table
->name
);
784 C
->table
->krt_attached
= C
;
785 krt_scan_postconfig(c
);
789 krt_start_timer(struct krt_proto
*p
)
793 t
= tm_new(p
->krt_pool
);
796 t
->recurrent
= KRT_CF
->scan_time
;
802 krt_start(struct proto
*P
)
804 struct krt_proto
*p
= (struct krt_proto
*) P
;
807 #ifdef CONFIG_ALL_TABLES_AT_ONCE
808 if (!krt_instance_count
++)
809 init_list(&krt_instance_list
);
812 p
->krt_pool
= krt_pool
;
813 add_tail(&krt_instance_list
, &p
->instance_node
);
815 p
->krt_pool
= P
->pool
;
818 #ifdef KRT_ALLOW_LEARN
822 krt_scan_start(p
, first
);
823 krt_set_start(p
, first
);
825 /* Start periodic routing table scanning */
826 #ifdef CONFIG_ALL_TABLES_AT_ONCE
828 krt_scan_timer
= krt_start_timer(p
);
830 tm_start(krt_scan_timer
, 0);
831 p
->scan_timer
= krt_scan_timer
;
833 p
->scan_timer
= krt_start_timer(p
);
840 krt_shutdown(struct proto
*P
)
842 struct krt_proto
*p
= (struct krt_proto
*) P
;
845 #ifdef CONFIG_ALL_TABLES_AT_ONCE
846 rem_node(&p
->instance_node
);
847 if (--krt_instance_count
)
851 tm_stop(p
->scan_timer
);
853 /* FIXME we should flush routes even when persist during reconfiguration */
854 if (p
->initialized
&& !KRT_CF
->persist
)
857 krt_set_shutdown(p
, last
);
858 krt_scan_shutdown(p
, last
);
860 #ifdef CONFIG_ALL_TABLES_AT_ONCE
862 rfree(krt_scan_timer
);
868 static struct proto
*
869 krt_init(struct proto_config
*c
)
871 struct krt_proto
*p
= proto_new(c
, sizeof(struct krt_proto
));
873 p
->p
.accept_ra_types
= RA_OPTIMAL
;
874 p
->p
.rt_notify
= krt_notify
;
879 krt_reconfigure(struct proto
*p
, struct proto_config
*new)
881 struct krt_config
*o
= (struct krt_config
*) p
->cf
;
882 struct krt_config
*n
= (struct krt_config
*) new;
884 return o
->scan_time
== n
->scan_time
885 && o
->learn
== n
->learn
/* persist needn't be the same */
886 && krt_set_params_same(&o
->set
, &n
->set
)
887 && krt_scan_params_same(&o
->scan
, &n
->scan
)
891 struct protocol proto_unix_kernel
= {
893 template: "kernel%d",
894 preconfig
: krt_preconfig
,
895 postconfig
: krt_postconfig
,
898 shutdown
: krt_shutdown
,
899 reconfigure
: krt_reconfigure
,
900 #ifdef KRT_ALLOW_LEARN
902 dump_attrs
: krt_dump_attrs
,