diff options
author | Martin Mares <mj@ucw.cz> | 1999-02-05 21:37:34 +0000 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 1999-02-05 21:37:34 +0000 |
commit | 31b3e1bbf5bc823ec5cf6d88931132f00e6c52b9 (patch) | |
tree | b3c3da837ca2079a222dfc99ab479bd040ba21ad /nest | |
parent | c4c63eecc37a744c53c23da89b1ba09b9640cb6e (diff) |
Implemented new configuration/reconfiguration interface and defined protocol
state machines. Full explanation will follow soon.
Diffstat (limited to 'nest')
-rw-r--r-- | nest/bird.h | 5 | ||||
-rw-r--r-- | nest/config.Y | 10 | ||||
-rw-r--r-- | nest/iface.c | 21 | ||||
-rw-r--r-- | nest/iface.h | 4 | ||||
-rw-r--r-- | nest/proto.c | 104 | ||||
-rw-r--r-- | nest/protocol.h | 128 | ||||
-rw-r--r-- | nest/rt-attr.c | 2 | ||||
-rw-r--r-- | nest/rt-dev.c | 46 | ||||
-rw-r--r-- | nest/rt-dev.h | 6 | ||||
-rw-r--r-- | nest/rt-table.c | 2 |
10 files changed, 213 insertions, 115 deletions
diff --git a/nest/bird.h b/nest/bird.h index b9c9192b..597e2050 100644 --- a/nest/bird.h +++ b/nest/bird.h @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Basic Declarations * - * (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. */ @@ -13,7 +13,4 @@ #include "lib/birdlib.h" #include "lib/ip.h" -extern u32 router_id; /* Our Router ID */ -extern u16 this_as; /* Our Autonomous System Number */ - #endif diff --git a/nest/config.Y b/nest/config.Y index 98436541..a19cce63 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -1,14 +1,14 @@ /* * BIRD -- Core 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. */ CF_HDR -static struct proto *this_proto; +static struct proto_config *this_proto; #include "nest/rt-dev.h" @@ -27,7 +27,7 @@ CF_GRAMMAR CF_ADDTO(conf, rtrid) rtrid: ROUTER ID idval { - router_id = $3; + new_config->router_id = $3; } ; @@ -87,7 +87,7 @@ dev_proto: dev_iface_list: INTERFACE TEXT { - init_list(&((struct rt_dev_proto *) this_proto)->iface_list); + init_list(&((struct rt_dev_config *) this_proto)->iface_list); rt_dev_add_iface($2); } | dev_iface_list ',' TEXT { rt_dev_add_iface($3); } @@ -98,7 +98,7 @@ CF_CODE void rt_dev_add_iface(char *n) { - struct rt_dev_proto *p = (void *) this_proto; + struct rt_dev_config *p = (void *) this_proto; struct iface_patt *k = cfg_alloc(sizeof(struct iface_patt)); k->pattern = cfg_strdup(n); diff --git a/nest/iface.c b/nest/iface.c index ce638d22..2b2af915 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -1,7 +1,7 @@ /* * BIRD -- Management of Interfaces and Neighbor Cache * - * (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. */ @@ -16,8 +16,6 @@ static pool *if_pool; -u32 router_id; - /* * Neighbor Cache * @@ -103,7 +101,7 @@ neigh_dump(neighbor *n) debug("%s ", n->iface->name); else debug("[] "); - debug("%s %p", n->proto->name, n->data); + debug("%s %p", n->proto->cf->name, n->data); if (n->flags & NEF_STICKY) debug(" STICKY"); debug("\n"); @@ -199,7 +197,6 @@ if_dump_all(void) debug("Known network interfaces:\n"); WALK_LIST(i, iface_list) if_dump(i); - debug("\nRouter ID: %08x\n\n", router_id); } static inline int @@ -322,28 +319,26 @@ if_feed_baby(struct proto *p) if (!p->if_notify) return; - debug("Announcing interfaces to new protocol %s\n", p->name); + debug("Announcing interfaces to new protocol %s\n", p->cf->name); WALK_LIST(i, iface_list) p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), NULL, i); } -void +u32 auto_router_id(void) /* FIXME: What if we run IPv6??? */ { struct iface *i, *j; - if (router_id) - return; j = NULL; WALK_LIST(i, iface_list) if ((i->flags & IF_UP) && !(i->flags & (IF_UNNUMBERED | IF_LOOPBACK | IF_IGNORE)) && (!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip))) j = i; - if (!j) /* FIXME: allow configuration or running without RID */ - bug("Cannot determine router ID, please configure manually"); - router_id = ipa_to_u32(j->ip); - debug("Router ID set to %08x (%s)\n", router_id, j->name); + if (!j) + return 0; + debug("Guessed router ID %I (%s)\n", j->ip, j->name); + return ipa_to_u32(j->ip); } void diff --git a/nest/iface.h b/nest/iface.h index a7f90a6e..fd72bf41 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Network Interfaces * - * (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. */ @@ -54,7 +54,7 @@ void if_dump_all(void); void if_update(struct iface *); void if_end_update(void); void if_feed_baby(struct proto *); -void auto_router_id(void); +u32 auto_router_id(void); /* * Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen diff --git a/nest/proto.c b/nest/proto.c index cb3113fd..976a967b 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -1,7 +1,7 @@ /* * BIRD -- Protocols * - * (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. */ @@ -23,47 +23,83 @@ list proto_list; list inactive_proto_list; void * -proto_new(struct protocol *pr, unsigned size) +proto_new(struct proto_config *c, unsigned size) { - struct proto *p = cfg_allocz(size); + struct protocol *pr = c->proto; + struct proto *p = cfg_allocz(size); /* FIXME: Allocate from global pool */ - debug("proto_new(%s)\n", pr->name); + p->cf = c; + p->debug = c->debug; + p->preference = c->preference; + p->disabled = c->disabled; p->proto = pr; - p->name = pr->name; - p->debug = pr->debug; - p->pool = rp_new(&root_pool, pr->name); - add_tail(&inactive_proto_list, &p->n); + p->pool = rp_new(&root_pool, c->name); return p; } +void * +proto_config_new(struct protocol *pr, unsigned size) +{ + struct proto_config *c = cfg_allocz(size); + + add_tail(&new_config->protos, &c->n); + c->global = new_config; + c->proto = pr; + c->debug = pr->debug; + c->name = pr->name; + return c; +} + void -protos_preconfig(void) +protos_preconfig(struct config *c) { struct protocol *p; init_list(&proto_list); init_list(&inactive_proto_list); - debug("Protocol preconfig\n"); + debug("Protocol preconfig:"); WALK_LIST(p, protocol_list) { - debug("...%s\n", p->name); + debug(" %s", p->name); if (p->preconfig) - p->preconfig(p); + p->preconfig(p, c); } + debug("\n"); } void -protos_postconfig(void) +protos_postconfig(struct config *c) { + struct proto_config *x; struct protocol *p; - debug("Protocol postconfig\n"); - WALK_LIST(p, protocol_list) + debug("Protocol postconfig:"); + WALK_LIST(x, c->protos) { - debug("...%s\n", p->name); + debug(" %s", x->name); + p = x->proto; if (p->postconfig) - p->postconfig(p); + p->postconfig(x); + } + debug("\n"); +} + +void +protos_commit(struct config *c) +{ + struct proto_config *x; + struct protocol *p; + struct proto *q; + + debug("Protocol commit:"); + WALK_LIST(x, c->protos) + { + debug(" %s", x->name); + p = x->proto; + q = p->init(x); + add_tail(&inactive_proto_list, &q->n); } + debug("\n"); } static void @@ -72,12 +108,15 @@ proto_start(struct proto *p) rem_node(&p->n); if (p->disabled) return; - p->state = PRS_STARTING; - if (p->start) - p->start(p); + p->proto_state = PS_DOWN; + p->core_state = FS_HUNGRY; + if (p->proto->start && p->proto->start(p) != PS_UP) + bug("Delayed protocol start not supported yet"); + p->proto_state = PS_UP; + p->core_state = FS_FEEDING; if_feed_baby(p); rt_feed_baby(p); - p->state = PRS_UP; + p->core_state = FS_HAPPY; add_tail(&proto_list, &p->n); } @@ -89,7 +128,7 @@ protos_start(void) debug("Protocol start\n"); WALK_LIST_DELSAFE(p, n, inactive_proto_list) { - debug("...%s\n", p->name); + debug("Starting %s\n", p->cf->name); proto_start(p); } } @@ -98,19 +137,21 @@ void protos_dump_all(void) { struct proto *p; + static char *p_states[] = { "DOWN", "START", "UP", "STOP" }; + static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" }; debug("Protocols:\n"); WALK_LIST(p, proto_list) { - debug(" protocol %s:\n", p->name); + debug(" protocol %s: state %s/%s\n", p->cf->name, p_states[p->proto_state], c_states[p->core_state]); if (p->disabled) debug("\tDISABLED\n"); - else if (p->dump) - p->dump(p); + else if (p->proto->dump) + p->proto->dump(p); } WALK_LIST(p, inactive_proto_list) - debug(" inactive %s\n", p->name); + debug(" inactive %s\n", p->cf->name); } void @@ -125,14 +166,3 @@ protos_build(void) add_tail(&protocol_list, &proto_static.n); #endif } - -void -protos_init(void) -{ - struct protocol *p; - - debug("Initializing protocols\n"); - WALK_LIST(p, protocol_list) - if (p->init) - p->init(p); -} diff --git a/nest/protocol.h b/nest/protocol.h index f516f0f2..c9720608 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Protocols * - * (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. */ @@ -17,6 +17,9 @@ struct rte; struct neighbor; struct rtattr; struct network; +struct proto_config; +struct config; +struct proto; /* * Routing Protocol @@ -27,15 +30,19 @@ struct protocol { char *name; unsigned debug; /* Default debugging flags */ - void (*init)(struct protocol *); /* Boot time */ - void (*preconfig)(struct protocol *); /* Just before configuring */ - void (*postconfig)(struct protocol *); /* After configuring */ + void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ + void (*postconfig)(struct proto_config *); /* After configuring each instance */ + struct proto * (*init)(struct proto_config *); /* Create new instance */ + int (*reconfigure)(struct proto *, struct proto_config *); /* Try to reconfigure instance */ + void (*dump)(struct proto *); /* Debugging dump */ + int (*start)(struct proto *); /* Start the instance */ + int (*shutdown)(struct proto *); /* Stop the instance */ }; void protos_build(void); -void protos_init(void); -void protos_preconfig(void); -void protos_postconfig(void); +void protos_preconfig(struct config *); +void protos_postconfig(struct config *); +void protos_commit(struct config *); void protos_start(void); void protos_dump_all(void); @@ -53,47 +60,128 @@ extern struct protocol proto_static; * Routing Protocol Instance */ +struct proto_config { + node n; + struct config *global; /* Global configuration data */ + struct protocol *proto; /* Protocol */ + char *name; + unsigned debug, preference, disabled; /* Generic parameters */ + + /* Protocol-specific data follow... */ +}; + struct proto { node n; struct protocol *proto; /* Protocol */ - char *name; /* Name of this instance */ + struct proto_config *cf; /* Configuration data */ + pool *pool; /* Pool containing local objects */ + unsigned debug; /* Debugging flags */ - pool *pool; /* Local objects */ unsigned preference; /* Default route preference */ - unsigned state; /* PRS_... */ unsigned disabled; /* Manually disabled */ + unsigned proto_state; /* Protocol state machine (see below) */ + unsigned core_state; /* Core state machine (see below) */ void (*if_notify)(struct proto *, unsigned flags, struct iface *new, struct iface *old); void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old); void (*neigh_notify)(struct neighbor *neigh); - void (*dump)(struct proto *); /* Debugging dump */ - void (*start)(struct proto *); /* Start the instance */ - void (*shutdown)(struct proto *, int time); /* Stop the instance */ int (*rta_same)(struct rtattr *, struct rtattr *); int (*rte_better)(struct rte *, struct rte *); void (*rte_insert)(struct network *, struct rte *); void (*rte_remove)(struct network *, struct rte *); - /* Reconfigure function? */ /* Input/output filters */ /* Connection to routing tables? */ /* Hic sunt protocol-specific data */ }; -#define PRS_DOWN 0 /* Inactive */ -#define PRS_STARTING 1 -#define PRS_UP 2 - -void *proto_new(struct protocol *, unsigned size); +void proto_build(struct proto_config *); +void *proto_new(struct proto_config *, unsigned size); +void *proto_config_new(struct protocol *, unsigned size); extern list proto_list, inactive_proto_list; /* + * Each protocol instance runs two different state machines: + * + * [P] The protocol machine: (implemented inside protocol) + * + * DOWN ----> START + * ^ | + * | V + * STOP <---- UP + * + * States: DOWN Protocol is down and it's waiting for the core + * requesting protocol start. + * START Protocol is waiting for connection with the rest + * of the network and it's not willing to accept + * packets. When it connects, it goes to UP state. + * UP Protocol is up and running. When the network + * connection breaks down or the core requests + * protocol to be terminated, it goes to STOP state. + * STOP Protocol is disconnecting from the network. + * After it disconnects, it returns to DOWN state. + * + * In: start() Called in DOWN state to request protocol startup. + * Returns new state: either UP or START (in this + * case, the protocol will notify the core when it + * finally comes UP). + * stop() Called in START, UP or STOP state to request + * protocol shutdown. Returns new state: either + * DOWN or STOP (in this case, the protocol will + * notify the core when it finally comes DOWN). + * + * Out: proto_notify_state() -- called by protocol instance when + * it does any state transition not covered by + * return values of start() and stop(). This includes + * START->UP (delayed protocol startup), UP->STOP + * (spontaneous shutdown) and STOP->DOWN (delayed + * shutdown). + */ + +#define PS_DOWN 0 +#define PS_START 1 +#define PS_UP 2 +#define PS_STOP 3 + +void proto_notify_state(struct proto *p, unsigned state); + +/* + * [F] The feeder machine: (implemented in core routines) + * + * HUNGRY ----> FEEDING + * ^ | + * | V + * FLUSHING <---- HAPPY + * + * States: HUNGRY Protocol either administratively down (i.e., + * disabled by the user) or temporarily down + * (i.e., [P] is not UP) + * FEEDING The protocol came up and we're feeding it + * initial routes. [P] is UP. + * HAPPY The protocol is up and it's receiving normal + * routing updates. [P] is UP. + * FLUSHING The protocol is down and we're removing its + * routes from the table. [P] is STOP or DOWN. + * + * Normal lifecycle of a protocol looks like: + * + * HUNGRY/DOWN --> HUNGRY/START --> HUNGRY/UP --> + * FEEDING/UP --> HAPPY/UP --> FLUSHING/STOP|DOWN --> + * HUNGRY/STOP|DOWN --> HUNGRY/DOWN + */ + +#define FS_HUNGRY 0 +#define FS_FEEDING 1 +#define FS_HAPPY 2 +#define FS_FLUSHING 3 + +/* * Known unique protocol instances as referenced by config routines */ -extern struct proto *cf_dev_proto; +extern struct proto_config *cf_dev_proto; #endif diff --git a/nest/rt-attr.c b/nest/rt-attr.c index aa4a59ad..129ec0ce 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -139,7 +139,7 @@ rta_dump(rta *a) static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; debug("p=%s uc=%d %s %s%s%s TOS=%d", - a->proto->name, a->uc, rts[a->source], sco[a->scope], rtc[a->cast], + a->proto->cf->name, a->uc, rts[a->source], sco[a->scope], rtc[a->cast], rtd[a->dest], a->tos); if (a->flags & RTF_EXTERIOR) debug(" EXT"); diff --git a/nest/rt-dev.c b/nest/rt-dev.c index e7d43fb1..b6e8d708 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -1,7 +1,7 @@ /* * BIRD -- Direct Device Routes * - * (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. */ @@ -18,12 +18,12 @@ #include "conf/conf.h" #include "lib/resource.h" -struct proto *cf_dev_proto; +struct proto_config *cf_dev_proto; static void dev_if_notify(struct proto *p, unsigned c, struct iface *old, struct iface *new) { - struct rt_dev_proto *P = (void *) p; + struct rt_dev_config *P = (void *) p->cf; if (old && !iface_patt_match(&P->iface_list, old) || new && !iface_patt_match(&P->iface_list, new)) @@ -68,42 +68,30 @@ dev_if_notify(struct proto *p, unsigned c, struct iface *old, struct iface *new) } } -static void -dev_start(struct proto *p) +static struct proto * +dev_init(struct proto_config *c) { -} + struct proto *p = proto_new(c, sizeof(struct proto)); -static void -dev_init(struct protocol *p) -{ + p->if_notify = dev_if_notify; + return p; } static void -dev_preconfig(struct protocol *x) +dev_preconfig(struct protocol *x, struct config *c) { - struct rt_dev_proto *P = proto_new(&proto_device, sizeof(struct rt_dev_proto)); - struct proto *p = &P->p; + 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; - p->preference = DEF_PREF_DIRECT; - p->start = dev_start; - p->if_notify = dev_if_notify; - init_list(&P->iface_list); + 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); -} - -static void -dev_postconfig(struct protocol *p) -{ + add_tail(&p->iface_list, &k->n); } struct protocol proto_device = { - { NULL, NULL }, - "Device", - 0, - dev_init, - dev_preconfig, - dev_postconfig + name: "Device", + preconfig: dev_preconfig, + init: dev_init, }; diff --git a/nest/rt-dev.h b/nest/rt-dev.h index 05a7f4c6..64f2cd95 100644 --- a/nest/rt-dev.h +++ b/nest/rt-dev.h @@ -1,7 +1,7 @@ /* * BIRD -- Direct Device Routes * - * (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. */ @@ -9,8 +9,8 @@ #ifndef _BIRD_RT_DEV_H_ #define _BIRD_RT_DEV_H_ -struct rt_dev_proto { - struct proto p; +struct rt_dev_config { + struct proto_config c; list iface_list; }; diff --git a/nest/rt-table.c b/nest/rt-table.c index 0ccb8da6..916f887d 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -121,7 +121,7 @@ rt_feed_baby(struct proto *p) if (!p->rt_notify) return; - debug("Announcing routes to new protocol %s\n", p->name); + debug("Announcing routes to new protocol %s\n", p->cf->name); while (t) { FIB_WALK(&t->fib, fn) |