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 "conf/conf.h"
60 #include "lib/string.h"
61 #include "lib/timer.h"
71 static linpool
*krt_filter_lp
;
72 static list krt_proto_list
;
77 krt_pool
= rp_new(&root_pool
, "Kernel Syncer");
78 krt_filter_lp
= lp_new_default(krt_pool
);
79 init_list(&krt_proto_list
);
87 struct kif_proto
*kif_proto
;
88 static struct kif_config
*kif_cf
;
89 static timer
*kif_scan_timer
;
90 static btime kif_last_shot
;
92 static struct kif_iface_config kif_default_iface
= {};
94 struct kif_iface_config
*
95 kif_get_iface_config(struct iface
*iface
)
97 struct kif_config
*cf
= (void *) (kif_proto
->p
.cf
);
98 struct kif_iface_config
*ic
= (void *) iface_patt_find(&cf
->iface_list
, iface
, NULL
);
99 return ic
?: &kif_default_iface
;
105 struct kif_proto
*p
= t
->data
;
107 KRT_TRACE(p
, D_EVENTS
, "Scanning interfaces");
108 kif_last_shot
= current_time();
115 if (kif_proto
&& ((kif_last_shot
+ 2 S
) < current_time()))
117 kif_scan(kif_scan_timer
);
118 tm_start(kif_scan_timer
, ((struct kif_config
*) kif_proto
->p
.cf
)->scan_time
);
123 kif_request_scan(void)
125 if (kif_proto
&& (kif_scan_timer
->expires
> (current_time() + 1 S
)))
126 tm_start(kif_scan_timer
, 1 S
);
129 static struct proto
*
130 kif_init(struct proto_config
*c
)
132 struct kif_proto
*p
= proto_new(c
);
139 kif_start(struct proto
*P
)
141 struct kif_proto
*p
= (struct kif_proto
*) P
;
146 /* Start periodic interface scanning */
147 kif_scan_timer
= tm_new_init(P
->pool
, kif_scan
, p
, KIF_CF
->scan_time
, 0);
148 kif_scan(kif_scan_timer
);
149 tm_start(kif_scan_timer
, KIF_CF
->scan_time
);
155 kif_shutdown(struct proto
*P
)
157 struct kif_proto
*p
= (struct kif_proto
*) P
;
159 tm_stop(kif_scan_timer
);
167 kif_reconfigure(struct proto
*p
, struct proto_config
*new)
169 struct kif_config
*o
= (struct kif_config
*) p
->cf
;
170 struct kif_config
*n
= (struct kif_config
*) new;
172 if (!kif_sys_reconfigure((struct kif_proto
*) p
, n
, o
))
175 if (o
->scan_time
!= n
->scan_time
)
177 tm_stop(kif_scan_timer
);
178 kif_scan_timer
->recurrent
= n
->scan_time
;
179 kif_scan(kif_scan_timer
);
180 tm_start(kif_scan_timer
, n
->scan_time
);
183 if (!EMPTY_LIST(o
->iface_list
) || !EMPTY_LIST(n
->iface_list
))
185 /* This is hack, we have to update a configuration
186 * to the new value just now, because it is used
187 * for recalculation of preferred addresses.
191 if_recalc_all_preferred_addresses();
199 kif_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
202 kif_sys_preconfig(c
);
205 struct proto_config
*
206 kif_init_config(int class)
209 cf_error("Kernel device protocol already defined");
211 kif_cf
= (struct kif_config
*) proto_config_new(&proto_unix_iface
, class);
212 kif_cf
->scan_time
= 60 S
;
213 init_list(&kif_cf
->iface_list
);
215 kif_sys_init_config(kif_cf
);
216 return (struct proto_config
*) kif_cf
;
220 kif_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
222 struct kif_config
*d
= (struct kif_config
*) dest
;
223 struct kif_config
*s
= (struct kif_config
*) src
;
225 /* Copy interface config list */
226 cfg_copy_list(&d
->iface_list
, &s
->iface_list
, sizeof(struct kif_iface_config
));
228 /* Fix sysdep parts */
229 kif_sys_copy_config(d
, s
);
232 struct protocol proto_unix_iface
= {
234 .template = "device%d",
235 .class = PROTOCOL_DEVICE
,
236 .proto_size
= sizeof(struct kif_proto
),
237 .config_size
= sizeof(struct kif_config
),
238 .preconfig
= kif_preconfig
,
241 .shutdown
= kif_shutdown
,
242 .reconfigure
= kif_reconfigure
,
243 .copy_config
= kif_copy_config
251 krt_trace_in(struct krt_proto
*p
, rte
*e
, char *msg
)
253 if (p
->p
.debug
& D_PACKETS
)
254 log(L_TRACE
"%s: %N: %s", p
->p
.name
, e
->net
->n
.addr
, msg
);
258 krt_trace_in_rl(struct tbf
*f
, struct krt_proto
*p
, rte
*e
, char *msg
)
260 if (p
->p
.debug
& D_PACKETS
)
261 log_rl(f
, L_TRACE
"%s: %N: %s", p
->p
.name
, e
->net
->n
.addr
, msg
);
268 #ifdef KRT_ALLOW_LEARN
270 static struct tbf rl_alien
= TBF_DEFAULT_LOG_LIMITS
;
273 * krt_same_key() specifies what (aside from the net) is the key in
274 * kernel routing tables. It should be OS-dependent, this is for
275 * Linux. It is important for asynchronous alien updates, because a
276 * positive update is implicitly a negative one for any old route with
281 krt_same_key(rte
*a
, rte
*b
)
283 return a
->u
.krt
.metric
== b
->u
.krt
.metric
;
287 krt_uptodate(rte
*a
, rte
*b
)
289 if (a
->attrs
!= b
->attrs
)
292 if (a
->u
.krt
.proto
!= b
->u
.krt
.proto
)
299 krt_learn_announce_update(struct krt_proto
*p
, rte
*e
)
302 rta
*aa
= rta_clone(e
->attrs
);
303 rte
*ee
= rte_get_temp(aa
);
304 ee
->pflags
= EA_ID_FLAG(EA_KRT_SOURCE
) | EA_ID_FLAG(EA_KRT_METRIC
);
305 ee
->u
.krt
= e
->u
.krt
;
306 rte_update(&p
->p
, n
->n
.addr
, ee
);
310 krt_learn_announce_delete(struct krt_proto
*p
, net
*n
)
312 rte_update(&p
->p
, n
->n
.addr
, NULL
);
315 /* Called when alien route is discovered during scan */
317 krt_learn_scan(struct krt_proto
*p
, rte
*e
)
320 net
*n
= net_get(&p
->krt_table
, n0
->n
.addr
);
323 e
->attrs
= rta_lookup(e
->attrs
);
325 for(mm
=&n
->routes
; m
= *mm
; mm
=&m
->next
)
326 if (krt_same_key(m
, e
))
330 if (krt_uptodate(m
, e
))
332 krt_trace_in_rl(&rl_alien
, p
, e
, "[alien] seen");
338 krt_trace_in(p
, e
, "[alien] updated");
345 krt_trace_in(p
, e
, "[alien] created");
355 krt_learn_prune(struct krt_proto
*p
)
357 struct fib
*fib
= &p
->krt_table
.fib
;
358 struct fib_iterator fit
;
360 KRT_TRACE(p
, D_EVENTS
, "Pruning inherited routes");
362 FIB_ITERATE_INIT(&fit
, fib
);
364 FIB_ITERATE_START(fib
, &fit
, net
, n
)
366 rte
*e
, **ee
, *best
, **pbest
, *old_best
;
369 * Note that old_best may be NULL even if there was an old best route in
370 * the previous step, because it might be replaced in krt_learn_scan().
371 * But in that case there is a new valid best route.
390 if (!best
|| best
->u
.krt
.metric
> e
->u
.krt
.metric
)
402 DBG("%I/%d: deleting\n", n
->n
.prefix
, n
->n
.pxlen
);
404 krt_learn_announce_delete(p
, n
);
406 FIB_ITERATE_PUT(&fit
);
411 best
->u
.krt
.best
= 1;
413 best
->next
= n
->routes
;
416 if ((best
!= old_best
) || p
->reload
)
418 DBG("%I/%d: announcing (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
419 krt_learn_announce_update(p
, best
);
422 DBG("%I/%d: uptodate (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
430 krt_learn_async(struct krt_proto
*p
, rte
*e
, int new)
433 net
*n
= net_get(&p
->krt_table
, n0
->n
.addr
);
434 rte
*g
, **gg
, *best
, **bestp
, *old_best
;
436 e
->attrs
= rta_lookup(e
->attrs
);
438 old_best
= n
->routes
;
439 for(gg
=&n
->routes
; g
= *gg
; gg
= &g
->next
)
440 if (krt_same_key(g
, e
))
446 if (krt_uptodate(g
, e
))
448 krt_trace_in(p
, e
, "[alien async] same");
452 krt_trace_in(p
, e
, "[alien async] updated");
457 krt_trace_in(p
, e
, "[alien async] created");
464 krt_trace_in(p
, e
, "[alien async] delete failed");
470 krt_trace_in(p
, e
, "[alien async] removed");
477 for(gg
=&n
->routes
; g
=*gg
; gg
=&g
->next
)
479 if (best
->u
.krt
.metric
> g
->u
.krt
.metric
)
490 best
->u
.krt
.best
= 1;
492 best
->next
= n
->routes
;
496 if (best
!= old_best
)
498 DBG("krt_learn_async: distributing change\n");
500 krt_learn_announce_update(p
, best
);
502 krt_learn_announce_delete(p
, n
);
507 krt_learn_init(struct krt_proto
*p
)
511 struct rtable_config
*cf
= mb_allocz(p
->p
.pool
, sizeof(struct rtable_config
));
512 cf
->name
= "Inherited";
513 cf
->addr_type
= p
->p
.net_type
;
515 rt_setup(p
->p
.pool
, &p
->krt_table
, cf
);
520 krt_dump(struct proto
*P
)
522 struct krt_proto
*p
= (struct krt_proto
*) P
;
526 debug("KRT: Table of inheritable routes\n");
527 rt_dump(&p
->krt_table
);
531 krt_dump_attrs(rte
*e
)
533 debug(" [m=%d,p=%d]", e
->u
.krt
.metric
, e
->u
.krt
.proto
);
543 krt_is_installed(struct krt_proto
*p
, net
*n
)
545 return n
->routes
&& bmap_test(&p
->p
.main_channel
->export_map
, n
->routes
->id
);
549 krt_flush_routes(struct krt_proto
*p
)
551 struct rtable
*t
= p
->p
.main_channel
->table
;
553 KRT_TRACE(p
, D_EVENTS
, "Flushing kernel routes");
554 FIB_WALK(&t
->fib
, net
, n
)
556 if (krt_is_installed(p
, n
))
558 /* FIXME: this does not work if gw is changed in export filter */
559 krt_replace_rte(p
, n
, NULL
, n
->routes
);
566 krt_export_net(struct krt_proto
*p
, net
*net
, rte
**rt_free
)
568 struct channel
*c
= p
->p
.main_channel
;
569 const struct filter
*filter
= c
->out_filter
;
572 if (c
->ra_mode
== RA_MERGED
)
573 return rt_export_merged(c
, net
, rt_free
, krt_filter_lp
, 1);
578 if (!rte_is_valid(rt
))
581 if (filter
== FILTER_REJECT
)
584 rte_make_tmp_attrs(&rt
, krt_filter_lp
, NULL
);
586 /* We could run krt_preexport() here, but it is already handled by krt_is_installed() */
588 if (filter
== FILTER_ACCEPT
)
591 if (f_run(filter
, &rt
, krt_filter_lp
, FF_SILENT
) > F_ACCEPT
)
596 if (rt
!= net
->routes
)
601 if (rt
!= net
->routes
)
607 krt_same_dest(rte
*k
, rte
*e
)
609 rta
*ka
= k
->attrs
, *ea
= e
->attrs
;
611 if (ka
->dest
!= ea
->dest
)
614 if (ka
->dest
== RTD_UNICAST
)
615 return nexthop_same(&(ka
->nh
), &(ea
->nh
));
621 * This gets called back when the low-level scanning code discovers a route.
622 * We expect that the route is a temporary rte and its attributes are uncached.
626 krt_got_route(struct krt_proto
*p
, rte
*e
)
631 #ifdef KRT_ALLOW_LEARN
632 switch (e
->u
.krt
.src
)
635 verdict
= KRF_IGNORE
;
638 case KRT_SRC_REDIRECT
:
639 verdict
= KRF_DELETE
;
644 krt_learn_scan(p
, e
);
647 krt_trace_in_rl(&rl_alien
, p
, e
, "[alien] ignored");
653 /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
655 if (net
->n
.flags
& KRF_VERDICT_MASK
)
657 /* Route to this destination was already seen. Strange, but it happens... */
658 krt_trace_in(p
, e
, "already seen");
665 /* We wait for the initial feed to have correct installed state */
666 verdict
= KRF_IGNORE
;
670 if (krt_is_installed(p
, net
))
674 new = krt_export_net(p
, net
, &rt_free
);
676 /* TODO: There also may be changes in route eattrs, we ignore that for now. */
679 verdict
= KRF_DELETE
;
680 else if (!bmap_test(&p
->sync_map
, new->id
) || !krt_same_dest(e
, new))
681 verdict
= KRF_UPDATE
;
688 lp_flush(krt_filter_lp
);
691 verdict
= KRF_DELETE
;
694 krt_trace_in(p
, e
, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict
]);
695 net
->n
.flags
= (net
->n
.flags
& ~KRF_VERDICT_MASK
) | verdict
;
696 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
698 /* Get a cached copy of attributes and temporarily link the route */
700 a
->source
= RTS_DUMMY
;
701 e
->attrs
= rta_lookup(a
);
702 e
->next
= net
->routes
;
710 krt_prune(struct krt_proto
*p
)
712 struct rtable
*t
= p
->p
.main_channel
->table
;
714 KRT_TRACE(p
, D_EVENTS
, "Pruning table %s", t
->name
);
715 FIB_WALK(&t
->fib
, net
, n
)
717 int verdict
= n
->n
.flags
& KRF_VERDICT_MASK
;
718 rte
*new, *old
, *rt_free
= NULL
;
720 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
722 /* Get a dummy route from krt_got_route() */
724 n
->routes
= old
->next
;
729 if (verdict
== KRF_CREATE
|| verdict
== KRF_UPDATE
)
731 /* We have to run export filter to get proper 'new' route */
732 new = krt_export_net(p
, n
, &rt_free
);
735 verdict
= (verdict
== KRF_CREATE
) ? KRF_IGNORE
: KRF_DELETE
;
743 krt_trace_in(p
, new, "reinstalling");
744 krt_replace_rte(p
, n
, new, NULL
);
748 /* Nothing happens */
751 krt_trace_in(p
, new, "updating");
752 krt_replace_rte(p
, n
, new, old
);
755 krt_trace_in(p
, old
, "deleting");
756 krt_replace_rte(p
, n
, NULL
, old
);
759 bug("krt_prune: invalid route status");
766 lp_flush(krt_filter_lp
);
767 n
->n
.flags
&= ~KRF_VERDICT_MASK
;
771 #ifdef KRT_ALLOW_LEARN
781 krt_got_route_async(struct krt_proto
*p
, rte
*e
, int new)
785 switch (e
->u
.krt
.src
)
788 /* Should be filtered by the back end */
789 bug("BIRD originated routes should not get here.");
791 case KRT_SRC_REDIRECT
:
794 krt_trace_in(p
, e
, "[redirect] deleting");
795 krt_replace_rte(p
, net
, NULL
, e
);
797 /* If !new, it is probably echo of our deletion */
800 #ifdef KRT_ALLOW_LEARN
804 krt_learn_async(p
, e
, new);
817 #ifdef CONFIG_ALL_TABLES_AT_ONCE
819 static timer
*krt_scan_timer
;
820 static int krt_scan_count
;
823 krt_scan(timer
*t UNUSED
)
829 /* We need some node to decide whether to print the debug messages or not */
830 p
= SKIP_BACK(struct krt_proto
, krt_node
, HEAD(krt_proto_list
));
831 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
836 WALK_LIST(q
, krt_proto_list
)
838 p
= SKIP_BACK(struct krt_proto
, krt_node
, q
);
844 krt_scan_timer_start(struct krt_proto
*p
)
847 krt_scan_timer
= tm_new_init(krt_pool
, krt_scan
, NULL
, KRT_CF
->scan_time
, 0);
851 tm_start(krt_scan_timer
, 1 S
);
855 krt_scan_timer_stop(struct krt_proto
*p UNUSED
)
861 rfree(krt_scan_timer
);
862 krt_scan_timer
= NULL
;
867 krt_scan_timer_kick(struct krt_proto
*p UNUSED
)
869 tm_start(krt_scan_timer
, 0);
877 struct krt_proto
*p
= t
->data
;
881 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
887 krt_scan_timer_start(struct krt_proto
*p
)
889 p
->scan_timer
= tm_new_init(p
->p
.pool
, krt_scan
, p
, KRT_CF
->scan_time
, 0);
890 tm_start(p
->scan_timer
, 1 S
);
894 krt_scan_timer_stop(struct krt_proto
*p
)
896 tm_stop(p
->scan_timer
);
900 krt_scan_timer_kick(struct krt_proto
*p
)
902 tm_start(p
->scan_timer
, 0);
915 krt_make_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
917 rte_init_tmp_attrs(rt
, pool
, 2);
918 rte_make_tmp_attr(rt
, EA_KRT_SOURCE
, EAF_TYPE_INT
, rt
->u
.krt
.proto
);
919 rte_make_tmp_attr(rt
, EA_KRT_METRIC
, EAF_TYPE_INT
, rt
->u
.krt
.metric
);
923 krt_store_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
925 rte_init_tmp_attrs(rt
, pool
, 2);
926 rt
->u
.krt
.proto
= rte_store_tmp_attr(rt
, EA_KRT_SOURCE
);
927 rt
->u
.krt
.metric
= rte_store_tmp_attr(rt
, EA_KRT_METRIC
);
931 krt_preexport(struct proto
*P
, rte
**new, struct linpool
*pool UNUSED
)
933 // struct krt_proto *p = (struct krt_proto *) P;
936 if (e
->attrs
->src
->proto
== P
)
946 krt_rt_notify(struct proto
*P
, struct channel
*ch UNUSED
, net
*net
,
949 struct krt_proto
*p
= (struct krt_proto
*) P
;
951 if (config
->shutdown
)
954 #ifdef CONFIG_SINGLE_ROUTE
956 * Implicit withdraw - when the imported kernel route becomes the best one,
957 * we know that the previous one exported to the kernel was already removed,
958 * but if we processed the update as usual, we would send withdraw to the
959 * kernel, which would remove the new imported route instead.
961 rte
*best
= net
->routes
;
962 if (!new && best
&& (best
->attrs
->src
->proto
== P
))
966 if (p
->initialized
) /* Before first scan we don't touch the routes */
967 krt_replace_rte(p
, net
, new, old
);
971 krt_if_notify(struct proto
*P
, uint flags
, struct iface
*iface UNUSED
)
973 struct krt_proto
*p
= (struct krt_proto
*) P
;
976 * When interface went down, we should remove routes to it. In the ideal world,
977 * OS kernel would send us route removal notifications in such cases, but we
978 * cannot rely on it as it is often not true. E.g. Linux kernel removes related
979 * routes when an interface went down, but it does not notify userspace about
980 * that. To be sure, we just schedule a scan to ensure synchronization.
983 if ((flags
& IF_CHANGE_DOWN
) && KRT_CF
->learn
)
984 krt_scan_timer_kick(p
);
988 krt_reload_routes(struct channel
*C
)
990 struct krt_proto
*p
= (void *) C
->proto
;
992 /* Although we keep learned routes in krt_table, we rather schedule a scan */
997 krt_scan_timer_kick(p
);
1002 krt_feed_end(struct channel
*C
)
1004 struct krt_proto
*p
= (void *) C
->proto
;
1007 krt_scan_timer_kick(p
);
1012 krt_rte_same(rte
*a
, rte
*b
)
1014 /* src is always KRT_SRC_ALIEN and type is irrelevant */
1015 return (a
->u
.krt
.proto
== b
->u
.krt
.proto
) && (a
->u
.krt
.metric
== b
->u
.krt
.metric
);
1023 struct krt_config
*krt_cf
;
1026 krt_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
1029 krt_sys_preconfig(c
);
1033 krt_postconfig(struct proto_config
*CF
)
1035 struct krt_config
*cf
= (void *) CF
;
1037 if (EMPTY_LIST(CF
->channels
))
1038 cf_error("Channel not specified");
1040 #ifdef CONFIG_ALL_TABLES_AT_ONCE
1041 if (krt_cf
->scan_time
!= cf
->scan_time
)
1042 cf_error("All kernel syncers must use the same table scan interval");
1045 struct channel_config
*cc
= proto_cf_main_channel(CF
);
1046 struct rtable_config
*tab
= cc
->table
;
1047 if (tab
->krt_attached
)
1048 cf_error("Kernel syncer (%s) already attached to table %s", tab
->krt_attached
->name
, tab
->name
);
1049 tab
->krt_attached
= CF
;
1051 if (cf
->merge_paths
)
1053 cc
->ra_mode
= RA_MERGED
;
1054 cc
->merge_limit
= cf
->merge_paths
;
1057 krt_sys_postconfig(cf
);
1060 static struct proto
*
1061 krt_init(struct proto_config
*CF
)
1063 struct krt_proto
*p
= proto_new(CF
);
1064 // struct krt_config *cf = (void *) CF;
1066 p
->p
.main_channel
= proto_add_channel(&p
->p
, proto_cf_main_channel(CF
));
1068 p
->p
.preexport
= krt_preexport
;
1069 p
->p
.rt_notify
= krt_rt_notify
;
1070 p
->p
.if_notify
= krt_if_notify
;
1071 p
->p
.reload_routes
= krt_reload_routes
;
1072 p
->p
.feed_end
= krt_feed_end
;
1073 p
->p
.make_tmp_attrs
= krt_make_tmp_attrs
;
1074 p
->p
.store_tmp_attrs
= krt_store_tmp_attrs
;
1075 p
->p
.rte_same
= krt_rte_same
;
1082 krt_start(struct proto
*P
)
1084 struct krt_proto
*p
= (struct krt_proto
*) P
;
1086 switch (p
->p
.net_type
)
1088 case NET_IP4
: p
->af
= AF_INET
; break;
1089 case NET_IP6
: p
->af
= AF_INET6
; break;
1090 case NET_IP6_SADR
: p
->af
= AF_INET6
; break;
1092 case NET_MPLS
: p
->af
= AF_MPLS
; break;
1094 default: log(L_ERR
"KRT: Tried to start with strange net type: %d", p
->p
.net_type
); return PS_START
; break;
1097 bmap_init(&p
->sync_map
, p
->p
.pool
, 1024);
1098 add_tail(&krt_proto_list
, &p
->krt_node
);
1100 #ifdef KRT_ALLOW_LEARN
1104 if (!krt_sys_start(p
))
1106 rem_node(&p
->krt_node
);
1110 krt_scan_timer_start(p
);
1112 if (p
->p
.gr_recovery
&& KRT_CF
->graceful_restart
)
1113 p
->p
.main_channel
->gr_wait
= 1;
1119 krt_shutdown(struct proto
*P
)
1121 struct krt_proto
*p
= (struct krt_proto
*) P
;
1123 krt_scan_timer_stop(p
);
1125 /* FIXME we should flush routes even when persist during reconfiguration */
1126 if (p
->initialized
&& !KRT_CF
->persist
&& (P
->down_code
!= PDC_CMD_GR_DOWN
))
1127 krt_flush_routes(p
);
1132 if (p
->p
.proto_state
== PS_START
)
1135 krt_sys_shutdown(p
);
1136 rem_node(&p
->krt_node
);
1137 bmap_free(&p
->sync_map
);
1143 krt_reconfigure(struct proto
*p
, struct proto_config
*CF
)
1145 struct krt_config
*o
= (void *) p
->cf
;
1146 struct krt_config
*n
= (void *) CF
;
1148 if (!proto_configure_channel(p
, &p
->main_channel
, proto_cf_main_channel(CF
)))
1151 if (!krt_sys_reconfigure((struct krt_proto
*) p
, n
, o
))
1154 /* persist, graceful restart need not be the same */
1155 return o
->scan_time
== n
->scan_time
&& o
->learn
== n
->learn
;
1158 struct proto_config
*
1159 krt_init_config(int class)
1161 #ifndef CONFIG_MULTIPLE_TABLES
1163 cf_error("Kernel protocol already defined");
1166 krt_cf
= (struct krt_config
*) proto_config_new(&proto_unix_kernel
, class);
1167 krt_cf
->scan_time
= 60 S
;
1169 krt_sys_init_config(krt_cf
);
1170 return (struct proto_config
*) krt_cf
;
1174 krt_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
1176 struct krt_config
*d
= (struct krt_config
*) dest
;
1177 struct krt_config
*s
= (struct krt_config
*) src
;
1179 /* Fix sysdep parts */
1180 krt_sys_copy_config(d
, s
);
1184 krt_get_attr(eattr
*a
, byte
*buf
, int buflen
)
1189 bsprintf(buf
, "source");
1193 bsprintf(buf
, "metric");
1197 return krt_sys_get_attr(a
, buf
, buflen
);
1202 #ifdef CONFIG_IP6_SADR_KERNEL
1203 #define MAYBE_IP6_SADR NB_IP6_SADR
1205 #define MAYBE_IP6_SADR 0
1208 #ifdef HAVE_MPLS_KERNEL
1209 #define MAYBE_MPLS NB_MPLS
1211 #define MAYBE_MPLS 0
1214 struct protocol proto_unix_kernel
= {
1216 .template = "kernel%d",
1217 .class = PROTOCOL_KERNEL
,
1218 .preference
= DEF_PREF_INHERITED
,
1219 .channel_mask
= NB_IP
| MAYBE_IP6_SADR
| MAYBE_MPLS
,
1220 .proto_size
= sizeof(struct krt_proto
),
1221 .config_size
= sizeof(struct krt_config
),
1222 .preconfig
= krt_preconfig
,
1223 .postconfig
= krt_postconfig
,
1226 .shutdown
= krt_shutdown
,
1227 .reconfigure
= krt_reconfigure
,
1228 .copy_config
= krt_copy_config
,
1229 .get_attr
= krt_get_attr
,
1230 #ifdef KRT_ALLOW_LEARN
1232 .dump_attrs
= krt_dump_attrs
,