summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2010-08-22 20:55:11 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2010-08-22 20:55:11 +0000
commit8b0fe1f05a24ae94c4d8e02325e8956d04164f11 (patch)
tree19bbaf03878518c74a8e823a8eeb38759a03d7e1
parentda8522b295984f055f977bfbe8392cbb3c277021 (diff)
When removing an announced prefix, inherit the metric and ext_tag
from the LSA that is currently in the tree. Based on claudio@'s diff and his fix for ospfd. Additionally originate an LSA with external route tag correctly by writing the AS-external-LSA's bit T into the correct field. ok claudio@
-rw-r--r--usr.sbin/ospf6d/rde.c35
-rw-r--r--usr.sbin/ospf6d/rde_lsdb.c10
2 files changed, 35 insertions, 10 deletions
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c
index 2a2e11e4844..b6e7da4cd81 100644
--- a/usr.sbin/ospf6d/rde.c
+++ b/usr.sbin/ospf6d/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.49 2010/07/09 12:39:46 bluhm Exp $ */
+/* $OpenBSD: rde.c,v 1.50 2010/08/22 20:55:10 bluhm Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -1574,7 +1574,7 @@ orig_asext_lsa(struct rroute *rr, u_int16_t age)
{
struct lsa *lsa;
u_int32_t ext_tag;
- u_int16_t len, ext_off = 0;
+ u_int16_t len, ext_off;
len = sizeof(struct lsa_hdr) + sizeof(struct lsa_asext) +
LSA_PREFIXSIZE(rr->kr.prefixlen);
@@ -1586,8 +1586,8 @@ orig_asext_lsa(struct rroute *rr, u_int16_t age)
* XXX for now we don't do this.
*/
+ ext_off = len;
if (rr->kr.ext_tag) {
- ext_off = len;
len += sizeof(ext_tag);
}
if ((lsa = calloc(1, len)) == NULL)
@@ -1603,19 +1603,40 @@ orig_asext_lsa(struct rroute *rr, u_int16_t age)
lsa->hdr.seq_num = htonl(INIT_SEQ_NUM);
lsa->hdr.len = htons(len);
- lsa->data.asext.metric = htonl(rr->metric);
lsa->data.asext.prefix.prefixlen = rr->kr.prefixlen;
memcpy((char *)lsa + sizeof(struct lsa_hdr) + sizeof(struct lsa_asext),
&rr->kr.prefix, LSA_PREFIXSIZE(rr->kr.prefixlen));
+ lsa->hdr.ls_id = lsa_find_lsid(&asext_tree, lsa->hdr.type,
+ lsa->hdr.adv_rtr, comp_asext, lsa);
+
+ if (age == MAX_AGE) {
+ /* inherit metric and ext_tag from the current LSA,
+ * some routers don't like to get withdraws that are
+ * different from what they have in their table.
+ */
+ struct vertex *v;
+ v = lsa_find(NULL, lsa->hdr.type, lsa->hdr.ls_id,
+ lsa->hdr.adv_rtr);
+ if (v != NULL) {
+ rr->metric = ntohl(v->lsa->data.asext.metric);
+ if (rr->metric & LSA_ASEXT_T_FLAG) {
+ memcpy(&ext_tag, (char *)v->lsa + ext_off,
+ sizeof(ext_tag));
+ rr->kr.ext_tag = ntohl(ext_tag);
+ }
+ rr->metric &= LSA_METRIC_MASK;
+ }
+ }
+
if (rr->kr.ext_tag) {
- lsa->data.asext.prefix.options |= LSA_ASEXT_T_FLAG;
+ lsa->data.asext.metric = htonl(rr->metric | LSA_ASEXT_T_FLAG);
ext_tag = htonl(rr->kr.ext_tag);
memcpy((char *)lsa + ext_off, &ext_tag, sizeof(ext_tag));
+ } else {
+ lsa->data.asext.metric = htonl(rr->metric);
}
- lsa->hdr.ls_id = lsa_find_lsid(&asext_tree, lsa->hdr.type,
- lsa->hdr.adv_rtr, comp_asext, lsa);
lsa->hdr.ls_chksum = 0;
lsa->hdr.ls_chksum =
htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET));
diff --git a/usr.sbin/ospf6d/rde_lsdb.c b/usr.sbin/ospf6d/rde_lsdb.c
index d8a89af154c..40b5a812f08 100644
--- a/usr.sbin/ospf6d/rde_lsdb.c
+++ b/usr.sbin/ospf6d/rde_lsdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_lsdb.c,v 1.34 2010/07/01 19:47:04 bluhm Exp $ */
+/* $OpenBSD: rde_lsdb.c,v 1.35 2010/08/22 20:55:10 bluhm Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -827,7 +827,11 @@ lsa_refresh(struct vertex *v)
u_int16_t len;
/* refresh LSA by increasing sequence number by one */
- v->lsa->hdr.age = htons(DEFAULT_AGE);
+ if (v->self && ntohs(v->lsa->hdr.age) >= MAX_AGE)
+ /* self originated network that is currently beeing removed */
+ v->lsa->hdr.age = htons(MAX_AGE);
+ else
+ v->lsa->hdr.age = htons(DEFAULT_AGE);
seqnum = ntohl(v->lsa->hdr.seq_num);
if (seqnum++ == MAX_SEQ_NUM)
/* XXX fix me */
@@ -931,7 +935,7 @@ lsa_equal(struct lsa *a, struct lsa *b)
return (0);
if (a->hdr.len != b->hdr.len)
return (0);
- /* LSA with age MAX_AGE are never equal */
+ /* LSAs with age MAX_AGE are never equal */
if (a->hdr.age == htons(MAX_AGE) || b->hdr.age == htons(MAX_AGE))
return (0);
if (memcmp(&a->data, &b->data, ntohs(a->hdr.len) -