diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2010-08-22 20:55:11 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2010-08-22 20:55:11 +0000 |
commit | 8b0fe1f05a24ae94c4d8e02325e8956d04164f11 (patch) | |
tree | 19bbaf03878518c74a8e823a8eeb38759a03d7e1 | |
parent | da8522b295984f055f977bfbe8392cbb3c277021 (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.c | 35 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde_lsdb.c | 10 |
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) - |