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
;
72 static list krt_proto_list
;
77 krt_pool
= rp_new(&root_pool
, "Kernel Syncer");
78 krt_filter_lp
= lp_new(krt_pool
, 4080);
79 init_list(&krt_proto_list
);
86 static struct kif_config
*kif_cf
;
87 static struct kif_proto
*kif_proto
;
88 static timer
*kif_scan_timer
;
89 static bird_clock_t kif_last_shot
;
94 struct kif_proto
*p
= t
->data
;
96 KRT_TRACE(p
, D_EVENTS
, "Scanning interfaces");
104 if (kif_proto
&& kif_last_shot
+ 2 < now
)
106 kif_scan(kif_scan_timer
);
107 tm_start(kif_scan_timer
, ((struct kif_config
*) kif_proto
->p
.cf
)->scan_time
);
112 kif_request_scan(void)
114 if (kif_proto
&& kif_scan_timer
->expires
> now
)
115 tm_start(kif_scan_timer
, 1);
119 prefer_addr(struct ifa
*a
, struct ifa
*b
)
121 int sa
= a
->scope
> SCOPE_LINK
;
122 int sb
= b
->scope
> SCOPE_LINK
;
129 return ipa_compare(a
->ip
, b
->ip
) < 0;
132 static inline struct ifa
*
133 find_preferred_ifa(struct iface
*i
, ip_addr prefix
, ip_addr mask
)
135 struct ifa
*a
, *b
= NULL
;
137 WALK_LIST(a
, i
->addrs
)
139 if (!(a
->flags
& IA_SECONDARY
) &&
140 ipa_equal(ipa_and(a
->ip
, mask
), prefix
) &&
141 (!b
|| prefer_addr(a
, b
)))
149 kif_choose_primary(struct iface
*i
)
151 struct kif_config
*cf
= (struct kif_config
*) (kif_proto
->p
.cf
);
152 struct kif_primary_item
*it
;
155 WALK_LIST(it
, cf
->primary
)
157 if (!it
->pattern
|| patmatch(it
->pattern
, i
->name
))
158 if (a
= find_preferred_ifa(i
, it
->prefix
, ipa_mkmask(it
->pxlen
)))
162 if (a
= kif_get_primary_ip(i
))
165 return find_preferred_ifa(i
, IPA_NONE
, IPA_NONE
);
169 static struct proto
*
170 kif_init(struct proto_config
*c
)
172 struct kif_proto
*p
= proto_new(c
, sizeof(struct kif_proto
));
179 kif_start(struct proto
*P
)
181 struct kif_proto
*p
= (struct kif_proto
*) P
;
186 /* Start periodic interface scanning */
187 kif_scan_timer
= tm_new(P
->pool
);
188 kif_scan_timer
->hook
= kif_scan
;
189 kif_scan_timer
->data
= p
;
190 kif_scan_timer
->recurrent
= KIF_CF
->scan_time
;
191 kif_scan(kif_scan_timer
);
192 tm_start(kif_scan_timer
, KIF_CF
->scan_time
);
198 kif_shutdown(struct proto
*P
)
200 struct kif_proto
*p
= (struct kif_proto
*) P
;
202 tm_stop(kif_scan_timer
);
210 kif_reconfigure(struct proto
*p
, struct proto_config
*new)
212 struct kif_config
*o
= (struct kif_config
*) p
->cf
;
213 struct kif_config
*n
= (struct kif_config
*) new;
215 if (!kif_sys_reconfigure((struct kif_proto
*) p
, n
, o
))
218 if (o
->scan_time
!= n
->scan_time
)
220 tm_stop(kif_scan_timer
);
221 kif_scan_timer
->recurrent
= n
->scan_time
;
222 kif_scan(kif_scan_timer
);
223 tm_start(kif_scan_timer
, n
->scan_time
);
226 if (!EMPTY_LIST(o
->primary
) || !EMPTY_LIST(n
->primary
))
228 /* This is hack, we have to update a configuration
229 * to the new value just now, because it is used
230 * for recalculation of primary addresses.
234 ifa_recalc_all_primary_addresses();
242 kif_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
245 kif_sys_preconfig(c
);
248 struct proto_config
*
249 kif_init_config(int class)
252 cf_error("Kernel device protocol already defined");
254 kif_cf
= (struct kif_config
*) proto_config_new(&proto_unix_iface
, sizeof(struct kif_config
), class);
255 kif_cf
->scan_time
= 60;
256 init_list(&kif_cf
->primary
);
258 kif_sys_init_config(kif_cf
);
259 return (struct proto_config
*) kif_cf
;
263 kif_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
265 struct kif_config
*d
= (struct kif_config
*) dest
;
266 struct kif_config
*s
= (struct kif_config
*) src
;
268 /* Shallow copy of everything (just scan_time currently) */
269 proto_copy_rest(dest
, src
, sizeof(struct kif_config
));
271 /* Copy primary addr list */
272 cfg_copy_list(&d
->primary
, &s
->primary
, sizeof(struct kif_primary_item
));
274 /* Fix sysdep parts */
275 kif_sys_copy_config(d
, s
);
279 struct protocol proto_unix_iface
= {
281 .template = "device%d",
282 .preference
= DEF_PREF_DIRECT
,
283 .preconfig
= kif_preconfig
,
286 .shutdown
= kif_shutdown
,
287 .reconfigure
= kif_reconfigure
,
288 .copy_config
= kif_copy_config
296 krt_trace_in(struct krt_proto
*p
, rte
*e
, char *msg
)
298 if (p
->p
.debug
& D_PACKETS
)
299 log(L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
303 krt_trace_in_rl(struct tbf
*f
, struct krt_proto
*p
, rte
*e
, char *msg
)
305 if (p
->p
.debug
& D_PACKETS
)
306 log_rl(f
, L_TRACE
"%s: %I/%d: %s", p
->p
.name
, e
->net
->n
.prefix
, e
->net
->n
.pxlen
, msg
);
313 #ifdef KRT_ALLOW_LEARN
315 static struct tbf rl_alien
= TBF_DEFAULT_LOG_LIMITS
;
318 * krt_same_key() specifies what (aside from the net) is the key in
319 * kernel routing tables. It should be OS-dependent, this is for
320 * Linux. It is important for asynchronous alien updates, because a
321 * positive update is implicitly a negative one for any old route with
326 krt_same_key(rte
*a
, rte
*b
)
328 return a
->u
.krt
.metric
== b
->u
.krt
.metric
;
332 krt_uptodate(rte
*a
, rte
*b
)
334 if (a
->attrs
!= b
->attrs
)
337 if (a
->u
.krt
.proto
!= b
->u
.krt
.proto
)
344 krt_learn_announce_update(struct krt_proto
*p
, rte
*e
)
347 rta
*aa
= rta_clone(e
->attrs
);
348 rte
*ee
= rte_get_temp(aa
);
349 net
*nn
= net_get(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
352 ee
->pref
= p
->p
.preference
;
353 ee
->u
.krt
= e
->u
.krt
;
354 rte_update(&p
->p
, nn
, ee
);
358 krt_learn_announce_delete(struct krt_proto
*p
, net
*n
)
360 n
= net_find(p
->p
.table
, n
->n
.prefix
, n
->n
.pxlen
);
361 rte_update(&p
->p
, n
, NULL
);
364 /* Called when alien route is discovered during scan */
366 krt_learn_scan(struct krt_proto
*p
, rte
*e
)
369 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
372 e
->attrs
= rta_lookup(e
->attrs
);
374 for(mm
=&n
->routes
; m
= *mm
; mm
=&m
->next
)
375 if (krt_same_key(m
, e
))
379 if (krt_uptodate(m
, e
))
381 krt_trace_in_rl(&rl_alien
, p
, e
, "[alien] seen");
387 krt_trace_in(p
, e
, "[alien] updated");
394 krt_trace_in(p
, e
, "[alien] created");
404 krt_learn_prune(struct krt_proto
*p
)
406 struct fib
*fib
= &p
->krt_table
.fib
;
407 struct fib_iterator fit
;
409 KRT_TRACE(p
, D_EVENTS
, "Pruning inherited routes");
411 FIB_ITERATE_INIT(&fit
, fib
);
413 FIB_ITERATE_START(fib
, &fit
, f
)
416 rte
*e
, **ee
, *best
, **pbest
, *old_best
;
418 old_best
= n
->routes
;
430 if (!best
|| best
->u
.krt
.metric
> e
->u
.krt
.metric
)
440 DBG("%I/%d: deleting\n", n
->n
.prefix
, n
->n
.pxlen
);
443 krt_learn_announce_delete(p
, n
);
444 n
->n
.flags
&= ~KRF_INSTALLED
;
446 FIB_ITERATE_PUT(&fit
, f
);
451 best
->next
= n
->routes
;
453 if (best
!= old_best
|| !(n
->n
.flags
& KRF_INSTALLED
))
455 DBG("%I/%d: announcing (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
456 krt_learn_announce_update(p
, best
);
457 n
->n
.flags
|= KRF_INSTALLED
;
460 DBG("%I/%d: uptodate (metric=%d)\n", n
->n
.prefix
, n
->n
.pxlen
, best
->u
.krt
.metric
);
466 krt_learn_async(struct krt_proto
*p
, rte
*e
, int new)
469 net
*n
= net_get(&p
->krt_table
, n0
->n
.prefix
, n0
->n
.pxlen
);
470 rte
*g
, **gg
, *best
, **bestp
, *old_best
;
472 e
->attrs
= rta_lookup(e
->attrs
);
474 old_best
= n
->routes
;
475 for(gg
=&n
->routes
; g
= *gg
; gg
= &g
->next
)
476 if (krt_same_key(g
, e
))
482 if (krt_uptodate(g
, e
))
484 krt_trace_in(p
, e
, "[alien async] same");
488 krt_trace_in(p
, e
, "[alien async] updated");
493 krt_trace_in(p
, e
, "[alien async] created");
500 krt_trace_in(p
, e
, "[alien async] delete failed");
506 krt_trace_in(p
, e
, "[alien async] removed");
513 for(gg
=&n
->routes
; g
=*gg
; gg
=&g
->next
)
514 if (best
->u
.krt
.metric
> g
->u
.krt
.metric
)
522 best
->next
= n
->routes
;
525 if (best
!= old_best
)
527 DBG("krt_learn_async: distributing change\n");
530 krt_learn_announce_update(p
, best
);
531 n
->n
.flags
|= KRF_INSTALLED
;
536 krt_learn_announce_delete(p
, n
);
537 n
->n
.flags
&= ~KRF_INSTALLED
;
543 krt_learn_init(struct krt_proto
*p
)
546 rt_setup(p
->p
.pool
, &p
->krt_table
, "Inherited", NULL
);
550 krt_dump(struct proto
*P
)
552 struct krt_proto
*p
= (struct krt_proto
*) P
;
556 debug("KRT: Table of inheritable routes\n");
557 rt_dump(&p
->krt_table
);
561 krt_dump_attrs(rte
*e
)
563 debug(" [m=%d,p=%d,t=%d]", e
->u
.krt
.metric
, e
->u
.krt
.proto
, e
->u
.krt
.type
);
573 krt_flush_routes(struct krt_proto
*p
)
575 struct rtable
*t
= p
->p
.table
;
577 KRT_TRACE(p
, D_EVENTS
, "Flushing kernel routes");
582 if (rte_is_valid(e
) && (n
->n
.flags
& KRF_INSTALLED
))
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
;
593 krt_same_dest(rte
*k
, rte
*e
)
595 rta
*ka
= k
->attrs
, *ea
= e
->attrs
;
597 if (ka
->dest
!= ea
->dest
)
602 return ipa_equal(ka
->gw
, ea
->gw
);
604 return !strcmp(ka
->iface
->name
, ea
->iface
->name
);
606 return mpnh_same(ka
->nexthops
, ea
->nexthops
);
613 * This gets called back when the low-level scanning code discovers a route.
614 * We expect that the route is a temporary rte and its attributes are uncached.
618 krt_got_route(struct krt_proto
*p
, rte
*e
)
624 #ifdef KRT_ALLOW_LEARN
625 switch (e
->u
.krt
.src
)
628 verdict
= KRF_IGNORE
;
631 case KRT_SRC_REDIRECT
:
632 verdict
= KRF_DELETE
;
637 krt_learn_scan(p
, e
);
640 krt_trace_in_rl(&rl_alien
, p
, e
, "[alien] ignored");
646 /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
648 if (net
->n
.flags
& KRF_VERDICT_MASK
)
650 /* Route to this destination was already seen. Strange, but it happens... */
651 krt_trace_in(p
, e
, "already seen");
658 /* We wait for the initial feed to have correct KRF_INSTALLED flag */
659 verdict
= KRF_IGNORE
;
664 if ((net
->n
.flags
& KRF_INSTALLED
) && rte_is_valid(old
))
666 /* There may be changes in route attributes, we ignore that.
667 Also, this does not work well if gw is changed in export filter */
668 if ((net
->n
.flags
& KRF_SYNC_ERROR
) || ! krt_same_dest(e
, old
))
669 verdict
= KRF_UPDATE
;
674 verdict
= KRF_DELETE
;
677 krt_trace_in(p
, e
, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict
]);
678 net
->n
.flags
= (net
->n
.flags
& ~KRF_VERDICT_MASK
) | verdict
;
679 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
681 /* Get a cached copy of attributes and temporarily link the route */
683 a
->source
= RTS_DUMMY
;
684 e
->attrs
= rta_lookup(a
);
685 e
->next
= net
->routes
;
693 krt_export_rte(struct krt_proto
*p
, rte
**new, ea_list
**tmpa
)
695 struct filter
*filter
= p
->p
.main_ahook
->out_filter
;
700 if (filter
== FILTER_REJECT
)
703 if (filter
== FILTER_ACCEPT
)
706 struct proto
*src
= (*new)->attrs
->src
->proto
;
707 *tmpa
= src
->make_tmp_attrs
? src
->make_tmp_attrs(*new, krt_filter_lp
) : NULL
;
708 return f_run(filter
, new, tmpa
, krt_filter_lp
, FF_FORCE_TMPATTR
) <= F_ACCEPT
;
712 krt_prune(struct krt_proto
*p
)
714 struct rtable
*t
= p
->p
.table
;
716 KRT_TRACE(p
, D_EVENTS
, "Pruning table %s", t
->name
);
720 int verdict
= f
->flags
& KRF_VERDICT_MASK
;
721 rte
*new, *new0
, *old
;
722 ea_list
*tmpa
= NULL
;
724 if (verdict
== KRF_UPDATE
|| verdict
== KRF_DELETE
)
726 /* Get a dummy route from krt_got_route() */
728 n
->routes
= old
->next
;
733 new = new0
= n
->routes
;
734 if (verdict
== KRF_CREATE
|| verdict
== KRF_UPDATE
)
736 /* We have to run export filter to get proper 'new' route */
737 if (! krt_export_rte(p
, &new, &tmpa
))
739 /* Route rejected, should not happen (KRF_INSTALLED) but to be sure .. */
740 verdict
= (verdict
== KRF_CREATE
) ? KRF_IGNORE
: KRF_DELETE
;
747 *x
= new ? new->attrs
->eattrs
: NULL
;
754 if (new && (f
->flags
& KRF_INSTALLED
))
756 krt_trace_in(p
, new, "reinstalling");
757 krt_replace_rte(p
, n
, new, NULL
, tmpa
);
762 /* Nothing happens */
765 krt_trace_in(p
, new, "updating");
766 krt_replace_rte(p
, n
, new, old
, tmpa
);
769 krt_trace_in(p
, old
, "deleting");
770 krt_replace_rte(p
, n
, NULL
, old
, NULL
);
773 bug("krt_prune: invalid route status");
780 lp_flush(krt_filter_lp
);
781 f
->flags
&= ~KRF_VERDICT_MASK
;
785 #ifdef KRT_ALLOW_LEARN
795 krt_got_route_async(struct krt_proto
*p
, rte
*e
, int new)
799 switch (e
->u
.krt
.src
)
802 ASSERT(0); /* Should be filtered by the back end */
804 case KRT_SRC_REDIRECT
:
807 krt_trace_in(p
, e
, "[redirect] deleting");
808 krt_replace_rte(p
, net
, NULL
, e
, NULL
);
810 /* If !new, it is probably echo of our deletion */
813 #ifdef KRT_ALLOW_LEARN
817 krt_learn_async(p
, e
, new);
830 #ifdef CONFIG_ALL_TABLES_AT_ONCE
832 static timer
*krt_scan_timer
;
833 static int krt_scan_count
;
836 krt_scan(timer
*t UNUSED
)
842 /* We need some node to decide whether to print the debug messages or not */
843 p
= SKIP_BACK(struct krt_proto
, krt_node
, HEAD(krt_proto_list
));
844 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
849 WALK_LIST(q
, krt_proto_list
)
851 p
= SKIP_BACK(struct krt_proto
, krt_node
, q
);
857 krt_scan_timer_start(struct krt_proto
*p
)
860 krt_scan_timer
= tm_new_set(krt_pool
, krt_scan
, NULL
, 0, KRT_CF
->scan_time
);
864 tm_start(krt_scan_timer
, 1);
868 krt_scan_timer_stop(struct krt_proto
*p
)
874 rfree(krt_scan_timer
);
875 krt_scan_timer
= NULL
;
880 krt_scan_timer_kick(struct krt_proto
*p UNUSED
)
882 tm_start(krt_scan_timer
, 0);
890 struct krt_proto
*p
= t
->data
;
894 KRT_TRACE(p
, D_EVENTS
, "Scanning routing table");
900 krt_scan_timer_start(struct krt_proto
*p
)
902 p
->scan_timer
= tm_new_set(p
->p
.pool
, krt_scan
, p
, 0, KRT_CF
->scan_time
);
903 tm_start(p
->scan_timer
, 1);
907 krt_scan_timer_stop(struct krt_proto
*p
)
909 tm_stop(p
->scan_timer
);
913 krt_scan_timer_kick(struct krt_proto
*p
)
915 tm_start(p
->scan_timer
, 0);
927 static struct ea_list
*
928 krt_make_tmp_attrs(rte
*rt
, struct linpool
*pool
)
930 struct ea_list
*l
= lp_alloc(pool
, sizeof(struct ea_list
) + 2 * sizeof(eattr
));
933 l
->flags
= EALF_SORTED
;
936 l
->attrs
[0].id
= EA_KRT_SOURCE
;
937 l
->attrs
[0].flags
= 0;
938 l
->attrs
[0].type
= EAF_TYPE_INT
| EAF_TEMP
;
939 l
->attrs
[0].u
.data
= rt
->u
.krt
.proto
;
941 l
->attrs
[1].id
= EA_KRT_METRIC
;
942 l
->attrs
[1].flags
= 0;
943 l
->attrs
[1].type
= EAF_TYPE_INT
| EAF_TEMP
;
944 l
->attrs
[1].u
.data
= rt
->u
.krt
.metric
;
950 krt_store_tmp_attrs(rte
*rt
, struct ea_list
*attrs
)
952 /* EA_KRT_SOURCE is read-only */
953 rt
->u
.krt
.metric
= ea_get_int(attrs
, EA_KRT_METRIC
, 0);
957 krt_import_control(struct proto
*P
, rte
**new, ea_list
**attrs
, struct linpool
*pool
)
959 struct krt_proto
*p
= (struct krt_proto
*) P
;
962 if (e
->attrs
->src
->proto
== P
)
965 if (!KRT_CF
->devroutes
&&
966 (e
->attrs
->dest
== RTD_DEVICE
) &&
967 (e
->attrs
->source
!= RTS_STATIC_DEVICE
))
977 krt_rt_notify(struct proto
*P
, struct rtable
*table UNUSED
, net
*net
,
978 rte
*new, rte
*old
, struct ea_list
*eattrs
)
980 struct krt_proto
*p
= (struct krt_proto
*) P
;
982 if (config
->shutdown
)
984 if (!(net
->n
.flags
& KRF_INSTALLED
))
987 net
->n
.flags
|= KRF_INSTALLED
;
989 net
->n
.flags
&= ~KRF_INSTALLED
;
990 if (p
->initialized
) /* Before first scan we don't touch the routes */
991 krt_replace_rte(p
, net
, new, old
, eattrs
);
995 krt_if_notify(struct proto
*P
, uint flags
, struct iface
*iface UNUSED
)
997 struct krt_proto
*p
= (struct krt_proto
*) P
;
1000 * When interface went down, we should remove routes to it. In the ideal world,
1001 * OS kernel would send us route removal notifications in such cases, but we
1002 * cannot rely on it as it is often not true. E.g. Linux kernel removes related
1003 * routes when an interface went down, but it does not notify userspace about
1004 * that. To be sure, we just schedule a scan to ensure synchronization.
1007 if ((flags
& IF_CHANGE_DOWN
) && KRT_CF
->learn
)
1008 krt_scan_timer_kick(p
);
1012 krt_reload_routes(struct proto
*P
)
1014 struct krt_proto
*p
= (struct krt_proto
*) P
;
1016 /* Although we keep learned routes in krt_table, we rather schedule a scan */
1019 krt_scan_timer_kick(p
);
1025 krt_feed_done(struct proto
*P
)
1027 struct krt_proto
*p
= (struct krt_proto
*) P
;
1030 krt_scan_timer_kick(p
);
1035 krt_rte_same(rte
*a
, rte
*b
)
1037 /* src is always KRT_SRC_ALIEN and type is irrelevant */
1038 return (a
->u
.krt
.proto
== b
->u
.krt
.proto
) && (a
->u
.krt
.metric
== b
->u
.krt
.metric
);
1046 struct krt_config
*krt_cf
;
1048 static struct proto
*
1049 krt_init(struct proto_config
*c
)
1051 struct krt_proto
*p
= proto_new(c
, sizeof(struct krt_proto
));
1053 p
->p
.accept_ra_types
= RA_OPTIMAL
;
1054 p
->p
.import_control
= krt_import_control
;
1055 p
->p
.rt_notify
= krt_rt_notify
;
1056 p
->p
.if_notify
= krt_if_notify
;
1057 p
->p
.reload_routes
= krt_reload_routes
;
1058 p
->p
.feed_done
= krt_feed_done
;
1059 p
->p
.make_tmp_attrs
= krt_make_tmp_attrs
;
1060 p
->p
.store_tmp_attrs
= krt_store_tmp_attrs
;
1061 p
->p
.rte_same
= krt_rte_same
;
1068 krt_start(struct proto
*P
)
1070 struct krt_proto
*p
= (struct krt_proto
*) P
;
1072 add_tail(&krt_proto_list
, &p
->krt_node
);
1074 #ifdef KRT_ALLOW_LEARN
1080 krt_scan_timer_start(p
);
1082 if (P
->gr_recovery
&& KRT_CF
->graceful_restart
)
1089 krt_shutdown(struct proto
*P
)
1091 struct krt_proto
*p
= (struct krt_proto
*) P
;
1093 krt_scan_timer_stop(p
);
1095 /* FIXME we should flush routes even when persist during reconfiguration */
1096 if (p
->initialized
&& !KRT_CF
->persist
)
1097 krt_flush_routes(p
);
1102 krt_sys_shutdown(p
);
1104 rem_node(&p
->krt_node
);
1110 krt_reconfigure(struct proto
*p
, struct proto_config
*new)
1112 struct krt_config
*o
= (struct krt_config
*) p
->cf
;
1113 struct krt_config
*n
= (struct krt_config
*) new;
1115 if (!krt_sys_reconfigure((struct krt_proto
*) p
, n
, o
))
1118 /* persist, graceful restart need not be the same */
1119 return o
->scan_time
== n
->scan_time
&& o
->learn
== n
->learn
&& o
->devroutes
== n
->devroutes
;
1123 krt_preconfig(struct protocol
*P UNUSED
, struct config
*c
)
1126 krt_sys_preconfig(c
);
1130 krt_postconfig(struct proto_config
*C
)
1132 struct krt_config
*c
= (struct krt_config
*) C
;
1134 #ifdef CONFIG_ALL_TABLES_AT_ONCE
1135 if (krt_cf
->scan_time
!= c
->scan_time
)
1136 cf_error("All kernel syncers must use the same table scan interval");
1139 if (C
->table
->krt_attached
)
1140 cf_error("Kernel syncer (%s) already attached to table %s", C
->table
->krt_attached
->name
, C
->table
->name
);
1141 C
->table
->krt_attached
= C
;
1142 krt_sys_postconfig(c
);
1145 struct proto_config
*
1146 krt_init_config(int class)
1148 #ifndef CONFIG_MULTIPLE_TABLES
1150 cf_error("Kernel protocol already defined");
1153 krt_cf
= (struct krt_config
*) proto_config_new(&proto_unix_kernel
, sizeof(struct krt_config
), class);
1154 krt_cf
->scan_time
= 60;
1156 krt_sys_init_config(krt_cf
);
1157 return (struct proto_config
*) krt_cf
;
1161 krt_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
1163 struct krt_config
*d
= (struct krt_config
*) dest
;
1164 struct krt_config
*s
= (struct krt_config
*) src
;
1166 /* Shallow copy of everything */
1167 proto_copy_rest(dest
, src
, sizeof(struct krt_config
));
1169 /* Fix sysdep parts */
1170 krt_sys_copy_config(d
, s
);
1174 krt_get_attr(eattr
* a
, byte
* buf
, int buflen UNUSED
)
1179 bsprintf(buf
, "source");
1183 bsprintf(buf
, "metric");
1186 case EA_KRT_PREFSRC
:
1187 bsprintf(buf
, "prefsrc");
1191 bsprintf(buf
, "realm");
1200 struct protocol proto_unix_kernel
= {
1202 .template = "kernel%d",
1203 .attr_class
= EAP_KRT
,
1204 .preference
= DEF_PREF_INHERITED
,
1205 .preconfig
= krt_preconfig
,
1206 .postconfig
= krt_postconfig
,
1209 .shutdown
= krt_shutdown
,
1210 .reconfigure
= krt_reconfigure
,
1211 .copy_config
= krt_copy_config
,
1212 .get_attr
= krt_get_attr
,
1213 #ifdef KRT_ALLOW_LEARN
1215 .dump_attrs
= krt_dump_attrs
,