summaryrefslogtreecommitdiff
path: root/proto/static
diff options
context:
space:
mode:
Diffstat (limited to 'proto/static')
-rw-r--r--proto/static/config.Y18
-rw-r--r--proto/static/static.c98
-rw-r--r--proto/static/static.h4
3 files changed, 77 insertions, 43 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y
index 182721b3..86359f0b 100644
--- a/proto/static/config.Y
+++ b/proto/static/config.Y
@@ -38,25 +38,25 @@ CF_GRAMMAR
CF_ADDTO(proto, static_proto '}')
-static_proto_start: proto_start STATIC {
- this_proto = proto_config_new(&proto_static, $1);
- static_init_config((struct static_config *) this_proto);
- }
- ;
+static_proto_start: proto_start STATIC
+{
+ this_proto = proto_config_new(&proto_static, $1);
+ static_init_config(STATIC_CFG);
+};
static_proto:
static_proto_start proto_name '{'
| static_proto proto_item ';'
+ | static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
| static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
;
-stat_route0: ROUTE prefix {
+stat_route0: ROUTE net_any {
this_srt = cfg_allocz(sizeof(struct static_route));
add_tail(&STATIC_CFG->other_routes, &this_srt->n);
- this_srt->net = $2.addr;
- this_srt->masklen = $2.len;
+ this_srt->net = $2;
this_srt_last_cmd = &(this_srt->cmds);
}
;
@@ -72,7 +72,7 @@ stat_multipath1:
this_srt_nh->use_bfd = -1; /* undefined */
}
| stat_multipath1 WEIGHT expr {
- this_srt_nh->masklen = $3 - 1; /* really */
+ this_srt_nh->weight = $3 - 1;
if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256");
}
| stat_multipath1 BFD bool {
diff --git a/proto/static/static.c b/proto/static/static.c
index be808593..6239fccb 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -26,7 +26,7 @@
* nodes (of dest RTD_NONE), which stores info about nexthops and are
* connected to neighbor entries and neighbor notifications. Dummy
* nodes are chained using mp_next, they aren't in other_routes list,
- * and abuse some fields (masklen, if_name) for other purposes.
+ * and abuse if_name field for other purposes.
*
* The only other thing worth mentioning is that when asked for reconfiguration,
* Static not only compares the two configurations, but it also calculates
@@ -54,7 +54,7 @@ static inline rtable *
p_igp_table(struct proto *p)
{
struct static_config *cf = (void *) p->cf;
- return cf->igp_table ? cf->igp_table->table : p->table;
+ return cf->igp_table ? cf->igp_table->table : p->main_channel->table;
}
static void
@@ -67,7 +67,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
if (r->installed > 0)
return;
- DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
+ DBG("Installing static route %N, rtd=%d\n", r->net, r->dest);
bzero(&a, sizeof(a));
a.src = p->main_source;
a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
@@ -89,7 +89,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
struct mpnh *nh = alloca(sizeof(struct mpnh));
nh->gw = r2->via;
nh->iface = r2->neigh->iface;
- nh->weight = r2->masklen; /* really */
+ nh->weight = r2->weight;
nh->next = NULL;
*nhp = nh;
nhp = &(nh->next);
@@ -108,11 +108,11 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
}
if (r->dest == RTDX_RECURSIVE)
- rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
+ rta_set_recursive_next_hop(p->main_channel->table, &a, p_igp_table(p), &r->via, &r->via);
/* We skip rta_lookup() here */
- n = net_get(p->table, r->net, r->masklen);
+ n = net_get(p->main_channel->table, r->net);
e = rte_get_temp(&a);
e->net = n;
e->pflags = 0;
@@ -135,8 +135,8 @@ static_remove(struct proto *p, struct static_route *r)
if (!r->installed)
return;
- DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via);
- n = net_find(p->table, r->net, r->masklen);
+ DBG("Removing static route %N via %I\n", r->net, r->via);
+ n = net_find(p->main_channel->table, r->net);
rte_update(p, n, NULL);
r->installed = 0;
}
@@ -186,7 +186,7 @@ static_decide(struct static_config *cf, struct static_route *r)
static void
static_add(struct proto *p, struct static_config *cf, struct static_route *r)
{
- DBG("static_add(%I/%d,%d)\n", r->net, r->masklen, r->dest);
+ DBG("static_add(%N,%d)\n", r->net, r->dest);
switch (r->dest)
{
case RTD_ROUTER:
@@ -309,6 +309,17 @@ static_shutdown(struct proto *p)
r->installed = 0;
}
+ /* Handle failure during channel reconfigure */
+ /* FIXME: This should be handled in a better way */
+ cf = (void *) p->cf_new;
+ if (cf)
+ {
+ WALK_LIST(r, cf->iface_routes)
+ r->installed = 0;
+ WALK_LIST(r, cf->other_routes)
+ r->installed = 0;
+ }
+
return PS_DOWN;
}
@@ -388,7 +399,7 @@ static_bfd_notify(struct bfd_request *req)
static void
static_dump_rt(struct static_route *r)
{
- debug("%-1I/%2d: ", r->net, r->masklen);
+ debug("%-1N: ", r->net);
switch (r->dest)
{
case RTD_ROUTER:
@@ -450,22 +461,40 @@ static_init_config(struct static_config *c)
init_list(&c->other_routes);
}
-static struct proto *
-static_init(struct proto_config *c)
+static void
+static_postconfig(struct proto_config *CF)
{
- struct proto *p = proto_new(c, sizeof(struct proto));
+ struct static_config *cf = (void *) CF;
+ struct static_route *r;
+
+ if (EMPTY_LIST(CF->channels))
+ cf_error("Channel not specified");
- p->neigh_notify = static_neigh_notify;
- p->if_notify = static_if_notify;
- p->rte_mergable = static_rte_mergable;
- return p;
+ WALK_LIST(r, cf->iface_routes)
+ if (r->net->type != CF->net_type)
+ cf_error("Route %N incompatible with channel type", r->net);
+
+ WALK_LIST(r, cf->other_routes)
+ if (r->net->type != CF->net_type)
+ cf_error("Route %N incompatible with channel type", r->net);
}
-static inline int
-static_same_net(struct static_route *x, struct static_route *y)
+
+static struct proto *
+static_init(struct proto_config *CF)
{
- return ipa_equal(x->net, y->net) && (x->masklen == y->masklen);
+ struct proto *P = proto_new(CF);
+ // struct static_proto *p = (void *) P;
+ // struct static_config *cf = (void *) CF;
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
+
+ P->neigh_notify = static_neigh_notify;
+ P->if_notify = static_if_notify;
+ P->rte_mergable = static_rte_mergable;
+
+ return P;
}
static inline int
@@ -486,7 +515,10 @@ static_same_dest(struct static_route *x, struct static_route *y)
for (x = x->mp_next, y = y->mp_next;
x && y;
x = x->mp_next, y = y->mp_next)
- if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if) || (x->use_bfd != y->use_bfd))
+ if (!ipa_equal(x->via, y->via) ||
+ (x->via_if != y->via_if) ||
+ (x->use_bfd != y->use_bfd) ||
+ (x->weight != y->weight))
return 0;
return !x && !y;
@@ -521,11 +553,11 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n)
r->neigh->data = NULL;
WALK_LIST(t, n->iface_routes)
- if (static_same_net(r, t))
+ if (net_equal(r->net, t->net))
goto found;
WALK_LIST(t, n->other_routes)
- if (static_same_net(r, t))
+ if (net_equal(r->net, t->net))
goto found;
static_remove(p, r);
@@ -546,15 +578,18 @@ cf_igp_table(struct static_config *cf)
}
static int
-static_reconfigure(struct proto *p, struct proto_config *new)
+static_reconfigure(struct proto *p, struct proto_config *CF)
{
struct static_config *o = (void *) p->cf;
- struct static_config *n = (void *) new;
+ struct static_config *n = (void *) CF;
struct static_route *r;
if (cf_igp_table(o) != cf_igp_table(n))
return 0;
+ if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
/* Delete all obsolete routes and reset neighbor entries */
WALK_LIST(r, o->iface_routes)
static_match(p, r, n);
@@ -620,20 +655,19 @@ static_copy_config(struct proto_config *dest, struct proto_config *src)
struct static_config *d = (struct static_config *) dest;
struct static_config *s = (struct static_config *) src;
- /* Shallow copy of everything */
- proto_copy_rest(dest, src, sizeof(struct static_config));
-
/* Copy route lists */
static_copy_routes(&d->iface_routes, &s->iface_routes);
static_copy_routes(&d->other_routes, &s->other_routes);
}
-
struct protocol proto_static = {
.name = "Static",
.template = "static%d",
.preference = DEF_PREF_STATIC,
+ .channel_mask = NB_ANY,
+ .proto_size = sizeof(struct proto),
.config_size = sizeof(struct static_config),
+ .postconfig = static_postconfig,
.init = static_init,
.dump = static_dump,
.start = static_start,
@@ -646,7 +680,7 @@ struct protocol proto_static = {
static void
static_show_rt(struct static_route *r)
{
- byte via[STD_ADDRESS_P_LENGTH + 16];
+ byte via[IPA_MAX_TEXT_LENGTH + 25];
switch (r->dest)
{
@@ -659,13 +693,13 @@ static_show_rt(struct static_route *r)
case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
default: bsprintf(via, "???");
}
- cli_msg(-1009, "%I/%d %s%s%s", r->net, r->masklen, via,
+ cli_msg(-1009, "%N %s%s%s", r->net, via,
r->bfd_req ? " (bfd)" : "", r->installed ? "" : " (dormant)");
struct static_route *r2;
if (r->dest == RTD_MULTIPATH)
for (r2 = r->mp_next; r2; r2 = r2->mp_next)
- cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
+ cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->weight + 1,
r2->bfd_req ? " (bfd)" : "", r2->installed ? "" : " (dormant)");
}
diff --git a/proto/static/static.h b/proto/static/static.h
index 6b047234..51486e83 100644
--- a/proto/static/static.h
+++ b/proto/static/static.h
@@ -26,8 +26,7 @@ void static_init_config(struct static_config *);
struct static_route {
node n;
struct static_route *chain; /* Next for the same neighbor */
- ip_addr net; /* Network we route */
- int masklen; /* Mask length */
+ net_addr *net; /* Network we route */
int dest; /* Destination type (RTD_*) */
ip_addr via; /* Destination router */
struct iface *via_if; /* Destination iface, for link-local vias */
@@ -37,6 +36,7 @@ struct static_route {
struct f_inst *cmds; /* List of commands for setting attributes */
int installed; /* Installed in rt table, -1 for reinstall */
int use_bfd; /* Configured to use BFD */
+ int weight; /* Multipath next hop weight */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
};