summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/rde_rib.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2004-02-04 09:18:04 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2004-02-04 09:18:04 +0000
commitc5a79481f4ad51906a5e820f0859c7b6c8eaff38 (patch)
treec9091994773045c5658a24baf9614f0fd811dbc5 /usr.sbin/bgpd/rde_rib.c
parent69202d1cee69e24f375c90a4cd6fd55ee1afccbc (diff)
Move BGP path attribute handling functions in a own file. henning@ conceptual ok
Diffstat (limited to 'usr.sbin/bgpd/rde_rib.c')
-rw-r--r--usr.sbin/bgpd/rde_rib.c429
1 files changed, 1 insertions, 428 deletions
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 9fad5ce7bcb..b30d3d63a84 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.31 2004/02/02 19:14:11 deraadt Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.32 2004/02/04 09:18:03 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -18,11 +18,7 @@
#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -39,9 +35,6 @@
*/
struct rib_stats {
- u_int64_t attr_copy;
- u_int64_t aspath_create;
- u_int64_t aspath_destroy;
u_int64_t path_update;
u_int64_t path_get;
u_int64_t path_add;
@@ -77,420 +70,6 @@ struct rib_stats {
*/
#define MAX_PREFIX_PER_AS 1500
-/* attribute specific functions */
-void attr_optfree(struct attr_flags *);
-
-int
-attr_compare(struct attr_flags *a, struct attr_flags *b)
-{
- struct attr *oa, *ob;
- int r;
-
- if (a->origin > b->origin)
- return (1);
- if (a->origin < b->origin)
- return (-1);
- if (a->nexthop > b->nexthop)
- return (1);
- if (a->nexthop < b->nexthop)
- return (-1);
- if (a->med > b->med)
- return (1);
- if (a->med < b->med)
- return (-1);
- if (a->lpref > b->lpref)
- return (1);
- if (a->lpref < b->lpref)
- return (-1);
- r = aspath_compare(a->aspath, b->aspath);
- if (r > 0)
- return (1);
- if (r < 0)
- return (-1);
-
- for (oa = TAILQ_FIRST(&a->others), ob = TAILQ_FIRST(&b->others);
- oa != TAILQ_END(&a->others) && ob != TAILQ_END(&a->others);
- oa = TAILQ_NEXT(oa, attr_l), ob = TAILQ_NEXT(ob, attr_l)) {
- if (oa->type > ob->type)
- return (1);
- if (oa->type < ob->type)
- return (-1);
- if (oa->len > ob->len)
- return (1);
- if (oa->len < ob->len)
- return (-1);
- r = memcmp(oa->data, ob->data, oa->len);
- if (r > 0)
- return (1);
- if (r < 0)
- return (-1);
- }
- if (oa != TAILQ_END(&a->others))
- return (1);
- if (ob != TAILQ_END(&a->others))
- return (-1);
- return (0);
-}
-
-void
-attr_copy(struct attr_flags *t, struct attr_flags *s)
-{
- struct attr *os;
- /*
- * first copy the full struct, then replace the path and tags with
- * a own copy.
- */
- memcpy(t, s, sizeof(struct attr_flags));
- t->aspath = aspath_create(s->aspath->data, s->aspath->hdr.len);
- TAILQ_INIT(&t->others);
- TAILQ_FOREACH(os, &s->others, attr_l)
- attr_optadd(t, os->flags, os->type, os->data, os->len);
-}
-
-int
-attr_write(void *p, u_int16_t p_len, u_int8_t flags, u_int8_t type,
- void *data, u_int16_t data_len)
-{
- u_char *b = p;
- u_int16_t tmp, tot_len = 2; /* attribute header (without len) */
-
- if (data_len > 255) {
- tot_len += 2 + data_len;
- flags |= ATTR_EXTLEN;
- } else
- tot_len += 1 + data_len;
-
- if (tot_len > p_len)
- return (-1);
-
- *b++ = flags;
- *b++ = type;
- if (data_len > 255) {
- tmp = htons(data_len);
- memcpy(b, &tmp, 2);
- b += 2;
- } else
- *b++ = (u_char)(data_len & 0xff);
-
- if (data_len != 0)
- memcpy(b, data, data_len);
-
- return (tot_len);
-}
-
-void
-attr_optadd(struct attr_flags *attr, u_int8_t flags, u_int8_t type,
- u_char *data, u_int16_t len)
-{
- struct attr *a, *p;
-
- if (flags & ATTR_OPTIONAL && ! flags & ATTR_TRANSITIVE)
- /*
- * We already know that we're not intrested in this attribute.
- * Currently only the MED is optional and non-transitive but
- * MED is directly stored in struct attr_flags.
- */
- return;
-
- a = calloc(1, sizeof(struct attr));
- if (a == NULL)
- fatal("attr_optadd");
- a->flags = flags;
- a->type = type;
- a->len = len;
- if (len != 0) {
- a->data = malloc(len);
- if (a->data == NULL)
- fatal("attr_optadd");
- memcpy(a->data, data, len);
- }
- /* keep a sorted list */
- TAILQ_FOREACH_REVERSE(p, &attr->others, attr_l, attr_list) {
- if (type > p->type) {
- TAILQ_INSERT_AFTER(&attr->others, p, a, attr_l);
- return;
- }
- ENSURE(type != p->type);
- }
-}
-
-void
-attr_optfree(struct attr_flags *attr)
-{
- struct attr *a, *xa;
-
- for (a = TAILQ_FIRST(&attr->others); a != TAILQ_END(&attr->others);
- a = xa) {
- xa = TAILQ_NEXT(a, attr_l);
- free(a->data);
- free(a);
- }
-}
-
-/* aspath specific functions */
-
-/* TODO
- * aspath loop detection (partially done I think),
- * aspath regexp search,
- * aspath to string converter
- */
-static u_int16_t aspath_extract(void *, int);
-
-/*
- * 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;
-
- ENSURE(0 <= pos && pos < 255);
-
- ptr += 2 + 2 * pos;
- as = *ptr++;
- as <<= 8;
- as |= *ptr;
- return as;
-}
-
-int
-aspath_verify(void *data, u_int16_t len, u_int16_t myAS)
-{
- u_int8_t *seg = data;
- u_int16_t seg_size;
- u_int8_t i, seg_len, seg_type;
-
- for (; len > 0; len -= seg_size, seg += seg_size) {
- seg_type = seg[0];
- seg_len = seg[1];
- if (seg_type != AS_SET && seg_type != AS_SEQUENCE) {
- return AS_ERR_TYPE;
- }
- seg_size = 2 + 2 * seg_len;
-
- if (seg_size > len)
- return AS_ERR_LEN;
-
- if (seg_size == 0)
- /* empty aspath segment are not allowed */
- return AS_ERR_BAD;
-
- for (i = 0; i < seg_len; i++) {
- if (myAS == aspath_extract(seg, i))
- return AS_ERR_LOOP;
- }
- }
- return 0; /* all OK */
-}
-
-struct aspath *
-aspath_create(void *data, u_int16_t len)
-{
- struct aspath *aspath;
-
- RIB_STAT(aspath_create);
-
- /* 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);
-
- aspath->hdr.as_cnt = aspath_count(aspath);
-
- return aspath;
-}
-
-int
-aspath_write(void *p, u_int16_t len, struct aspath *aspath, u_int16_t myAS,
- int prepend)
-{
- u_char *b = p;
- int tot_len, as_len, size, wpos = 0;
- u_int16_t tmp;
- u_int8_t type, attr_flag = ATTR_WELL_KNOWN;
-
- if (prepend > 255)
- /* lunatic prepends need to be blocked in the parser */
- return (-1);
-
- /* first calculate new size */
- if (aspath->hdr.len > 0) {
- ENSURE(aspath->hdr.len > 2);
- type = aspath->data[0];
- size = aspath->data[1];
- } else {
- /* empty as path */
- type = AS_SET;
- size = 0;
- }
- 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);
-
- /* 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);
-}
-
-void
-aspath_destroy(struct aspath *aspath)
-{
- RIB_STAT(aspath_destroy);
- /* currently there is only the aspath that needs to be freed */
- free(aspath);
-}
-
-u_char *
-aspath_dump(struct aspath *aspath)
-{
- return aspath->data;
-}
-
-u_int16_t
-aspath_length(struct aspath *aspath)
-{
- return aspath->hdr.len;
-}
-
-u_int16_t
-aspath_count(struct aspath *aspath)
-{
- u_int8_t *seg;
- u_int16_t cnt, len, 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_type = seg[0];
- seg_len = seg[1];
- ENSURE(seg_type == AS_SET || seg_type == AS_SEQUENCE);
- seg_size = 2 + 2 * seg_len;
-
- if (seg_type == AS_SET)
- cnt += 1;
- else
- cnt += seg_len;
- }
- return cnt;
-}
-
-u_int16_t
-aspath_neighbour(struct aspath *aspath)
-{
- /*
- * Empty aspath is OK -- internal as route.
- * But what is the neighbour? For now let's return 0 that
- * should not break anything.
- */
-
- if (aspath->hdr.len == 0)
- return 0;
-
- ENSURE(aspath->hdr.len > 2);
- return aspath_extract(aspath->data, 0);
-}
-
-#define AS_HASH_INITIAL 8271
-
-u_long
-aspath_hash(struct aspath *aspath)
-{
- u_int8_t *seg;
- u_long hash;
- u_int16_t len, 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_type = seg[0];
- seg_len = seg[1];
- ENSURE(seg_type == AS_SET || seg_type == AS_SEQUENCE);
- seg_size = 2 + 2 * seg_len;
-
- ENSURE(seg_size <= len);
- for (i = 0; i < seg_len; i++) {
- hash += (hash << 5);
- hash ^= aspath_extract(seg, i);
- }
- }
- return hash;
-}
-
-int
-aspath_compare(struct aspath *a1, struct aspath *a2)
-{
- int r;
-
- 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;
-}
-
/* path specific functions */
static void path_link(struct rde_aspath *, struct rde_peer *);
@@ -796,9 +375,6 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
* the prefix without changing the peer.
*/
/* XXX for debugging */
- if (asp->prefix_cnt == MAX_PREFIX_PER_AS)
- log_warnx("RDE: prefix hog, prefix %s/%d",
- inet_ntoa(np->prefix->prefix.v4), np->prefix->prefixlen);
ENSURE(asp->prefix_cnt < MAX_PREFIX_PER_AS);
/*
@@ -973,9 +549,6 @@ prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp)
asp->peer->prefix_cnt++;
/* XXX for debugging */
- if (asp->prefix_cnt == MAX_PREFIX_PER_AS)
- log_warnx("RDE: prefix hog, prefix %s/%d",
- inet_ntoa(pte->prefix.v4), pte->prefixlen);
ENSURE(asp->prefix_cnt < MAX_PREFIX_PER_AS);
pref->aspath = asp;