diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-08-05 18:44:20 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-08-05 18:44:20 +0000 |
commit | 475388ebf609553cd9c9c2e5c86f22388f366dcd (patch) | |
tree | 8127764db95d65e5da4dcd61ac2f6643a839bc85 /usr.sbin | |
parent | a9afe3a1c53305a7d4f2e003ce8fc277c893e008 (diff) |
Cleanup aspath specific functions and api. Mainly switch to a refcnt based
allocation. This helps to save a bit of RAM. looks good henning@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/rde.c | 8 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 37 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_attr.c | 344 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_decide.c | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 16 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_prefix.c | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 20 |
8 files changed, 247 insertions, 197 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 6278cc4301b..97e2d2bdc30 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.134 2004/08/05 16:26:56 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.135 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -172,6 +172,7 @@ rde_main(struct bgpd_config *config, struct network_head *net_l, pt_init(); path_init(pathhashsize); + aspath_init(pathhashsize); nexthop_init(nexthophashsize); peer_init(peerhashsize); rules_l = rules; @@ -644,9 +645,6 @@ rde_update_dispatch(struct imsg *imsg) /* aspath needs to be loop free nota bene this is not a hard error */ if (peer->conf.ebgp && !aspath_loopfree(attrs.aspath, conf->as)) { - char *s; - aspath_asprint(&s, attrs.aspath->data, attrs.aspath->hdr.len); - free(s); attr_free(&attrs); return (0); } @@ -1481,7 +1479,7 @@ network_add(struct network_config *nc, int flagstatic) bzero(&attrs, sizeof(attrs)); - attrs.aspath = aspath_create(NULL, 0); + attrs.aspath = aspath_get(NULL, 0); attrs.nexthop.s_addr = INADDR_ANY; /* med = 0 */ attrs.lpref = DEFAULT_LPREF; diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 5f94d0d6bc6..e7829dba2dc 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.48 2004/08/05 15:58:21 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.49 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -67,25 +67,16 @@ struct rde_peer { #define AS_SET 1 #define AS_SEQUENCE 2 -#define ASPATH_HEADER_SIZE sizeof(struct aspath_hdr) +#define ASPATH_HEADER_SIZE sizeof(struct aspath) -struct aspath_hdr { - u_int16_t len; /* total length of aspath - in octets */ - u_int16_t as_cnt; /* number of AS's in data */ - u_int16_t prepend; -}; +LIST_HEAD(aspath_list, aspath); struct aspath { - struct aspath_hdr hdr; - u_char data[1]; - /* - * data consists of multiple struct aspath_segment with a length of - * len octets. In zebra data is a pointer to some memory location with - * the aspath segments. We could do it like this but then we should - * remove the pointer from rde_aspath and store the aspath header - * directly there. - */ + LIST_ENTRY(aspath) entry; + int refcnt; /* reference count */ + u_int16_t len; /* total length of aspath in octets */ + u_int16_t ascnt; /* number of AS hops in data */ + u_char data[0]; /* placeholder for actual data */ }; enum attrtypes { @@ -264,17 +255,17 @@ int aspath_verify(void *, u_int16_t); #define AS_ERR_LEN -1 #define AS_ERR_TYPE -2 #define AS_ERR_BAD -3 -struct aspath *aspath_create(void *, u_int16_t); -void aspath_destroy(struct aspath *); -int aspath_write(void *, u_int16_t, struct aspath *, u_int16_t, - int); +void aspath_init(u_int32_t); +struct aspath *aspath_get(void *, u_int16_t); +void aspath_put(struct aspath *); u_char *aspath_dump(struct aspath *); u_int16_t aspath_length(struct aspath *); -u_int16_t aspath_count(struct aspath *); +u_int16_t aspath_count(const void *, u_int16_t); u_int16_t aspath_neighbor(struct aspath *); -u_int32_t aspath_hash(struct aspath *); int aspath_loopfree(struct aspath *, u_int16_t); int aspath_compare(struct aspath *, struct aspath *); +u_int32_t aspath_hash(const void *, u_int16_t); +struct aspath *aspath_prepend(struct aspath *, u_int16_t, int); int aspath_snprint(char *, size_t, void *, u_int16_t); int aspath_asprint(char **, void *, u_int16_t); size_t aspath_strlen(void *, u_int16_t); diff --git a/usr.sbin/bgpd/rde_attr.c b/usr.sbin/bgpd/rde_attr.c index 84d0007b23a..756d4649869 100644 --- a/usr.sbin/bgpd/rde_attr.c +++ b/usr.sbin/bgpd/rde_attr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_attr.c,v 1.39 2004/07/28 16:02:14 claudio Exp $ */ +/* $OpenBSD: rde_attr.c,v 1.40 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -112,7 +112,7 @@ attr_parse(u_char *p, u_int16_t len, struct attr_flags *a, int ebgp, if (aspath_verify(p, attr_len) != 0) return (-1); WFLAG(a->wflags, F_ATTR_ASPATH); - a->aspath = aspath_create(p, attr_len); + a->aspath = aspath_get(p, attr_len); if (enforce_as == ENFORCE_AS_ON && remote_as != aspath_neighbor(a->aspath)) return (-1); @@ -448,7 +448,7 @@ attr_copy(struct attr_flags *t, struct attr_flags *s) * a own copy. */ memcpy(t, s, sizeof(struct attr_flags)); - t->aspath = aspath_create(s->aspath->data, s->aspath->hdr.len); + t->aspath = aspath_get(s->aspath->data, s->aspath->len); TAILQ_INIT(&t->others); TAILQ_FOREACH(os, &s->others, entry) attr_optadd(t, os->flags, os->type, os->data, os->len); @@ -476,7 +476,7 @@ attr_free(struct attr_flags *a) * free the aspath and all optional path attributes * but not the attr_flags struct. */ - aspath_destroy(a->aspath); + aspath_put(a->aspath); a->aspath = NULL; attr_optfree(a); } @@ -667,25 +667,17 @@ attr_mp_nexthop(const struct attr_flags *attrs) /* aspath specific functions */ -static u_int16_t aspath_extract(void *, int); +u_int32_t aspath_hash(const void *, u_int16_t); +u_int16_t aspath_extract(const void *, int); +struct aspath *aspath_lookup(const void *, u_int16_t); -/* - * Extract the asnum out of the as segment at the specified position. - * Direct access is not possible because of non-aligned reads. - * ATTENTION: no bounds check are done. - */ -static u_int16_t -aspath_extract(void *seg, int pos) -{ - u_char *ptr = seg; - u_int16_t as = 0; +struct aspath_table { + struct aspath_list *hashtbl; + u_int32_t hashmask; +} astable; - ptr += 2 + 2 * pos; - as = *ptr++; - as <<= 8; - as |= *ptr; - return (as); -} +#define ASPATH_HASH(x) \ + &astable.hashtbl[(x) & astable.hashmask] int aspath_verify(void *data, u_int16_t len) @@ -719,115 +711,63 @@ aspath_verify(void *data, u_int16_t len) return (0); /* aspath is valid but probably not loop free */ } -struct aspath * -aspath_create(void *data, u_int16_t len) +void +aspath_init(u_int32_t hashsize) { - struct aspath *aspath; + u_int32_t hs, i; - /* The aspath must already have been checked for correctness. */ - aspath = malloc(ASPATH_HEADER_SIZE + len); - if (aspath == NULL) - fatal("aspath_create"); - aspath->hdr.len = len; - memcpy(aspath->data, data, len); + for (hs = 1; hs < hashsize; hs <<= 1) + ; + astable.hashtbl = calloc(hs, sizeof(struct aspath_list)); + if (astable.hashtbl == NULL) + fatal("path_init"); - aspath->hdr.as_cnt = aspath_count(aspath); - aspath->hdr.prepend = 0; + for (i = 0; i < hs; i++) + LIST_INIT(&astable.hashtbl[i]); - return (aspath); + astable.hashmask = hs - 1; } -int -aspath_write(void *p, u_int16_t len, struct aspath *aspath, u_int16_t myAS, - int ebgp) +struct aspath * +aspath_get(void *data, u_int16_t len) { - u_char *b = p; - int tot_len, as_len, prepend, size, wpos = 0; - u_int16_t tmp; - u_int8_t type, attr_flag = ATTR_WELL_KNOWN; - - prepend = aspath->hdr.prepend + (ebgp ? 1 : 0); - - if (prepend > 255) - /* lunatic prepends need to be blocked in the parser */ - return (-1); + struct aspath_list *head; + struct aspath *aspath; - /* first calculate new size */ - if (aspath->hdr.len > 0) { - if (aspath->hdr.len < 2) - return (-1); - type = aspath->data[0]; - size = aspath->data[1]; - } else { - /* empty as path */ - type = AS_SET; - size = 0; + /* The aspath must already have been checked for correctness. */ + aspath = aspath_lookup(data, len); + if (aspath == NULL) { + aspath = malloc(ASPATH_HEADER_SIZE + len); + if (aspath == NULL) + fatal("aspath_get"); + + aspath->refcnt = 0; + aspath->len = len; + aspath->ascnt = aspath_count(data, len); + memcpy(aspath->data, data, len); + + /* link */ + head = ASPATH_HASH(aspath_hash(aspath->data, aspath->len)); + LIST_INSERT_HEAD(head, aspath, entry); } - if (prepend == 0) - as_len = aspath->hdr.len; - else if (type == AS_SET || size + prepend > 255) - /* need to attach a new AS_SEQUENCE */ - as_len = 2 + prepend * 2 + aspath->hdr.len; - else - as_len = prepend * 2 + aspath->hdr.len; - - /* check buffer size */ - tot_len = 2 + as_len; - if (as_len > 255) { - attr_flag |= ATTR_EXTLEN; - tot_len += 2; - } else - tot_len += 1; - - if (tot_len > len) - return (-1); - - /* header */ - b[wpos++] = attr_flag; - b[wpos++] = ATTR_ASPATH; - if (as_len > 255) { - tmp = as_len; - tmp = htons(tmp); - memcpy(b, &tmp, 2); - wpos += 2; - } else - b[wpos++] = (u_char)(as_len & 0xff); + aspath->refcnt++; - /* first prepends */ - myAS = htons(myAS); - if (type == AS_SET) { - b[wpos++] = AS_SEQUENCE; - b[wpos++] = prepend; - for (; prepend > 0; prepend--) { - memcpy(b + wpos, &myAS, 2); - wpos += 2; - } - memcpy(b + wpos, aspath->data, aspath->hdr.len); - } else { - if (size + prepend > 255) { - b[wpos++] = AS_SEQUENCE; - b[wpos++] = size + prepend - 255; - for (; prepend + size > 255; prepend--) { - memcpy(b + wpos, &myAS, 2); - wpos += 2; - } - } - b[wpos++] = AS_SEQUENCE; - b[wpos++] = size + prepend; - for (; prepend > 0; prepend--) { - memcpy(b + wpos, &myAS, 2); - wpos += 2; - } - memcpy(b + wpos, aspath->data + 2, aspath->hdr.len - 2); - } - return (tot_len); + return (aspath); } void -aspath_destroy(struct aspath *aspath) +aspath_put(struct aspath *aspath) { - /* only the aspath needs to be freed */ - if (aspath == NULL) return; + if (aspath == NULL) + return; + + if (--aspath->refcnt > 0) + /* somebody still holds a reference */ + return; + + /* unlink */ + LIST_REMOVE(aspath, entry); + free(aspath); } @@ -840,19 +780,19 @@ aspath_dump(struct aspath *aspath) u_int16_t aspath_length(struct aspath *aspath) { - return (aspath->hdr.len); + return (aspath->len); } u_int16_t -aspath_count(struct aspath *aspath) +aspath_count(const void *data, u_int16_t len) { - u_int8_t *seg; - u_int16_t cnt, len, seg_size; + const u_int8_t *seg; + u_int16_t cnt, seg_size; u_int8_t seg_type, seg_len; cnt = 0; - seg = aspath->data; - for (len = aspath->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + seg = data; + for (; len > 0; len -= seg_size, seg += seg_size) { seg_type = seg[0]; seg_len = seg[1]; seg_size = 2 + 2 * seg_len; @@ -861,6 +801,9 @@ aspath_count(struct aspath *aspath) cnt += 1; else cnt += seg_len; + + if (seg_size > len) + fatalx("aspath_count: bula bula"); } return (cnt); } @@ -874,7 +817,7 @@ aspath_neighbor(struct aspath *aspath) * That should not break anything. */ - if (aspath->hdr.len == 0) + if (aspath->len == 0) return (0); return (aspath_extract(aspath->data, 0)); @@ -888,7 +831,7 @@ aspath_loopfree(struct aspath *aspath, u_int16_t myAS) u_int8_t i, seg_len, seg_type; seg = aspath->data; - for (len = aspath->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + for (len = aspath->len; len > 0; len -= seg_size, seg += seg_size) { seg_type = seg[0]; seg_len = seg[1]; seg_size = 2 + 2 * seg_len; @@ -897,23 +840,43 @@ aspath_loopfree(struct aspath *aspath, u_int16_t myAS) if (myAS == aspath_extract(seg, i)) return (0); } + + if (seg_size > len) + fatalx("aspath_loopfree: bula bula"); } return (1); } +int +aspath_compare(struct aspath *a1, struct aspath *a2) +{ + int r; + + if (a1->len > a2->len) + return (1); + if (a1->len < a2->len) + return (-1); + r = memcmp(a1->data, a2->data, a1->len); + if (r > 0) + return (1); + if (r < 0) + return (-1); + return (0); +} + #define AS_HASH_INITIAL 8271 u_int32_t -aspath_hash(struct aspath *aspath) +aspath_hash(const void *data, u_int16_t len) { - u_int8_t *seg; + const u_int8_t *seg; u_int32_t hash; - u_int16_t len, seg_size; + u_int16_t seg_size; u_int8_t i, seg_len, seg_type; hash = AS_HASH_INITIAL; - seg = aspath->data; - for (len = aspath->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + seg = data; + for (; len > 0; len -= seg_size, seg += seg_size) { seg_type = seg[0]; seg_len = seg[1]; seg_size = 2 + 2 * seg_len; @@ -922,25 +885,117 @@ aspath_hash(struct aspath *aspath) hash += (hash << 5); hash ^= aspath_extract(seg, i); } + + if (seg_size > len) + fatalx("aspath_hash: bula bula"); } return (hash); } -int -aspath_compare(struct aspath *a1, struct aspath *a2) +/* + * Extract the asnum out of the as segment at the specified position. + * Direct access is not possible because of non-aligned reads. + * ATTENTION: no bounds check are done. + */ +u_int16_t +aspath_extract(const void *seg, int pos) { - int r; + const u_char *ptr = seg; + u_int16_t as = 0; - if (a1->hdr.len > a2->hdr.len) - return (1); - if (a1->hdr.len < a2->hdr.len) - return (-1); - r = memcmp(a1->data, a2->data, a1->hdr.len); - if (r > 0) - return (1); - if (r < 0) - return (-1); - return (0); + ptr += 2 + 2 * pos; + as = *ptr++; + as <<= 8; + as |= *ptr; + return (as); +} + +struct aspath * +aspath_lookup(const void *data, u_int16_t len) +{ + struct aspath_list *head; + struct aspath *aspath; + u_int32_t hash; + + hash = aspath_hash(data, len); + head = ASPATH_HASH(hash); + + LIST_FOREACH(aspath, head, entry) { + if (len == aspath->len && memcmp(data, aspath->data, len) == 0) + return (aspath); + } + return (NULL); +} + + +/* + * Returns a new prepended aspath. Old needs to be freed by caller. + */ +struct aspath * +aspath_prepend(struct aspath *asp, u_int16_t as, int quantum) +{ + u_char *p; + int len, overflow = 0, shift = 0, size, wpos = 0; + u_int8_t type; + + /* lunatic prepends are blocked in the parser and limited */ + + /* first calculate new size */ + if (asp->len > 0) { + if (asp->len < 2) + fatalx("aspath_prepend: bula bula"); + type = asp->data[0]; + size = asp->data[1]; + } else { + /* empty as path */ + type = AS_SET; + size = 0; + } + + if (quantum == 0) { + /* no change needed but increase refcnt as we return a copy */ + asp->refcnt++; + return (asp); + } else if (type == AS_SET || size + quantum > 255) { + /* need to attach a new AS_SEQUENCE */ + len = 2 + quantum * 2 + asp->len; + overflow = type == AS_SET ? quantum : (size + quantum) & 0xff; + } else + len = quantum * 2 + asp->len; + + quantum -= overflow; + + p = malloc(len); + if (p == NULL) + fatal("aspath_prepend"); + + /* first prepends */ + as = htons(as); + if (overflow > 0) { + p[wpos++] = AS_SEQUENCE; + p[wpos++] = overflow; + + for (; overflow > 0; overflow--) { + memcpy(p + wpos, &as, 2); + wpos += 2; + } + } + if (quantum > 0) { + shift = 2; + p[wpos++] = AS_SEQUENCE; + p[wpos++] = quantum + size; + + for (; quantum > 0; quantum--) { + memcpy(p + wpos, &as, 2); + wpos += 2; + } + } + memcpy(p + wpos, asp->data + shift, asp->len - shift); + + asp = aspath_get(p, len); + free(p); + + return (asp); } int @@ -1073,7 +1128,7 @@ aspath_match(struct aspath *a, enum as_spec type, u_int16_t as) u_int8_t i, seg_type, seg_len; if (type == AS_EMPTY) { - if (a->hdr.len == 0) + if (a->len == 0) return (1); else return (0); @@ -1081,7 +1136,7 @@ aspath_match(struct aspath *a, enum as_spec type, u_int16_t as) final = 0; seg = a->data; - for (len = a->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { seg_type = seg[0]; seg_len = seg[1]; seg_size = 2 + 2 * seg_len; @@ -1149,6 +1204,7 @@ community_set(struct attr *attr, int as, int type) attr->len += 4; if ((p = realloc(attr->data, attr->len)) == NULL) return (0); + attr->data = p; p = attr->data + attr->len - 4; } diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c index e42f58c36d4..1d116f75bb3 100644 --- a/usr.sbin/bgpd/rde_decide.c +++ b/usr.sbin/bgpd/rde_decide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide.c,v 1.36 2004/07/28 17:10:15 claudio Exp $ */ +/* $OpenBSD: rde_decide.c,v 1.37 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -132,10 +132,10 @@ prefix_cmp(struct prefix *p1, struct prefix *p2) return (asp1->flags.lpref - asp2->flags.lpref); /* 3. aspath count, the shorter the better */ - if ((asp2->flags.aspath->hdr.as_cnt - - asp1->flags.aspath->hdr.as_cnt) != 0) - return (asp2->flags.aspath->hdr.as_cnt - - asp1->flags.aspath->hdr.as_cnt); + if ((asp2->flags.aspath->ascnt - + asp1->flags.aspath->ascnt) != 0) + return (asp2->flags.aspath->ascnt - + asp1->flags.aspath->ascnt); /* 4. origin, the lower the better */ if ((asp2->flags.origin - asp1->flags.origin) != 0) diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index df96d864692..22d880364c5 100644 --- a/usr.sbin/bgpd/rde_filter.c +++ b/usr.sbin/bgpd/rde_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_filter.c,v 1.14 2004/08/05 15:58:21 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.15 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -58,6 +58,9 @@ rde_filter(struct rde_peer *peer, struct attr_flags *attrs, void rde_apply_set(struct attr_flags *attrs, struct filter_set *set) { + struct aspath *new; + u_int16_t as; + if (attrs == NULL) return; @@ -72,13 +75,10 @@ rde_apply_set(struct attr_flags *attrs, struct filter_set *set) if (set->flags & SET_NEXTHOP_BLACKHOLE) attrs->nexthop_blackhole = 1; if (set->flags & SET_PREPEND) { - /* - * The actual prepending is done afterwards because - * This could overflow but somebody that uses that many - * prepends is loony and needs professional help. - */ - attrs->aspath->hdr.prepend += set->prepend; - attrs->aspath->hdr.as_cnt += set->prepend; + as = rde_local_as(); + new = aspath_prepend(attrs->aspath, as, set->prepend); + aspath_put(attrs->aspath); + attrs->aspath = new; } if (set->flags & SET_PFTABLE) strlcpy(attrs->pftable, set->pftable, sizeof(attrs->pftable)); diff --git a/usr.sbin/bgpd/rde_prefix.c b/usr.sbin/bgpd/rde_prefix.c index 0a9155a0ea3..d4cc5854fe5 100644 --- a/usr.sbin/bgpd/rde_prefix.c +++ b/usr.sbin/bgpd/rde_prefix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_prefix.c,v 1.17 2004/08/03 14:46:23 claudio Exp $ */ +/* $OpenBSD: rde_prefix.c,v 1.18 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -270,7 +270,7 @@ pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b) int i; if (a->af != b->af) - fatalx("king bula sez: comapring pears with apples"); + fatalx("king bula sez: comapring pears with apples"); switch (a->af) { case AF_INET: diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 5e0c5d6390c..482f73d139b 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.52 2004/08/05 16:26:56 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.53 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -73,7 +73,8 @@ static void path_free(struct rde_aspath *); struct path_table pathtable; #define PATH_HASH(x) \ - &pathtable.path_hashtbl[aspath_hash((x)) & pathtable.path_hashmask] + &pathtable.path_hashtbl[aspath_hash((x)->data, (x)->len) & \ + pathtable.path_hashmask] void path_init(u_int32_t hashsize) diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index d26bd2e30cc..8b442352305 100644 --- a/usr.sbin/bgpd/rde_update.c +++ b/usr.sbin/bgpd/rde_update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.25 2004/08/05 16:26:56 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.26 2004/08/05 18:44:19 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -283,7 +283,7 @@ up_generate_updates(struct rde_peer *peer, * pass only prefix that have a aspath count * of zero this is equal to the ^$ regex. */ - if (old->aspath->flags.aspath->hdr.as_cnt != 0) + if (old->aspath->flags.aspath->ascnt != 0) return; break; } @@ -385,7 +385,7 @@ up_generate_updates(struct rde_peer *peer, * pass only prefix that have a aspath count * of zero this is equal to the ^$ regex. */ - if (new->aspath->flags.aspath->hdr.as_cnt != 0) { + if (new->aspath->flags.aspath->ascnt != 0) { up_generate_updates(peer, NULL, old); return; } @@ -455,7 +455,8 @@ up_generate_updates(struct rde_peer *peer, * use aspath_hash as attr_hash, this may be unoptimal * but currently I don't care. */ - a->attr_hash = aspath_hash(attrs.aspath); + a->attr_hash = aspath_hash(attrs.aspath->data, + attrs.aspath->len); p->prefix = addr; p->prefixlen = new->prefix->prefixlen; @@ -480,7 +481,7 @@ up_generate_default(struct rde_peer *peer, sa_family_t af) bzero(&addr, sizeof(addr)); bzero(&nexthop, sizeof(nexthop)); - attrs.aspath = aspath_create(NULL, 0); + attrs.aspath = aspath_get(NULL, 0); attrs.nexthop.s_addr = INADDR_ANY; /* med = 0 */ attrs.lpref = DEFAULT_LPREF; @@ -521,7 +522,7 @@ up_generate_default(struct rde_peer *peer, sa_family_t af) * use aspath_hash as attr_hash, this may be unoptimal * but currently I don't care. */ - a->attr_hash = aspath_hash(attrs.aspath); + a->attr_hash = aspath_hash(attrs.aspath->data, attrs.aspath->len); p->prefix = addr; p->prefixlen = 0; /* default route */ @@ -539,6 +540,7 @@ int up_generate_attr(struct rde_peer *peer, struct update_attr *upa, struct attr_flags *a, struct nexthop *nh) { + struct aspath *path; struct attr *oa; u_int32_t tmp32; in_addr_t nexthop, mask; @@ -552,9 +554,11 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa, wlen += r; len -= r; /* aspath */ - if ((r = aspath_write(up_attr_buf + wlen, len, a->aspath, - rde_local_as(), peer->conf.ebgp)) == -1) + path = aspath_prepend(a->aspath, rde_local_as(), peer->conf.ebgp); + if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, + ATTR_ASPATH, path->data, path->len)) == -1) return (-1); + aspath_put(path); wlen += r; len -= r; /* nexthop, already network byte order */ |