Moved to a much more systematic way of configuring kernel protocols.
o Nothing is configured automatically. You _need_ to specify the kernel syncer in config file in order to get it started. o Syncing has been split to route syncer (protocol "Kernel") and interface syncer (protocol "Device"), device routes are generated by protocol "Direct" (now can exist in multiple instances, so that it will be possible to feed different device routes to different routing tables once multiple tables get supported). See doc/bird.conf.example for a living example of these shiny features.
This commit is contained in:
parent
739ebd8e82
commit
7e5f5ffdda
13 changed files with 212 additions and 99 deletions
2
TODO
2
TODO
|
@ -6,6 +6,8 @@ Core
|
|||
- config: define ipaddr constants?
|
||||
- config: better default protocol names
|
||||
|
||||
- do we really need preconfig?
|
||||
|
||||
- counters (according to SNMP MIB?)
|
||||
- better memory allocators
|
||||
- default preferences of protocols: prefer BGP over OSPF/RIP external routes?
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
# debug all
|
||||
#}
|
||||
|
||||
protocol device {
|
||||
protocol direct {
|
||||
# disabled
|
||||
# interface "-eth*", "*"
|
||||
}
|
||||
|
@ -25,13 +25,16 @@ protocol kernel {
|
|||
# disabled
|
||||
# learn # Learn all routes from the kernel
|
||||
persist # Don't remove routes on bird shutdown
|
||||
scan time 10 # Scan kernel tables every 10 seconds
|
||||
route scan time 20 # But routes only every 20 seconds
|
||||
scan time 20 # Scan kernel routing table every 20 seconds
|
||||
# async off # Netlink: Disable asynchronous events
|
||||
# input filter sink
|
||||
# output filter okay
|
||||
}
|
||||
|
||||
protocol device {
|
||||
scan time 10 # Scan interfaces every 10 seconds
|
||||
}
|
||||
|
||||
protocol static {
|
||||
# disabled
|
||||
# route 0.0.0.0/0 via 62.168.0.13
|
||||
|
|
|
@ -16,7 +16,7 @@ void rt_dev_add_iface(char *);
|
|||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DEVICE)
|
||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||
CF_KEYWORDS(INTERFACE, INPUT, OUTPUT, FILTER)
|
||||
|
||||
%type <i> idval
|
||||
|
@ -44,7 +44,7 @@ proto_start: PROTOCOL
|
|||
|
||||
proto_name:
|
||||
/* EMPTY */ {
|
||||
struct symbol *s = cf_default_name(this_proto->proto->name);
|
||||
struct symbol *s = cf_default_name(this_proto->proto->name, &this_proto->proto->name_counter);
|
||||
s->class = SYM_PROTO;
|
||||
s->def = this_proto;
|
||||
this_proto->name = s->name;
|
||||
|
@ -71,24 +71,30 @@ proto_item:
|
|||
| OUTPUT FILTER filter { this_proto->out_filter = $3; }
|
||||
;
|
||||
|
||||
/* Device protocol */
|
||||
/* Direct device route protocol */
|
||||
|
||||
CF_ADDTO(proto, dev_proto '}')
|
||||
|
||||
dev_proto_start: proto_start DEVICE {
|
||||
if (!(this_proto = cf_dev_proto)) cf_error("Device protocol already defined");
|
||||
cf_dev_proto = NULL;
|
||||
dev_proto_start: proto_start DIRECT {
|
||||
struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config));
|
||||
struct iface_patt *k = cfg_alloc(sizeof(struct iface_patt));
|
||||
this_proto = &p->c;
|
||||
p->c.preference = DEF_PREF_DIRECT;
|
||||
init_list(&p->iface_list);
|
||||
k->pattern = "*";
|
||||
add_tail(&p->iface_list, &k->n);
|
||||
}
|
||||
;
|
||||
|
||||
dev_proto:
|
||||
dev_proto_start '{'
|
||||
dev_proto_start proto_name '{'
|
||||
| dev_proto proto_item ';'
|
||||
| dev_proto dev_iface_list ';'
|
||||
;
|
||||
|
||||
dev_iface_list:
|
||||
INTERFACE TEXT {
|
||||
/* FIXME: Beware of obscure semantics. */
|
||||
init_list(&((struct rt_dev_config *) this_proto)->iface_list);
|
||||
rt_dev_add_iface($2);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#include "conf/conf.h"
|
||||
#include "lib/resource.h"
|
||||
|
||||
struct proto_config *cf_dev_proto;
|
||||
|
||||
static void
|
||||
dev_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
|
||||
{
|
||||
|
@ -77,22 +75,8 @@ dev_init(struct proto_config *c)
|
|||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
dev_preconfig(struct protocol *x, struct config *c)
|
||||
{
|
||||
struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config));
|
||||
struct iface_patt *k = cfg_alloc(sizeof(struct iface_patt));
|
||||
|
||||
cf_dev_proto = &p->c;
|
||||
p->c.preference = DEF_PREF_DIRECT;
|
||||
init_list(&p->iface_list);
|
||||
k->pattern = "*";
|
||||
add_tail(&p->iface_list, &k->n);
|
||||
}
|
||||
|
||||
struct protocol proto_device = {
|
||||
name: "Device",
|
||||
priority: 100,
|
||||
preconfig: dev_preconfig,
|
||||
name: "Direct",
|
||||
priority: 90,
|
||||
init: dev_init,
|
||||
};
|
||||
|
|
|
@ -19,8 +19,9 @@ struct krt_if_params {
|
|||
struct krt_if_status {
|
||||
};
|
||||
|
||||
static inline void krt_if_preconfig(struct krt_config *c) { };
|
||||
static inline void krt_if_start(struct krt_proto *p) { };
|
||||
static inline void krt_if_shutdown(struct krt_proto *p) { };
|
||||
static inline void krt_if_preconfig(struct kif_config *c) { };
|
||||
static inline void krt_if_start(struct kif_proto *p) { };
|
||||
static inline void krt_if_shutdown(struct kif_proto *p) { };
|
||||
static inline void krt_if_io_init(void) { };
|
||||
|
||||
#endif
|
||||
|
|
|
@ -392,7 +392,7 @@ nl_parse_addr(struct nlmsghdr *h)
|
|||
}
|
||||
|
||||
void
|
||||
krt_if_scan(struct krt_proto *p)
|
||||
krt_if_scan(struct kif_proto *p)
|
||||
{
|
||||
struct nlmsghdr *h;
|
||||
|
||||
|
|
|
@ -693,6 +693,7 @@ io_init(void)
|
|||
init_list(&far_timers);
|
||||
init_list(&sock_list);
|
||||
init_list(&global_event_list);
|
||||
krt_io_init();
|
||||
now = time(NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||
}
|
||||
|
||||
void
|
||||
krt_if_scan(struct krt_proto *p)
|
||||
krt_if_scan(struct kif_proto *p)
|
||||
{
|
||||
struct ifconf ic;
|
||||
static int last_ifbuf_size = 4*sizeof(struct ifreq);
|
||||
|
@ -172,23 +172,25 @@ krt_if_scan(struct krt_proto *p)
|
|||
}
|
||||
|
||||
void
|
||||
krt_if_preconfig(struct krt_config *c)
|
||||
krt_if_preconfig(struct kif_config *c)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
krt_if_start(struct krt_proto *p)
|
||||
krt_if_start(struct kif_proto *p)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
krt_if_shutdown(struct kif_proto *p)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
krt_if_io_init(void)
|
||||
{
|
||||
if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
|
||||
if (if_scan_sock < 0)
|
||||
{
|
||||
if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
|
||||
if (if_scan_sock < 0)
|
||||
die("Cannot create scanning socket: %m");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
krt_if_shutdown(struct krt_proto *p)
|
||||
{
|
||||
die("Cannot create scanning socket: %m");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* BIRD -- UNIX Kernel Syncer Configuration
|
||||
*
|
||||
* (c) 1998 Martin Mares <mj@ucw.cz>
|
||||
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
@ -11,24 +11,31 @@ CF_HDR
|
|||
#include "lib/krt.h"
|
||||
|
||||
#define THIS_KRT ((struct krt_config *) this_proto)
|
||||
#define THIS_KIF ((struct kif_config *) this_proto)
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, ROUTE, LEARN)
|
||||
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
/* Kernel protocol */
|
||||
/* Kernel syncer protocol */
|
||||
|
||||
CF_ADDTO(proto, kern_proto '}')
|
||||
|
||||
kern_proto_start: proto_start KERNEL {
|
||||
if (!(this_proto = cf_krt)) cf_error("Kernel protocol already defined");
|
||||
cf_krt = NULL;
|
||||
if (cf_krt)
|
||||
cf_error("Kernel protocol already defined");
|
||||
cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
|
||||
this_proto->preference = 0;
|
||||
THIS_KRT->scan_time = 60;
|
||||
THIS_KRT->learn = THIS_KRT->persist = 0;
|
||||
krt_scan_preconfig(THIS_KRT);
|
||||
krt_set_preconfig(THIS_KRT);
|
||||
}
|
||||
;
|
||||
|
||||
CF_ADDTO(kern_proto, kern_proto_start '{')
|
||||
CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
|
||||
CF_ADDTO(kern_proto, kern_proto proto_item ';')
|
||||
CF_ADDTO(kern_proto, kern_proto kern_item ';')
|
||||
|
||||
|
@ -38,10 +45,34 @@ kern_item:
|
|||
/* Scan time of 0 means scan on startup only */
|
||||
THIS_KRT->scan_time = $3;
|
||||
}
|
||||
| ROUTE SCAN TIME expr { THIS_KRT->route_scan_time = $4; }
|
||||
| LEARN bool { THIS_KRT->learn = $2; }
|
||||
;
|
||||
|
||||
/* Kernel interface protocol */
|
||||
|
||||
CF_ADDTO(proto, kif_proto '}')
|
||||
|
||||
kif_proto_start: proto_start DEVICE {
|
||||
if (cf_kif)
|
||||
cf_error("Kernel device protocol already defined");
|
||||
cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config));
|
||||
this_proto->preference = DEF_PREF_DIRECT;
|
||||
THIS_KIF->scan_time = 60;
|
||||
krt_if_preconfig(THIS_KIF);
|
||||
}
|
||||
;
|
||||
|
||||
CF_ADDTO(kif_proto, kif_proto_start '{')
|
||||
CF_ADDTO(kif_proto, kif_proto proto_item ';')
|
||||
CF_ADDTO(kif_proto, kif_proto kif_item ';')
|
||||
|
||||
kif_item:
|
||||
SCAN TIME expr {
|
||||
/* Scan time of 0 means scan on startup only */
|
||||
THIS_KIF->scan_time = $3;
|
||||
}
|
||||
;
|
||||
|
||||
CF_CODE
|
||||
|
||||
CF_END
|
||||
|
|
|
@ -17,7 +17,94 @@
|
|||
#include "unix.h"
|
||||
#include "krt.h"
|
||||
|
||||
struct proto_config *cf_krt;
|
||||
/*
|
||||
* Global resources
|
||||
*/
|
||||
|
||||
void
|
||||
krt_io_init(void)
|
||||
{
|
||||
krt_if_io_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Interfaces
|
||||
*/
|
||||
|
||||
struct proto_config *cf_kif;
|
||||
|
||||
static struct kif_proto *kif_proto;
|
||||
static timer *kif_scan_timer;
|
||||
static bird_clock_t kif_last_shot;
|
||||
|
||||
static void
|
||||
kif_scan(timer *t)
|
||||
{
|
||||
struct kif_proto *p = t->data;
|
||||
|
||||
DBG("KIF: It's interface scan time...\n");
|
||||
kif_last_shot = now;
|
||||
krt_if_scan(p);
|
||||
}
|
||||
|
||||
static void
|
||||
kif_force_scan(void)
|
||||
{
|
||||
if (kif_proto && kif_last_shot + 2 < now)
|
||||
{
|
||||
kif_scan(kif_scan_timer);
|
||||
tm_start(kif_scan_timer, ((struct kif_config *) kif_proto->p.cf)->scan_time);
|
||||
}
|
||||
}
|
||||
|
||||
static struct proto *
|
||||
kif_init(struct proto_config *c)
|
||||
{
|
||||
struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
|
||||
return &p->p;
|
||||
}
|
||||
|
||||
static int
|
||||
kif_start(struct proto *P)
|
||||
{
|
||||
struct kif_proto *p = (struct kif_proto *) P;
|
||||
|
||||
kif_proto = p;
|
||||
krt_if_start(p);
|
||||
|
||||
/* Start periodic interface scanning */
|
||||
kif_scan_timer = tm_new(P->pool);
|
||||
kif_scan_timer->hook = kif_scan;
|
||||
kif_scan_timer->data = p;
|
||||
kif_scan_timer->recurrent = KIF_CF->scan_time;
|
||||
kif_scan(kif_scan_timer);
|
||||
tm_start(kif_scan_timer, KIF_CF->scan_time);
|
||||
|
||||
return PS_UP;
|
||||
}
|
||||
|
||||
static int
|
||||
kif_shutdown(struct proto *P)
|
||||
{
|
||||
struct kif_proto *p = (struct kif_proto *) P;
|
||||
|
||||
tm_stop(kif_scan_timer);
|
||||
krt_if_shutdown(p);
|
||||
kif_proto = NULL;
|
||||
|
||||
if_start_update(); /* Remove all interfaces */
|
||||
if_end_update();
|
||||
|
||||
return PS_DOWN;
|
||||
}
|
||||
|
||||
struct protocol proto_unix_iface = {
|
||||
name: "Device",
|
||||
priority: 100,
|
||||
init: kif_init,
|
||||
start: kif_start,
|
||||
shutdown: kif_shutdown,
|
||||
};
|
||||
|
||||
/*
|
||||
* Routes
|
||||
|
@ -210,7 +297,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
|||
* FIXME: This is limited to one inherited route per destination as we
|
||||
* use single protocol for all inherited routes. Probably leave it
|
||||
* as-is (and document it :)), because the correct solution is to
|
||||
* multiple kernel tables anyway.
|
||||
* use multiple kernel tables anyway.
|
||||
*/
|
||||
DBG("Learning\n");
|
||||
rte_update(net, &p->p, e);
|
||||
|
@ -234,35 +321,27 @@ krt_scan(timer *t)
|
|||
{
|
||||
struct krt_proto *p = t->data;
|
||||
|
||||
DBG("KRT: It's scan time...\n");
|
||||
krt_if_scan(p);
|
||||
|
||||
p->accum_time += KRT_CF->scan_time;
|
||||
if (KRT_CF->route_scan_time && p->accum_time >= KRT_CF->route_scan_time)
|
||||
{
|
||||
p->accum_time %= KRT_CF->route_scan_time;
|
||||
DBG("Scanning kernel routing table...\n");
|
||||
krt_scan_fire(p);
|
||||
krt_prune(p);
|
||||
}
|
||||
kif_force_scan();
|
||||
DBG("KRT: It's route scan time...\n");
|
||||
krt_scan_fire(p);
|
||||
krt_prune(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Protocol glue
|
||||
*/
|
||||
|
||||
struct proto_config *cf_krt;
|
||||
|
||||
static int
|
||||
krt_start(struct proto *P)
|
||||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
||||
p->accum_time = KRT_CF->route_scan_time - KRT_CF->scan_time;
|
||||
|
||||
krt_if_start(p);
|
||||
krt_scan_start(p);
|
||||
krt_set_start(p);
|
||||
|
||||
/* Start periodic interface scanning */
|
||||
/* Start periodic routing table scanning */
|
||||
krt_scan_timer = tm_new(P->pool);
|
||||
krt_scan_timer->hook = krt_scan;
|
||||
krt_scan_timer->data = p;
|
||||
|
@ -278,35 +357,17 @@ krt_shutdown(struct proto *P)
|
|||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
||||
tm_stop(krt_scan_timer);
|
||||
|
||||
if (!KRT_CF->persist)
|
||||
krt_flush_routes(p);
|
||||
|
||||
krt_set_shutdown(p);
|
||||
krt_scan_shutdown(p);
|
||||
|
||||
/* Stop periodic interface scans */
|
||||
tm_stop(krt_scan_timer);
|
||||
krt_if_shutdown(p);
|
||||
/* FIXME: What should we do with interfaces? */
|
||||
|
||||
return PS_DOWN;
|
||||
}
|
||||
|
||||
static void
|
||||
krt_preconfig(struct protocol *x, struct config *c)
|
||||
{
|
||||
struct krt_config *z = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
|
||||
|
||||
cf_krt = &z->c;
|
||||
z->c.preference = DEF_PREF_UKR;
|
||||
z->scan_time = z->route_scan_time = 60;
|
||||
z->learn = z->persist = 0;
|
||||
|
||||
krt_scan_preconfig(z);
|
||||
krt_set_preconfig(z);
|
||||
krt_if_preconfig(z);
|
||||
}
|
||||
|
||||
static struct proto *
|
||||
krt_init(struct proto_config *c)
|
||||
{
|
||||
|
@ -318,8 +379,7 @@ krt_init(struct proto_config *c)
|
|||
|
||||
struct protocol proto_unix_kernel = {
|
||||
name: "Kernel",
|
||||
priority: 90,
|
||||
preconfig: krt_preconfig,
|
||||
priority: 80,
|
||||
init: krt_init,
|
||||
start: krt_start,
|
||||
shutdown: krt_shutdown,
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
struct krt_config;
|
||||
struct krt_proto;
|
||||
struct kif_config;
|
||||
struct kif_proto;
|
||||
|
||||
#include "lib/krt-scan.h"
|
||||
#include "lib/krt-set.h"
|
||||
|
@ -34,8 +36,7 @@ struct krt_config {
|
|||
struct krt_scan_params scan;
|
||||
struct krt_if_params iface;
|
||||
int persist; /* Keep routes when we exit */
|
||||
int scan_time; /* How often we re-scan interfaces */
|
||||
int route_scan_time; /* How often we re-scan routes */
|
||||
int scan_time; /* How often we re-scan routes */
|
||||
int learn; /* Learn routes from other sources */
|
||||
};
|
||||
|
||||
|
@ -44,7 +45,6 @@ struct krt_proto {
|
|||
struct krt_set_status set;
|
||||
struct krt_scan_status scan;
|
||||
struct krt_if_status iface;
|
||||
int accum_time; /* Accumulated route scanning time */
|
||||
};
|
||||
|
||||
extern struct proto_config *cf_krt;
|
||||
|
@ -60,6 +60,23 @@ void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
|
|||
#define KRT_SRC_REDIRECT 1 /* Redirect route, delete it */
|
||||
#define KRT_SRC_ALIEN 2 /* Route installed by someone else */
|
||||
|
||||
extern struct protocol proto_unix_iface;
|
||||
|
||||
struct kif_config {
|
||||
struct proto_config c;
|
||||
struct krt_if_params iface;
|
||||
int scan_time; /* How often we re-scan interfaces */
|
||||
};
|
||||
|
||||
struct kif_proto {
|
||||
struct proto p;
|
||||
struct krt_if_status iface;
|
||||
};
|
||||
|
||||
extern struct proto_config *cf_kif;
|
||||
|
||||
#define KIF_CF ((struct kif_config *)p->p.cf)
|
||||
|
||||
/* krt-scan.c */
|
||||
|
||||
void krt_scan_preconfig(struct krt_config *);
|
||||
|
@ -79,10 +96,11 @@ void krt_set_notify(struct proto *x, net *net, rte *new, rte *old);
|
|||
|
||||
/* krt-iface.c */
|
||||
|
||||
void krt_if_preconfig(struct krt_config *);
|
||||
void krt_if_start(struct krt_proto *);
|
||||
void krt_if_shutdown(struct krt_proto *);
|
||||
void krt_if_preconfig(struct kif_config *);
|
||||
void krt_if_start(struct kif_proto *);
|
||||
void krt_if_shutdown(struct kif_proto *);
|
||||
|
||||
void krt_if_scan(struct krt_proto *);
|
||||
void krt_if_scan(struct kif_proto *);
|
||||
void krt_if_io_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -205,6 +205,7 @@ main(int argc, char **argv)
|
|||
|
||||
protos_build();
|
||||
add_tail(&protocol_list, &proto_unix_kernel.n);
|
||||
add_tail(&protocol_list, &proto_unix_iface.n);
|
||||
|
||||
read_config();
|
||||
|
||||
|
|
|
@ -26,4 +26,8 @@ void io_loop(void);
|
|||
void fill_in_sockaddr(struct sockaddr_in *sa, ip_addr a, unsigned port);
|
||||
void get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port);
|
||||
|
||||
/* krt.c bits */
|
||||
|
||||
void krt_io_init(void);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue