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].
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.
38 * The code uses OS-dependent parts for kernel updates and scans. These parts are
39 * in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_*
40 * and kif_sys_* (and some others like krt_replace_rte()) and krt-sys.h header file.
41 * This is also used for platform specific protocol options and route attributes.
43 * There was also an old code that used traditional UNIX ioctls for these tasks.
44 * It was unmaintained and later removed. For reference, see sysdep/krt-* files
45 * in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6
49 * If you are brave enough, continue now. You cannot say you haven't been warned.
54 #include "nest/bird.h"
55 #include "nest/iface.h"
56 #include "nest/route.h"
57 #include "nest/protocol.h"
58 #include "filter/filter.h"
59 #include "lib/timer.h"
60 #include "conf/conf.h"
61 #include "lib/string.h"
71 static linpool
*krt_filter_lp
;
76 krt_pool
= rp_new(&root_pool
, "Kernel Syncer");
77 krt_filter_lp
= lp_new(krt_pool
, 4080);
84 static struct kif_config
*kif_cf
;
85 static struct kif_proto
*kif_proto
;
86 static timer
*kif_scan_timer
;
87 static bird_clock_t kif_last_shot
;
92 struct kif_proto
*p
= t
->data
;
94 KRT_TRACE(p
, D_EVENTS
, "Scanning interfaces");
102 if (kif_proto
&& kif_last_shot
+ 2 < now
)
104 kif_scan(kif_scan_timer
);
105 tm_start(kif_scan_timer
, ((struct kif_config
*) kif_proto
->p
.cf
)->scan_time
);
110 kif_request_scan(void)
112 if (kif_proto
&& kif_scan_timer
->expires
> now
)
113 tm_start(kif_scan_timer
, 1);
117 prefer_scope(struct ifa
*a
, struct ifa
*b
)
118 { return (a
->scope
> SCOPE_LINK
) && (b
->scope
<= SCOPE_LINK
); }
121 prefer_addr(struct ifa
*a
, struct ifa
*b
)
122 { return ipa_compare(a
->ip
, b
->ip
) < 0; }
124 static inline struct ifa
*
125 find_preferred_ifa(struct iface
*i
, ip_addr prefix
, ip_addr mask
)
127 struct ifa
*a
, *b
= NULL
;
129 WALK_LIST(a
, i
->addrs
)
131 if (!(a
->flags
& IA_SECONDARY
) &&
132 ipa_equal(ipa_and(a
->ip
, mask
), prefix
) &&
133 (!b
|| prefer_scope(a
, b
) || prefer_addr(a
, b
)))
141 kif_choose_primary(struct iface
*i
)
143 struct kif_config
*cf
= (struct kif_config
*) (kif_proto
->p
.cf
);
144 struct kif_primary_item
*it
;
147 WALK_LIST(it
, cf
->primary
)
149 if (!it
->pattern
|| patmatch(it
->pattern
, i
->name
))
150 if (a
= find_preferred_ifa(i
, it
->prefix
, ipa_mkmask(it
->pxlen
)))
154 return find_preferred_ifa(i
, IPA_NONE
, IPA_NONE
);
158 static struct proto
*
159 kif_init(struct proto_config
*c
)
161 struct kif_proto
*p
= proto_new(c
, sizeof(struct kif_proto
));
168 kif_start(struct proto
*P
)
170 struct kif_proto
*p
= (struct kif_proto
*) P
;
175 /* Start periodic interface scanning */
176 kif_scan_timer
= tm_new(P
->pool
);
177 kif_scan_timer
->hook
= kif_scan
;
178 kif_scan_timer
->data
= p
;
179 kif_scan_timer
->recurrent
= KIF_CF
->scan_time
;
180 kif_scan(kif_scan_timer
);
181 tm_start(kif_scan_timer
, KIF_CF
->scan_time
);
187 kif_shutdown(struct proto
*P
)
189 struct kif_proto
*p
= (struct kif_proto
*) P
;
191 tm_stop(kif_scan_timer
);
199 kif_reconfigure(struct proto
*p
, struct proto_config
*new)
201 struct kif_config
*o
= (struct kif_config
*) p
->cf
;
202 struct kif_config
*n
= (struct kif_config
*) new;
204 if (!kif_sys_reconfigure((struct kif_proto
*) p
, n
, o
))
207 if (o
->scan_time
!= n
->scan_time
)
209 tm_stop(kif_scan_timer
);
210 kif_scan_timer
->recurrent
= n
->scan_time
;
211 kif_scan(kif_scan_timer
);
212 tm_start(kif_scan_timer
, n
->scan_time
);
215 if (!EMPTY_LIST(o
->primary
) || !EMPTY_LIST(n
->primary
))
217 /* This is hack, we have to update a configuration
218 * to the new value just now, because it is used
219 * for recalculation of primary addresses.
223 ifa_recalc_all_primary_addresses();
231 kif_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
234 kif_sys_preconfig(c
);
237 struct proto_config
*
238 kif_init_config(int class)
241 cf_error("Kernel device protocol already defined");
243 kif_cf
= (struct kif_config
*) proto_config_new(&proto_unix_iface
, sizeof(struct kif_config
), class);
244 kif_cf
->scan_time
= 60;
245 init_list(&kif_cf
->primary
);
247 kif_sys_init_config(kif_cf
);
248 return (struct proto_config
*) kif_cf
;
252 kif_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
254 struct kif_config
*d
= (struct kif_config
*) dest
;
255 struct kif_config
*s
= (struct kif_config
*) src
;
257 /* Shallow copy of everything (just scan_time currently) */
258 proto_copy_rest(dest
, src
, sizeof(struct kif_config
));
260 /* Copy primary addr list */
261 cfg_copy_list(&d
->primary
, &s
->primary
, sizeof(struct kif_primary_item
));
263 /* Fix sysdep parts */
264 kif_sys_copy_config(d
, s
);
268 struct protocol proto_unix_iface
= {
270 template: "device%d",
271 preference
: DEF_PREF_DIRECT
,
272 preconfig
: kif_preconfig
,
275 shutdown
: kif_shutdown
,
276 reconfigure
: kif_reconfigure
,
277 copy_config
: kif_copy_config
285 krt_trace_in(struct krt_proto
*p
, rte
*e
, char *msg
)
287 if (p
->p
.debug
& D_PACKETS
)
288 log(L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
292 krt_trace_in_rl(struct rate_limit
*rl
, struct krt_proto
*p
, rte
*e
, char *msg
)
294 if (p
->p
.debug
& D_PACKETS
)
295 log_rl(rl
, L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
302 #ifdef KRT_ALLOW_LEARN
304 static struct rate_limit rl_alien_seen
, rl_alien_updated
, rl_alien_created
, rl_alien_ignored
;
307 * krt_same_key() specifies what (aside from the net) is the key in
308 * kernel routing tables. It should be OS-dependent, this is for
309 * Linux. It is important for asynchronous alien updates, because a
310 * positive update is implicitly a negative one for any old route with
315 krt_same_key(rte
*a
, rte
*b
)
317 return a
->u
.krt
.metric
== b
->u
.krt
.metric
;
321 krt_uptodate(rte
*a
, rte
*b
)
323 if (a
->attrs
!= b
->attrs
)
326 if (a
->u
.krt
.proto
!= b
->u
.krt
.proto
)
333 krt_learn_announce_update(struct krt_proto
*p
, rte
*e
)
336 rta
*aa
= rta_clone(e
->attrs
);
337 rte
*ee
= rte_get_temp(aa
);
338 net
*nn
= net_get(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
341 ee
->pref
= p
->p
.preference
;
342 ee
->u
.krt
= e
->u
.krt
;
343 rte_update(p
->p
.table
, nn
, &p
->p
, &p
->p
, ee
);
347 krt_learn_announce_delete(struct krt_proto
*p
, net
*n
)
349 n
= net_find(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
351 rte_update(p
->p
.table
, n
, &p
->p
, &p
->p
, NULL
);
354 /* Called when alien route is discovered during scan */
356 krt_learn_scan(struct krt_proto
*p
, rte
*e
)
359 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
362 e
->attrs
= rta_lookup(e
->attrs
);
364 for(mm
=&n
->routes
; m
= *mm
; mm
=&m
->next
)
365 if (krt_same_key(m
, e
))
369 if (krt_uptodate(m
, e
))
371 krt_trace_in_rl(&rl_alien_seen
, p
, e
, "[alien] seen");
377 krt_trace_in_rl(&rl_alien_updated
, p
, e
, "[alien] updated");
384 krt_trace_in_rl(&rl_alien_created
, p
, e
, "[alien] created");
394 krt_learn_prune(struct krt_proto
*p
)
396 struct fib
*fib
= &p
->krt_table
.fib
;
397 struct fib_iterator fit
;
399 KRT_TRACE(p
, D_EVENTS
, "Pruning inherited routes");
401 FIB_ITERATE_INIT(&fit
, fib
);
403 FIB_ITERATE_START(fib
, &fit
, f
)
406 rte
*e
, **ee
, *best
, **pbest
, *old_best
;
408 old_best
= n
->routes
;
420 if (!best
|| best
->u
.krt
.metric
> e
->u
.krt
.metric
)
430 DBG("%I/%d: deleting\n", n
->n
.prefix
, n
->n
.pxlen
);
433 krt_learn_announce_delete(p
, n
);
434 n
->n
.flags
&= ~KRF_INSTALLED
;
436 FIB_ITERATE_PUT(&fit
, f
);
441 best
->next
= n
->routes
;
443 if (best
!= old_best
|| !(n
->n
.flags
& KRF_INSTALLED
))
445 DBG("%I/%d: announcing (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
446 krt_learn_announce_update(p
, best
);
447 n
->n
.flags
|= KRF_INSTALLED
;
450 DBG("%I/%d: uptodate (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
456 krt_learn_async(struct krt_proto
*p
, rte
*e
, int new)
459 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
460 rte
*g
, **gg
, *best
, **bestp
, *old_best
;
462 e
->attrs
= rta_lookup(e
->attrs
);
464 old_best
= n
->routes
;
465 for(gg
=&n
->routes
; g
= *gg
; gg
= &g
->next
)
466 if (krt_same_key(g
, e
))
472 if (krt_uptodate(g
, e
))
474 krt_trace_in(p
, e
, "[alien async] same");
478 krt_trace_in(p
, e
, "[alien async] updated");
483 krt_trace_in(p
, e
, "[alien async] created");
490 krt_trace_in(p
, e
, "[alien async] delete failed");
496 krt_trace_in(p
, e
, "[alien async] removed");
503 for(gg
=&n
->routes
; g
=*gg
; gg
=&g
->next
)
504 if (best
->u
.krt
.metric
> g
->u
.krt
.metric
)
512 best
->next
= n
->routes
;
515 if (best
!= old_best
)
517 DBG("krt_learn_async: distributing change\n");
520 krt_learn_announce_update(p
, best
);
521 n
->n
.flags
|= KRF_INSTALLED
;
526 krt_learn_announce_delete(p
, n
);
527 n
->n
.flags
&= ~KRF_INSTALLED
;
533 krt_learn_init(struct krt_proto
*p
)
536 rt_setup(p
->p
.pool
, &p
->krt_table
, "Inherited", NULL
);
540 krt_dump(struct proto
*P
)
542 struct krt_proto
*p
= (struct krt_proto
*) P
;
546 debug("KRT: Table of inheritable routes\n");
547 rt_dump(&p
->krt_table
);
551 krt_dump_attrs(rte
*e
)
553 debug(" [m=%d,p=%d,t=%d]", e
->u
.krt
.metric
, e
->u
.krt
.proto
, e
->u
.krt
.type
);
562 #ifdef CONFIG_ALL_TABLES_AT_ONCE
563 static timer
*krt_scan_timer
;
564 static int krt_instance_count
;
565 static list krt_instance_list
;
569 krt_flush_routes(struct krt_proto
*p
)
571 struct rtable
*t
= p
->p
.table
;
573 KRT_TRACE(p
, D_EVENTS
, "Flushing kernel routes");
581 if ((n
->n
.flags
& KRF_INSTALLED
) &&
582 a
->source
!= RTS_DEVICE
&& a
->source
!= RTS_INHERIT
)
584 /* FIXME: this does not work if gw is changed in export filter */
585 krt_replace_rte(p
, e
->net
, NULL
, e
, NULL
);
586 n
->n
.flags
&= ~KRF_INSTALLED
;
594 krt_same_dest(rte
*k
, rte
*e
)
596 rta
*ka
= k
->attrs
, *ea
= e
->attrs
;
598 if (ka
->dest
!= ea
->dest
)
603 return ipa_equal(ka
->gw
, ea
->gw
);
605 return !strcmp(ka
->iface
->name
, ea
->iface
->name
);
607 return mpnh_same(ka
->nexthops
, ea
->nexthops
);
614 * This gets called back when the low-level scanning code discovers a route.
615 * We expect that the route is a temporary rte and its attributes are uncached.
619 krt_got_route(struct krt_proto
*p
, rte
*e
)
625 #ifdef KRT_ALLOW_LEARN
626 switch (e
->u
.krt
.src
)
629 verdict
= KRF_IGNORE
;
632 case KRT_SRC_REDIRECT
:
633 verdict
= KRF_DELETE
;
638 krt_learn_scan(p
, e
);
641 krt_trace_in_rl(&rl_alien_ignored
, p
, e
, "[alien] ignored");
647 /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
649 if (net
->n
.flags
& KRF_VERDICT_MASK
)
651 /* Route to this destination was already seen. Strange, but it happens... */
652 krt_trace_in(p
, e
, "already seen");
658 if ((net
->n
.flags
& KRF_INSTALLED
) && old
)
660 /* There may be changes in route attributes, we ignore that.
661 Also, this does not work well if gw is changed in export filter */
662 if ((net
->n
.flags
& KRF_SYNC_ERROR
) || ! krt_same_dest(e
, old
))
663 verdict
= KRF_UPDATE
;
668 verdict
= KRF_DELETE
;
671 krt_trace_in(p
, e
, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict
]);
672 net
->n
.flags
= (net
->n
.flags
& ~KRF_VERDICT_MASK
) | verdict
;
673 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
675 /* Get a cached copy of attributes and temporarily link the route */
677 a
->source
= RTS_DUMMY
;
678 e
->attrs
= rta_lookup(a
);
679 e
->next
= net
->routes
;
687 krt_export_rte(struct krt_proto
*p
, rte
**new, ea_list
**tmpa
)
689 struct filter
*filter
= p
->p
.main_ahook
->out_filter
;
694 if (filter
== FILTER_REJECT
)
697 if (filter
== FILTER_ACCEPT
)
700 struct proto
*src
= (*new)->attrs
->proto
;
701 *tmpa
= src
->make_tmp_attrs
? src
->make_tmp_attrs(*new, krt_filter_lp
) : NULL
;
702 return f_run(filter
, new, tmpa
, krt_filter_lp
, FF_FORCE_TMPATTR
) <= F_ACCEPT
;
706 krt_prune(struct krt_proto
*p
)
708 struct rtable
*t
= p
->p
.table
;
710 KRT_TRACE(p
, D_EVENTS
, "Pruning table %s", t
->name
);
714 int verdict
= f
->flags
& KRF_VERDICT_MASK
;
715 rte
*new, *new0
, *old
;
716 ea_list
*tmpa
= NULL
;
718 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
720 /* Get a dummy route from krt_got_route() */
722 n
->routes
= old
->next
;
727 new = new0
= n
->routes
;
728 if (verdict
== KRF_CREATE
|| verdict
== KRF_UPDATE
)
730 /* We have to run export filter to get proper 'new' route */
731 if (! krt_export_rte(p
, &new, &tmpa
))
733 /* Route rejected, should not happen (KRF_INSTALLED) but to be sure .. */
734 verdict
= (verdict
== KRF_CREATE
) ? KRF_IGNORE
: KRF_DELETE
;
741 if (new && (f
->flags
& KRF_INSTALLED
))
743 krt_trace_in(p
, new, "reinstalling");
744 krt_replace_rte(p
, n
, new, NULL
, tmpa
);
749 /* Nothing happens */
752 krt_trace_in(p
, new, "updating");
753 krt_replace_rte(p
, n
, new, old
, tmpa
);
756 krt_trace_in(p
, old
, "deleting");
757 krt_replace_rte(p
, n
, NULL
, old
, NULL
);
760 bug("krt_prune: invalid route status");
767 lp_flush(krt_filter_lp
);
768 f
->flags
&= ~KRF_VERDICT_MASK
;
772 #ifdef KRT_ALLOW_LEARN
780 krt_got_route_async(struct krt_proto
*p
, rte
*e
, int new)
784 switch (e
->u
.krt
.src
)
787 ASSERT(0); /* Should be filtered by the back end */
789 case KRT_SRC_REDIRECT
:
792 krt_trace_in(p
, e
, "[redirect] deleting");
793 krt_replace_rte(p
, net
, NULL
, e
, NULL
);
795 /* If !new, it is probably echo of our deletion */
798 #ifdef KRT_ALLOW_LEARN
802 krt_learn_async(p
, e
, new);
815 krt_scan(timer
*t UNUSED
)
820 #ifdef CONFIG_ALL_TABLES_AT_ONCE
823 /* We need some node to decide whether to print the debug messages or not */
824 p
= SKIP_BACK(struct krt_proto
, instance_node
, HEAD(krt_instance_list
));
825 if (p
->instance_node
.next
)
826 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
828 WALK_LIST(q
, krt_instance_list
)
830 p
= SKIP_BACK(struct krt_proto
, instance_node
, q
);
836 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
847 static struct ea_list
*
848 krt_make_tmp_attrs(rte
*rt
, struct linpool
*pool
)
850 struct ea_list
*l
= lp_alloc(pool
, sizeof(struct ea_list
) + 2 * sizeof(eattr
));
853 l
->flags
= EALF_SORTED
;
856 l
->attrs
[0].id
= EA_KRT_SOURCE
;
857 l
->attrs
[0].flags
= 0;
858 l
->attrs
[0].type
= EAF_TYPE_INT
| EAF_TEMP
;
859 l
->attrs
[0].u
.data
= rt
->u
.krt
.proto
;
861 l
->attrs
[1].id
= EA_KRT_METRIC
;
862 l
->attrs
[1].flags
= 0;
863 l
->attrs
[1].type
= EAF_TYPE_INT
| EAF_TEMP
;
864 l
->attrs
[1].u
.data
= rt
->u
.krt
.metric
;
870 krt_store_tmp_attrs(rte
*rt
, struct ea_list
*attrs
)
872 /* EA_KRT_SOURCE is read-only */
873 rt
->u
.krt
.metric
= ea_get_int(attrs
, EA_KRT_METRIC
, 0);
877 krt_import_control(struct proto
*P
, rte
**new, ea_list
**attrs
, struct linpool
*pool
)
879 struct krt_proto
*p
= (struct krt_proto
*) P
;
882 if (e
->attrs
->proto
== P
)
885 if (!KRT_CF
->devroutes
&&
886 (e
->attrs
->dest
== RTD_DEVICE
) &&
887 (e
->attrs
->source
!= RTS_STATIC_DEVICE
))
897 krt_notify(struct proto
*P
, struct rtable
*table UNUSED
, net
*net
,
898 rte
*new, rte
*old
, struct ea_list
*eattrs
)
900 struct krt_proto
*p
= (struct krt_proto
*) P
;
904 if (!(net
->n
.flags
& KRF_INSTALLED
))
907 net
->n
.flags
|= KRF_INSTALLED
;
909 net
->n
.flags
&= ~KRF_INSTALLED
;
910 if (p
->initialized
) /* Before first scan we don't touch the routes */
911 krt_replace_rte(p
, net
, new, old
, eattrs
);
915 krt_rte_same(rte
*a
, rte
*b
)
917 /* src is always KRT_SRC_ALIEN and type is irrelevant */
918 return (a
->u
.krt
.proto
== b
->u
.krt
.proto
) && (a
->u
.krt
.metric
== b
->u
.krt
.metric
);
926 struct krt_config
*krt_cf
;
928 static struct proto
*
929 krt_init(struct proto_config
*c
)
931 struct krt_proto
*p
= proto_new(c
, sizeof(struct krt_proto
));
933 p
->p
.accept_ra_types
= RA_OPTIMAL
;
934 p
->p
.make_tmp_attrs
= krt_make_tmp_attrs
;
935 p
->p
.store_tmp_attrs
= krt_store_tmp_attrs
;
936 p
->p
.import_control
= krt_import_control
;
937 p
->p
.rt_notify
= krt_notify
;
938 p
->p
.rte_same
= krt_rte_same
;
945 krt_start_timer(struct krt_proto
*p
)
949 t
= tm_new(p
->krt_pool
);
952 t
->recurrent
= KRT_CF
->scan_time
;
958 krt_start(struct proto
*P
)
960 struct krt_proto
*p
= (struct krt_proto
*) P
;
963 #ifdef CONFIG_ALL_TABLES_AT_ONCE
964 if (!krt_instance_count
++)
965 init_list(&krt_instance_list
);
968 p
->krt_pool
= krt_pool
;
969 add_tail(&krt_instance_list
, &p
->instance_node
);
971 p
->krt_pool
= P
->pool
;
974 #ifdef KRT_ALLOW_LEARN
978 krt_sys_start(p
, first
);
980 /* Start periodic routing table scanning */
981 #ifdef CONFIG_ALL_TABLES_AT_ONCE
983 krt_scan_timer
= krt_start_timer(p
);
985 tm_start(krt_scan_timer
, 0);
986 p
->scan_timer
= krt_scan_timer
;
988 p
->scan_timer
= krt_start_timer(p
);
995 krt_shutdown(struct proto
*P
)
997 struct krt_proto
*p
= (struct krt_proto
*) P
;
1000 #ifdef CONFIG_ALL_TABLES_AT_ONCE
1001 rem_node(&p
->instance_node
);
1002 if (--krt_instance_count
)
1006 tm_stop(p
->scan_timer
);
1008 /* FIXME we should flush routes even when persist during reconfiguration */
1009 if (p
->initialized
&& !KRT_CF
->persist
)
1010 krt_flush_routes(p
);
1012 krt_sys_shutdown(p
, last
);
1014 #ifdef CONFIG_ALL_TABLES_AT_ONCE
1016 rfree(krt_scan_timer
);
1023 krt_reconfigure(struct proto
*p
, struct proto_config
*new)
1025 struct krt_config
*o
= (struct krt_config
*) p
->cf
;
1026 struct krt_config
*n
= (struct krt_config
*) new;
1028 if (!krt_sys_reconfigure((struct krt_proto
*) p
, n
, o
))
1031 /* persist needn't be the same */
1032 return o
->scan_time
== n
->scan_time
&& o
->learn
== n
->learn
&& o
->devroutes
== n
->devroutes
;
1036 krt_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
1039 krt_sys_preconfig(c
);
1043 krt_postconfig(struct proto_config
*C
)
1045 struct krt_config
*c
= (struct krt_config
*) C
;
1047 #ifdef CONFIG_ALL_TABLES_AT_ONCE
1048 if (krt_cf
->scan_time
!= c
->scan_time
)
1049 cf_error("All kernel syncers must use the same table scan interval");
1052 if (C
->table
->krt_attached
)
1053 cf_error("Kernel syncer (%s) already attached to table %s", C
->table
->krt_attached
->name
, C
->table
->name
);
1054 C
->table
->krt_attached
= C
;
1055 krt_sys_postconfig(c
);
1058 struct proto_config
*
1059 krt_init_config(int class)
1061 #ifndef CONFIG_MULTIPLE_TABLES
1063 cf_error("Kernel protocol already defined");
1066 krt_cf
= (struct krt_config
*) proto_config_new(&proto_unix_kernel
, sizeof(struct krt_config
), class);
1067 krt_cf
->scan_time
= 60;
1069 krt_sys_init_config(krt_cf
);
1070 return (struct proto_config
*) krt_cf
;
1074 krt_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
1076 struct krt_config
*d
= (struct krt_config
*) dest
;
1077 struct krt_config
*s
= (struct krt_config
*) src
;
1079 /* Shallow copy of everything */
1080 proto_copy_rest(dest
, src
, sizeof(struct krt_config
));
1082 /* Fix sysdep parts */
1083 krt_sys_copy_config(d
, s
);
1087 krt_get_attr(eattr
* a
, byte
* buf
, int buflen UNUSED
)
1092 bsprintf(buf
, "source");
1096 bsprintf(buf
, "metric");
1099 case EA_KRT_PREFSRC
:
1100 bsprintf(buf
, "prefsrc");
1104 bsprintf(buf
, "realm");
1113 struct protocol proto_unix_kernel
= {
1115 template: "kernel%d",
1116 attr_class
: EAP_KRT
,
1117 preference
: DEF_PREF_INHERITED
,
1118 preconfig
: krt_preconfig
,
1119 postconfig
: krt_postconfig
,
1122 shutdown
: krt_shutdown
,
1123 reconfigure
: krt_reconfigure
,
1124 copy_config
: krt_copy_config
,
1125 get_attr
: krt_get_attr
,
1126 #ifdef KRT_ALLOW_LEARN
1128 dump_attrs
: krt_dump_attrs
,