summaryrefslogtreecommitdiff
path: root/usr.sbin/ospfd/rde_lsdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ospfd/rde_lsdb.c')
-rw-r--r--usr.sbin/ospfd/rde_lsdb.c131
1 files changed, 92 insertions, 39 deletions
diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c
index 4cc79c52fb6..053666cf49e 100644
--- a/usr.sbin/ospfd/rde_lsdb.c
+++ b/usr.sbin/ospfd/rde_lsdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_lsdb.c,v 1.46 2011/05/02 11:45:55 claudio Exp $ */
+/* $OpenBSD: rde_lsdb.c,v 1.47 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -27,9 +27,11 @@
#include "rde.h"
#include "log.h"
-struct vertex *vertex_get(struct lsa *, struct rde_nbr *);
+struct vertex *vertex_get(struct lsa *, struct rde_nbr *, struct lsa_tree *);
int lsa_router_check(struct lsa *, u_int16_t);
+struct vertex *lsa_find_tree(struct lsa_tree *, u_int16_t, u_int32_t,
+ u_int32_t);
void lsa_timeout(int, short, void *);
void lsa_refresh(struct vertex *);
int lsa_equal(struct lsa *, struct lsa *);
@@ -49,20 +51,20 @@ lsa_compare(struct vertex *a, struct vertex *b)
return (-1);
if (a->type > b->type)
return (1);
- if (a->ls_id < b->ls_id)
- return (-1);
- if (a->ls_id > b->ls_id)
- return (1);
if (a->adv_rtr < b->adv_rtr)
return (-1);
if (a->adv_rtr > b->adv_rtr)
return (1);
+ if (a->ls_id < b->ls_id)
+ return (-1);
+ if (a->ls_id > b->ls_id)
+ return (1);
return (0);
}
struct vertex *
-vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
+vertex_get(struct lsa *lsa, struct rde_nbr *nbr, struct lsa_tree *tree)
{
struct vertex *v;
struct timespec tp;
@@ -79,6 +81,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
v->ls_id = ntohl(lsa->hdr.ls_id);
v->adv_rtr = ntohl(lsa->hdr.adv_rtr);
v->type = lsa->hdr.type;
+ v->lsa_tree = tree;
if (!nbr->self)
v->flooded = 1; /* XXX fix me */
@@ -92,10 +95,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
void
vertex_free(struct vertex *v)
{
- if (v->type == LSA_TYPE_EXTERNAL)
- RB_REMOVE(lsa_tree, &asext_tree, v);
- else
- RB_REMOVE(lsa_tree, &v->area->lsa_tree, v);
+ RB_REMOVE(lsa_tree, v->lsa_tree, v);
(void)evtimer_del(&v->ev);
vertex_nexthop_clear(v);
@@ -255,13 +255,24 @@ lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len)
if (area->stub)
return (0);
break;
+ case LSA_TYPE_LINK_OPAQ:
+ case LSA_TYPE_AREA_OPAQ:
+ case LSA_TYPE_AS_OPAQ:
+ if (len % sizeof(u_int32_t)) {
+ log_warnx("lsa_check: bad opaque LSA packet");
+ return (0);
+ }
+ /* Type-11 Opaque-LSA are silently discarded in stub areas */
+ if (lsa->hdr.type == LSA_TYPE_AS_OPAQ && area->stub)
+ return (0);
+ break;
default:
log_warnx("lsa_check: unknown type %u", lsa->hdr.type);
return (0);
}
/* MaxAge handling */
- if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area,
+ if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(nbr->iface,
lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL &&
!rde_nbr_loading(area)) {
/*
@@ -372,12 +383,15 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
struct vertex *new, *old;
struct timeval tv, now, res;
- if (lsa->hdr.type == LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type == LSA_TYPE_EXTERNAL ||
+ lsa->hdr.type == LSA_TYPE_AS_OPAQ)
tree = &asext_tree;
+ else if (lsa->hdr.type == LSA_TYPE_LINK_OPAQ)
+ tree = &nbr->iface->lsa_tree;
else
tree = &nbr->area->lsa_tree;
- new = vertex_get(lsa, nbr);
+ new = vertex_get(lsa, nbr, tree);
old = RB_INSERT(lsa_tree, tree, new);
if (old != NULL) {
@@ -396,14 +410,16 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
return (1);
}
if (!lsa_equal(new->lsa, old->lsa)) {
- if (lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type != LSA_TYPE_EXTERNAL &&
+ lsa->hdr.type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
start_spf_timer();
}
vertex_free(old);
RB_INSERT(lsa_tree, tree, new);
} else {
- if (lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type != LSA_TYPE_EXTERNAL &&
+ lsa->hdr.type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
start_spf_timer();
}
@@ -427,7 +443,7 @@ lsa_del(struct rde_nbr *nbr, struct lsa_hdr *lsa)
struct vertex *v;
struct timeval tv;
- v = lsa_find(nbr->area, lsa->type, lsa->ls_id, lsa->adv_rtr);
+ v = lsa_find(nbr->iface, lsa->type, lsa->ls_id, lsa->adv_rtr);
if (v == NULL)
return;
@@ -469,21 +485,39 @@ lsa_age(struct vertex *v)
}
struct vertex *
-lsa_find(struct area *area, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr)
+lsa_find(struct iface *iface, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr)
+{
+ struct lsa_tree *tree;
+
+ if (type == LSA_TYPE_EXTERNAL ||
+ type == LSA_TYPE_AS_OPAQ)
+ tree = &asext_tree;
+ else if (type == LSA_TYPE_LINK_OPAQ)
+ tree = &iface->lsa_tree;
+ else
+ tree = &iface->area->lsa_tree;
+
+ return lsa_find_tree(tree, type, ls_id, adv_rtr);
+}
+
+struct vertex *
+lsa_find_area(struct area *area, u_int8_t type, u_int32_t ls_id,
+ u_int32_t adv_rtr)
+{
+ return lsa_find_tree(&area->lsa_tree, type, ls_id, adv_rtr);
+}
+
+struct vertex *
+lsa_find_tree(struct lsa_tree *tree, u_int16_t type, u_int32_t ls_id,
+ u_int32_t adv_rtr)
{
struct vertex key;
struct vertex *v;
- struct lsa_tree *tree;
key.ls_id = ntohl(ls_id);
key.adv_rtr = ntohl(adv_rtr);
key.type = type;
- if (type == LSA_TYPE_EXTERNAL)
- tree = &asext_tree;
- else
- tree = &area->lsa_tree;
-
v = RB_FIND(lsa_tree, tree, &key);
/* LSA that are deleted are not findable */
@@ -532,26 +566,40 @@ lsa_num_links(struct vertex *v)
}
void
-lsa_snap(struct area *area, u_int32_t peerid)
+lsa_snap(struct rde_nbr *nbr)
{
- struct lsa_tree *tree = &area->lsa_tree;
+ struct lsa_tree *tree = &nbr->area->lsa_tree;
struct vertex *v;
do {
RB_FOREACH(v, lsa_tree, tree) {
if (v->deleted)
continue;
+ switch (v->type) {
+ case LSA_TYPE_LINK_OPAQ:
+ case LSA_TYPE_AREA_OPAQ:
+ case LSA_TYPE_AS_OPAQ:
+ if (nbr->capa_options & OSPF_OPTION_O)
+ break;
+ continue;
+ }
lsa_age(v);
if (ntohs(v->lsa->hdr.age) >= MAX_AGE)
- rde_imsg_compose_ospfe(IMSG_LS_UPD, peerid,
+ rde_imsg_compose_ospfe(IMSG_LS_UPD, nbr->peerid,
0, &v->lsa->hdr, ntohs(v->lsa->hdr.len));
else
- rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT, peerid,
- 0, &v->lsa->hdr, sizeof(struct lsa_hdr));
+ rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT,
+ nbr->peerid, 0, &v->lsa->hdr,
+ sizeof(struct lsa_hdr));
}
- if (tree != &area->lsa_tree || area->stub)
+ if (tree == &asext_tree)
break;
- tree = &asext_tree;
+ if (tree == &nbr->area->lsa_tree)
+ tree = &nbr->iface->lsa_tree;
+ else if (nbr->area->stub)
+ break;
+ else
+ tree = &asext_tree;
} while (1);
}
@@ -566,9 +614,7 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid)
lsa_age(v);
switch (imsg_type) {
case IMSG_CTL_SHOW_DATABASE:
- rde_imsg_compose_ospfe(IMSG_CTL_SHOW_DATABASE, 0, pid,
- &v->lsa->hdr, ntohs(v->lsa->hdr.len));
- continue;
+ break;
case IMSG_CTL_SHOW_DB_SELF:
if (v->lsa->hdr.adv_rtr == rde_router_id())
break;
@@ -593,6 +639,12 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid)
if (v->type == LSA_TYPE_SUM_ROUTER)
break;
continue;
+ case IMSG_CTL_SHOW_DB_OPAQ:
+ if (v->type == LSA_TYPE_LINK_OPAQ ||
+ v->type == LSA_TYPE_AREA_OPAQ ||
+ v->type == LSA_TYPE_AS_OPAQ)
+ break;
+ continue;
default:
log_warnx("lsa_dump: unknown imsg type");
return;
@@ -618,7 +670,8 @@ lsa_timeout(int fd, short event, void *bula)
v->deleted = 0;
/* schedule recalculation of the RIB */
- if (v->lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (v->type != LSA_TYPE_EXTERNAL &&
+ v->type != LSA_TYPE_AS_OPAQ)
v->area->dirty = 1;
start_spf_timer();
@@ -713,7 +766,8 @@ lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v)
free(v->lsa);
v->lsa = lsa;
start_spf_timer();
- if (v->type != LSA_TYPE_EXTERNAL)
+ if (v->type != LSA_TYPE_EXTERNAL &&
+ v->type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
/* set correct timeout for reflooding the LSA */
@@ -774,13 +828,13 @@ lsa_generate_stub_sums(struct area *area)
rn.cost = r->metric & LSA_METRIC_MASK;
/* update lsa but only if it was changed */
- v = lsa_find(area, LSA_TYPE_SUM_NETWORK,
+ v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK,
rn.prefix.s_addr, rde_router_id());
lsa = orig_sum_lsa(&rn, area, LSA_TYPE_SUM_NETWORK, 0);
lsa_merge(rde_nbr_self(area), lsa, v);
if (v == NULL)
- v = lsa_find(area, LSA_TYPE_SUM_NETWORK,
+ v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK,
rn.prefix.s_addr, rde_router_id());
/*
@@ -817,4 +871,3 @@ lsa_equal(struct lsa *a, struct lsa *b)
return (1);
}
-