summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospfd/rde.c81
-rw-r--r--usr.sbin/ospfd/rde.h25
2 files changed, 93 insertions, 13 deletions
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index b33ed1e5a6f..91f3f28e7e2 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.13 2005/05/02 02:26:35 djm Exp $ */
+/* $OpenBSD: rde.c,v 1.14 2005/05/08 19:58:51 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -50,6 +50,11 @@ struct rde_nbr *rde_nbr_find(u_int32_t);
struct rde_nbr *rde_nbr_new(u_int32_t, struct rde_nbr *);
void rde_nbr_del(struct rde_nbr *);
+void rde_req_list_add(struct rde_nbr *, struct lsa_hdr *);
+int rde_req_list_exists(struct rde_nbr *, struct lsa_hdr *);
+void rde_req_list_del(struct rde_nbr *, struct lsa_hdr *);
+void rde_req_list_free(struct rde_nbr *);
+
int rde_redistribute(struct kroute *);
struct lsa *rde_asext_get(struct kroute *);
struct lsa *rde_asext_put(struct kroute *);
@@ -257,6 +262,9 @@ rde_dispatch_imsg(int fd, short event, void *bula)
fatalx("rde_dispatch_imsg: "
"neighbor does not exist");
nbr->state = state;
+
+ if (nbr->state & NBR_STA_FULL)
+ rde_req_list_free(nbr);
break;
case IMSG_DB_SNAPSHOT:
nbr = rde_nbr_find(imsg.hdr.peerid);
@@ -292,15 +300,16 @@ rde_dispatch_imsg(int fd, short event, void *bula)
else
db_hdr = &v->lsa->hdr;
- if (lsa_newer(&lsa_hdr, db_hdr) > 0)
+ if (lsa_newer(&lsa_hdr, db_hdr) > 0) {
/*
* only request LSA's that are
* newer or missing
*/
- /* XXX add to local REQ list */
+ rde_req_list_add(nbr, &lsa_hdr);
imsg_compose(ibuf_ospfe, IMSG_DD,
imsg.hdr.peerid, 0, -1,
&lsa_hdr, sizeof(lsa_hdr));
+ }
}
if (l != 0)
log_warnx("rde_dispatch_imsg: peerid %lu, "
@@ -381,6 +390,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
if (!(self = lsa_self(nbr, lsa, v)))
lsa_add(nbr, lsa);
+ rde_req_list_del(nbr, &lsa->hdr);
/* flood and perhaps ack LSA */
imsg_compose(ibuf_ospfe, IMSG_LS_FLOOD,
imsg.hdr.peerid, 0, -1,
@@ -395,7 +405,9 @@ rde_dispatch_imsg(int fd, short event, void *bula)
/* start spf_timer */
log_debug("rde_dispatch_imsg: start spf_timer");
start_spf_timer(rdeconf);
- /* TODO LSA on req list -> BadLSReq */
+ } else if (rde_req_list_exists(nbr, &lsa->hdr)) {
+ imsg_compose(ibuf_ospfe, IMSG_LS_BADREQ,
+ imsg.hdr.peerid, 0, -1, NULL, 0);
} else if (r < 0) {
/* new LSA older than DB */
if (ntohl(db_hdr->seq_num) == MAX_SEQ_NUM &&
@@ -740,6 +752,7 @@ rde_nbr_new(u_int32_t peerid, struct rde_nbr *new)
memcpy(nbr, new, sizeof(*nbr));
nbr->peerid = peerid;
nbr->area = area;
+ TAILQ_INIT(&nbr->req_list);
head = RDE_NBR_HASH(peerid);
LIST_INSERT_HEAD(head, nbr, hash);
@@ -754,6 +767,8 @@ rde_nbr_del(struct rde_nbr *nbr)
if (nbr == NULL)
return;
+ rde_req_list_free(nbr);
+
LIST_REMOVE(nbr, entry);
LIST_REMOVE(nbr, hash);
@@ -790,6 +805,64 @@ rde_nbr_self(struct area *area)
}
/*
+ * LSA req list
+ */
+void
+rde_req_list_add(struct rde_nbr *nbr, struct lsa_hdr *lsa)
+{
+ struct rde_req_entry *le;
+
+ if ((le = calloc(1, sizeof(*le))) == NULL)
+ fatal("rde_req_list_add");
+
+ TAILQ_INSERT_TAIL(&nbr->req_list, le, entry);
+ le->type = lsa->type;
+ le->ls_id = lsa->ls_id;
+ le->adv_rtr = lsa->adv_rtr;
+}
+
+int
+rde_req_list_exists(struct rde_nbr *nbr, struct lsa_hdr *lsa_hdr)
+{
+ struct rde_req_entry *le;
+
+ TAILQ_FOREACH(le, &nbr->req_list, entry) {
+ if ((lsa_hdr->type == le->type) &&
+ (lsa_hdr->ls_id == le->ls_id) &&
+ (lsa_hdr->adv_rtr == le->adv_rtr))
+ return (1);
+ }
+ return (0);
+}
+
+void
+rde_req_list_del(struct rde_nbr *nbr, struct lsa_hdr *lsa_hdr)
+{
+ struct rde_req_entry *le;
+
+ TAILQ_FOREACH(le, &nbr->req_list, entry) {
+ if ((lsa_hdr->type == le->type) &&
+ (lsa_hdr->ls_id == le->ls_id) &&
+ (lsa_hdr->adv_rtr == le->adv_rtr)) {
+ TAILQ_REMOVE(&nbr->req_list, le, entry);
+ free(le);
+ return;
+ }
+ }
+}
+
+void
+rde_req_list_free(struct rde_nbr *nbr)
+{
+ struct rde_req_entry *le;
+
+ while ((le = TAILQ_FIRST(&nbr->req_list)) != NULL) {
+ TAILQ_REMOVE(&nbr->req_list, le, entry);
+ free(le);
+ }
+}
+
+/*
* as-external LSA handling
*/
LIST_HEAD(, rde_asext) rde_asext_list;
diff --git a/usr.sbin/ospfd/rde.h b/usr.sbin/ospfd/rde.h
index cb8562708b1..41b7ffef224 100644
--- a/usr.sbin/ospfd/rde.h
+++ b/usr.sbin/ospfd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.9 2005/04/12 09:54:59 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.10 2005/05/08 19:58:51 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -43,16 +43,23 @@ struct vertex {
u_int8_t flooded;
};
+struct rde_req_entry {
+ TAILQ_ENTRY(rde_req_entry) entry;
+ u_int32_t ls_id;
+ u_int32_t adv_rtr;
+ u_int8_t type;
+};
+
/* just the info RDE needs */
struct rde_nbr {
- LIST_ENTRY(rde_nbr) entry, hash;
- struct in_addr id;
- struct in_addr area_id;
- struct lsa_head ls_req_list;
- struct area *area;
- u_int32_t peerid; /* unique ID in DB */
- int state;
- int self;
+ LIST_ENTRY(rde_nbr) entry, hash;
+ struct in_addr id;
+ struct in_addr area_id;
+ TAILQ_HEAD(, rde_req_entry) req_list;
+ struct area *area;
+ u_int32_t peerid; /* unique ID in DB */
+ int state;
+ int self;
};
struct rde_asext {