summaryrefslogtreecommitdiff
path: root/proto/babel
diff options
context:
space:
mode:
Diffstat (limited to 'proto/babel')
-rw-r--r--proto/babel/babel.c195
-rw-r--r--proto/babel/babel.h6
-rw-r--r--proto/babel/config.Y4
3 files changed, 106 insertions, 99 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 23cb6774..685bb122 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -37,6 +37,7 @@
#include <stdlib.h>
#include "babel.h"
+#include "lib/macro.h"
#define LOG_PKT_AUTH(msg, args...) \
log_rl(&p->log_pkt_tbf, L_AUTH "%s: " msg, p->p.name, args)
@@ -58,6 +59,8 @@ static void babel_update_cost(struct babel_neighbor *n);
static inline void babel_kick_timer(struct babel_proto *p);
static inline void babel_iface_kick_timer(struct babel_iface *ifa);
+static struct ea_class ea_babel_metric, ea_babel_router_id, ea_babel_seqno;
+
/*
* Functions to maintain data structures
*/
@@ -656,37 +659,14 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
if (r)
{
- rta a0 = {
- .source = RTS_BABEL,
- .scope = SCOPE_UNIVERSE,
- .dest = RTD_UNICAST,
- .pref = c->preference,
- .from = r->neigh->addr,
- .nh.gw = r->next_hop,
- .nh.iface = r->neigh->ifa->iface,
- .eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr)),
- };
-
- *a0.eattrs = (ea_list) { .count = 3 };
- a0.eattrs->attrs[0] = (eattr) {
- .id = EA_BABEL_METRIC,
- .type = EAF_TYPE_INT,
- .u.data = r->metric,
- };
-
- struct adata *ad = alloca(sizeof(struct adata) + sizeof(u64));
- ad->length = sizeof(u64);
- memcpy(ad->data, &(r->router_id), sizeof(u64));
- a0.eattrs->attrs[1] = (eattr) {
- .id = EA_BABEL_ROUTER_ID,
- .type = EAF_TYPE_OPAQUE,
- .u.ptr = ad,
- };
-
- a0.eattrs->attrs[2] = (eattr) {
- .id = EA_BABEL_SEQNO,
- .type = EAF_TYPE_INT,
- .u.data = r->seqno,
+ struct nexthop_adata nhad = {
+ .nh = {
+ .gw = r->next_hop,
+ .iface = r->neigh->ifa->iface,
+ },
+ .ad = {
+ .length = sizeof nhad - sizeof nhad.ad,
+ },
};
/*
@@ -695,36 +675,54 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
* have routing work.
*/
if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0))
- a0.nh.flags = RNF_ONLINK;
+ nhad.nh.flags = RNF_ONLINK;
+
+ struct {
+ ea_list l;
+ eattr a[7];
+ } eattrs = {
+ .l.count = ARRAY_SIZE(eattrs.a),
+ .a = {
+ EA_LITERAL_EMBEDDED(&ea_gen_preference, 0, c->preference),
+ EA_LITERAL_STORE_ADATA(&ea_gen_from, 0, &r->neigh->addr, sizeof(r->neigh->addr)),
+ EA_LITERAL_EMBEDDED(&ea_gen_source, 0, RTS_BABEL),
+ EA_LITERAL_STORE_ADATA(&ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length),
+ EA_LITERAL_EMBEDDED(&ea_babel_metric, 0, r->metric),
+ EA_LITERAL_STORE_ADATA(&ea_babel_router_id, 0, &r->router_id, sizeof(r->router_id)),
+ EA_LITERAL_EMBEDDED(&ea_babel_seqno, 0, r->seqno),
+ }
+ };
- rta *a = rta_lookup(&a0);
- rte *rte = rte_get_temp(a, p->p.main_source);
+ rte e0 = {
+ .attrs = &eattrs.l,
+ .src = p->p.main_source,
+ };
e->unreachable = 0;
- rte_update2(c, e->n.addr, rte, p->p.main_source);
+ rte_update(c, e->n.addr, &e0, p->p.main_source);
}
else if (e->valid && (e->router_id != p->router_id))
{
/* Unreachable */
- rta a0 = {
- .source = RTS_BABEL,
- .scope = SCOPE_UNIVERSE,
- .dest = RTD_UNREACHABLE,
- .pref = 1,
- };
+ ea_list *ea = NULL;
- rta *a = rta_lookup(&a0);
- rte *rte = rte_get_temp(a, p->p.main_source);
- rte->pflags = 0;
+ ea_set_attr_u32(&ea, &ea_gen_preference, 0, 1);
+ ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_BABEL);
+ ea_set_dest(&ea, 0, RTD_UNREACHABLE);
+
+ rte e0 = {
+ .attrs = ea,
+ .src = p->p.main_source,
+ };
e->unreachable = 1;
- rte_update2(c, e->n.addr, rte, p->p.main_source);
+ rte_update(c, e->n.addr, &e0, p->p.main_source);
}
else
{
/* Retraction */
e->unreachable = 0;
- rte_update2(c, e->n.addr, NULL, p->p.main_source);
+ rte_update(c, e->n.addr, NULL, p->p.main_source);
}
}
@@ -734,7 +732,7 @@ babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
{
struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
e->unreachable = 0;
- rte_update2(c, e->n.addr, NULL, p->p.main_source);
+ rte_update(c, e->n.addr, NULL, p->p.main_source);
}
@@ -2069,38 +2067,41 @@ static void
babel_get_route_info(rte *rte, byte *buf)
{
u64 rid = 0;
- eattr *e = ea_find(rte->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ eattr *e = ea_find(rte->attrs, &ea_babel_router_id);
if (e)
memcpy(&rid, e->u.ptr->data, sizeof(u64));
- buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref,
- ea_get_int(rte->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY), rid);
+ buf += bsprintf(buf, " (%d/%d) [%lR]",
+ rt_get_preference(rte),
+ ea_get_int(rte->attrs, &ea_babel_metric, BABEL_INFINITY), rid);
}
-static int
-babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
+static void
+babel_router_id_format(const eattr *a, byte *buf, uint len)
{
- switch (a->id)
- {
- case EA_BABEL_SEQNO:
- return GA_FULL;
+ u64 rid = 0;
+ memcpy(&rid, a->u.ptr->data, sizeof(u64));
+ bsnprintf(buf, len, "%lR", rid);
+}
- case EA_BABEL_METRIC:
- bsprintf(buf, "metric: %d", a->u.data);
- return GA_FULL;
+static struct ea_class ea_babel_metric = {
+ .name = "babel_metric",
+ .type = T_INT,
+};
- case EA_BABEL_ROUTER_ID:
- {
- u64 rid = 0;
- memcpy(&rid, a->u.ptr->data, sizeof(u64));
- bsprintf(buf, "router_id: %lR", rid);
- return GA_FULL;
- }
+static struct ea_class ea_babel_router_id = {
+ .name = "babel_router_id",
+ .type = T_OPAQUE,
+ .readonly = 1,
+ .format = babel_router_id_format,
+};
+
+static struct ea_class ea_babel_seqno = {
+ .name = "babel_seqno",
+ .type = T_INT,
+ .readonly = 1,
+};
- default:
- return GA_UNKNOWN;
- }
-}
void
babel_show_interfaces(struct proto *P, const char *iff)
@@ -2300,9 +2301,13 @@ babel_kick_timer(struct babel_proto *p)
static int
babel_preexport(struct channel *C, struct rte *new)
{
- struct rta *a = new->attrs;
+ if (new->src->owner != &C->proto->sources)
+ return 0;
+
/* Reject our own unreachable routes */
- if ((a->dest == RTD_UNREACHABLE) && (new->src->proto == C->proto))
+ eattr *ea = ea_find(new->attrs, &ea_gen_nexthop);
+ struct nexthop_adata *nhad = (void *) ea->u.ptr;
+ if (!NEXTHOP_IS_REACHABLE(nhad))
return -1;
return 0;
@@ -2313,8 +2318,8 @@ babel_preexport(struct channel *C, struct rte *new)
* so store it into our data structures.
*/
static void
-babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
- struct rte *new, struct rte *old UNUSED)
+babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
+ struct rte *new, const struct rte *old UNUSED)
{
struct babel_proto *p = (void *) P;
struct babel_entry *e;
@@ -2323,13 +2328,13 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
{
/* Update */
uint rt_seqno;
- uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
+ uint rt_metric = ea_get_int(new->attrs, &ea_babel_metric, 0);
u64 rt_router_id = 0;
- if (new->src->proto == P)
+ if (new->src->owner == &P->sources)
{
- rt_seqno = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
- eattr *e = ea_find(new->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ rt_seqno = ea_get_int(new->attrs, &ea_babel_seqno, 0);
+ eattr *e = ea_find(new->attrs, &ea_babel_router_id);
if (e)
memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64));
}
@@ -2342,11 +2347,11 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
if (rt_metric > BABEL_INFINITY)
{
log(L_WARN "%s: Invalid babel_metric value %u for route %N",
- p->p.name, rt_metric, net->n.addr);
+ p->p.name, rt_metric, net);
rt_metric = BABEL_INFINITY;
}
- e = babel_get_entry(p, net->n.addr);
+ e = babel_get_entry(p, net);
/* Activate triggered updates */
if ((e->valid != BABEL_ENTRY_VALID) ||
@@ -2364,7 +2369,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
else
{
/* Withdraw */
- e = babel_find_entry(p, net->n.addr);
+ e = babel_find_entry(p, net);
if (!e || e->valid != BABEL_ENTRY_VALID)
return;
@@ -2380,16 +2385,16 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
static int
babel_rte_better(struct rte *new, struct rte *old)
{
- uint new_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
- uint old_metric = ea_get_int(old->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
+ uint new_metric = ea_get_int(new->attrs, &ea_babel_metric, BABEL_INFINITY);
+ uint old_metric = ea_get_int(old->attrs, &ea_babel_metric, BABEL_INFINITY);
return new_metric < old_metric;
}
static u32
-babel_rte_igp_metric(struct rte *rt)
+babel_rte_igp_metric(const rte *rt)
{
- return ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
+ return ea_get_int(rt->attrs, &ea_babel_metric, BABEL_INFINITY);
}
@@ -2410,6 +2415,12 @@ babel_postconfig(struct proto_config *CF)
cf->ip6_channel = ip6 ?: ip6_sadr;
}
+static struct rte_owner_class babel_rte_owner_class = {
+ .get_route_info = babel_get_route_info,
+ .rte_better = babel_rte_better,
+ .rte_igp_metric = babel_rte_igp_metric,
+};
+
static struct proto *
babel_init(struct proto_config *CF)
{
@@ -2423,8 +2434,8 @@ babel_init(struct proto_config *CF)
P->if_notify = babel_if_notify;
P->rt_notify = babel_rt_notify;
P->preexport = babel_preexport;
- P->rte_better = babel_rte_better;
- P->rte_igp_metric = babel_rte_igp_metric;
+
+ P->sources.class = &babel_rte_owner_class;
return P;
}
@@ -2522,11 +2533,9 @@ babel_reconfigure(struct proto *P, struct proto_config *CF)
return 1;
}
-
struct protocol proto_babel = {
.name = "Babel",
.template = "babel%d",
- .class = PROTOCOL_BABEL,
.preference = DEF_PREF_BABEL,
.channel_mask = NB_IP | NB_IP6_SADR,
.proto_size = sizeof(struct babel_proto),
@@ -2537,12 +2546,16 @@ struct protocol proto_babel = {
.start = babel_start,
.shutdown = babel_shutdown,
.reconfigure = babel_reconfigure,
- .get_route_info = babel_get_route_info,
- .get_attr = babel_get_attr
};
void
babel_build(void)
{
proto_build(&proto_babel);
+
+ EA_REGISTER_ALL(
+ &ea_babel_metric,
+ &ea_babel_router_id,
+ &ea_babel_seqno
+ );
}
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index da8386b3..9014ace2 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -16,7 +16,7 @@
#include "nest/bird.h"
#include "nest/cli.h"
#include "nest/iface.h"
-#include "nest/route.h"
+#include "nest/rt.h"
#include "nest/protocol.h"
#include "nest/locks.h"
#include "nest/password.h"
@@ -26,10 +26,6 @@
#include "lib/string.h"
#include "lib/timer.h"
-#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
-#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
-#define EA_BABEL_SEQNO EA_CODE(PROTOCOL_BABEL, 2)
-
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
#define BABEL_PORT 6696
diff --git a/proto/babel/config.Y b/proto/babel/config.Y
index 05210fa4..a4350eed 100644
--- a/proto/babel/config.Y
+++ b/proto/babel/config.Y
@@ -24,7 +24,7 @@ CF_DECLS
CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT,
TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK,
- NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS,
+ NEXT, HOP, IPV4, IPV6, SHOW, INTERFACES, NEIGHBORS,
ENTRIES, RANDOMIZE, ROUTER, ID, AUTHENTICATION, NONE, MAC, PERMISSIVE)
CF_GRAMMAR
@@ -163,8 +163,6 @@ babel_iface_opt_list:
babel_iface:
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
-dynamic_attr: BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_BABEL_METRIC); } ;
-
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
CF_CLI(SHOW BABEL INTERFACES, optproto opttext, [<name>] [\"<interface>\"], [[Show information about Babel interfaces]])