summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--doc/bird.conf.example9
-rw-r--r--nest/config.Y20
-rw-r--r--nest/rt-dev.c20
-rw-r--r--sysdep/linux/netlink/krt-iface.h7
-rw-r--r--sysdep/linux/netlink/netlink.c2
-rw-r--r--sysdep/unix/io.c1
-rw-r--r--sysdep/unix/krt-iface.c24
-rw-r--r--sysdep/unix/krt.Y45
-rw-r--r--sysdep/unix/krt.c138
-rw-r--r--sysdep/unix/krt.h32
-rw-r--r--sysdep/unix/main.c1
-rw-r--r--sysdep/unix/unix.h4
13 files changed, 209 insertions, 96 deletions
diff --git a/TODO b/TODO
index 1544345..7fc453d 100644
--- a/TODO
+++ b/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?
diff --git a/doc/bird.conf.example b/doc/bird.conf.example
index 1d8203d..d91a792 100644
--- a/doc/bird.conf.example
+++ b/doc/bird.conf.example
@@ -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
diff --git a/nest/config.Y b/nest/config.Y
index 8300132..61a12ca 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -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);
}
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index fcaabd8..c122b96 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -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,
};
diff --git a/sysdep/linux/netlink/krt-iface.h b/sysdep/linux/netlink/krt-iface.h
index 5dfb934..53167c8 100644
--- a/sysdep/linux/netlink/krt-iface.h
+++ b/sysdep/linux/netlink/krt-iface.h
@@ -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
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c
index 93eb4ad..57e1899 100644
--- a/sysdep/linux/netlink/netlink.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -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;
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 8427ba4..6e1952e 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -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);
}
diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c
index 3b665a4..6303558 100644
--- a/sysdep/unix/krt-iface.c
+++ b/sysdep/unix/krt-iface.c
@@ -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)
{
- 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)
+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)
+ die("Cannot create scanning socket: %m");
}
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 661e505..083df7d 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -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
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 9ad4237..8a3db3f 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -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,
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 02814c6..bde509c 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -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
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 45940fb..5f260ca 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -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();
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index 7b33871..2d26074 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -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