diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-01-10 16:20:30 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-01-10 16:20:30 +0000 |
commit | d8df3d2156171ba2242d297a4dbb9363795d506e (patch) | |
tree | c65ff19e7c8cee3ff128e4d5cb68f0b9b35026ca /usr.sbin/bgpd/mrt.c | |
parent | 67805e42d42678d6bd124985db26f5eef7e82a3d (diff) |
RDE update generation. First we queue all updates and withdraws on a per
peer basis. A queue runner will dequeue and package those messages to valid
bgp UPDATE messages and send them to the SE.
Not yet done is per peer type attribute handling (like aspath prepends and
nexthop modifications) and the queue runner could be a tad smarter. All in
all this gives us a good starting point for the missing parts.
OK henning@
Diffstat (limited to 'usr.sbin/bgpd/mrt.c')
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 92 |
1 files changed, 84 insertions, 8 deletions
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c index a2a029e0276..4e68ae09e12 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.19 2004/01/07 12:34:23 claudio Exp $ */ +/* $OpenBSD: mrt.c,v 1.20 2004/01/10 16:20:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -38,10 +38,13 @@ * XXX imsg_create(), imsg_add(), imsg_close() ... */ -static int mrt_dump_entry(struct mrt_config *, struct prefix *, u_int16_t, - struct peer_config *); -static int mrt_dump_header(struct buf *, u_int16_t, u_int16_t, u_int32_t); -static int mrt_open(struct mrt *); +static u_int16_t mrt_attr_length(struct attr_flags *); +static int mrt_attr_dump(void *, u_int16_t, struct attr_flags *); +static int mrt_dump_entry(struct mrt_config *, struct prefix *, + u_int16_t, struct peer_config *); +static int mrt_dump_header(struct buf *, u_int16_t, u_int16_t, + u_int32_t); +static int mrt_open(struct mrt *); #define DUMP_BYTE(x, b) \ do { \ @@ -196,6 +199,79 @@ mrt_dump_state(struct mrt_config *mrt, u_int16_t old_state, u_int16_t new_state, } +static u_int16_t +mrt_attr_length(struct attr_flags *a) +{ + struct attr *oa; + u_int16_t alen, plen; + + alen = 4 /* origin */ + 7 /* nexthop */ + 7 /* lpref */; + plen = aspath_length(a->aspath); + alen += 2 + plen + (plen > 255 ? 2 : 1); + if (a->med != 0) + alen += 7; + + TAILQ_FOREACH(oa, &a->others, attr_l) + alen += 2 + oa->len + (oa->len > 255 ? 2 : 1); + + return alen; +} + +static int +mrt_attr_dump(void *p, u_int16_t len, struct attr_flags *a) +{ + struct attr *oa; + u_char *buf = p; + u_int32_t tmp32; + int r; + u_int16_t aslen, wlen = 0; + + /* origin */ + if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ORIGIN, + &a->origin, 1)) == -1) + return (-1); + wlen += r; len -= r; + + /* aspath */ + aslen = aspath_length(a->aspath); + if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ASPATH, + aspath_dump(a->aspath), aslen)) == -1) + return (-1); + wlen += r; len -= r; + + /* nexthop, already network byte order */ + if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_NEXTHOP, + &a->nexthop, 4)) == -1) + return (-1); + wlen += r; len -= r; + + /* MED, non transitive */ + if (a->med != 0) { + tmp32 = htonl(a->med); + if ((r = attr_write(buf + wlen, len, ATTR_OPTIONAL, ATTR_MED, + &tmp32, 4)) == -1) + return (-1); + wlen += r; len -= r; + } + + /* local preference, only valid for ibgp */ + tmp32 = htonl(a->lpref); + if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_LOCALPREF, + &tmp32, 4)) == -1) + return (-1); + wlen += r; len -= r; + + /* dump all other path attributes without modification */ + TAILQ_FOREACH(oa, &a->others, attr_l) { + if ((r = attr_write(buf + wlen, len, oa->flags, oa->type, + oa->data, oa->len)) == -1) + return (-1); + wlen += r; len -= r; + } + + return (wlen); +} + static int mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum, struct peer_config *peer) @@ -206,7 +282,7 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum, u_int16_t len, attr_len; int n; - attr_len = attr_length(&p->aspath->flags); + attr_len = mrt_attr_length(&p->aspath->flags); len = MRT_DUMP_HEADER_SIZE + attr_len; hdr.len = len + IMSG_HEADER_SIZE + MRT_HEADER_SIZE; @@ -244,8 +320,8 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum, return (-1); } - if (attr_dump(bptr, attr_len, &p->aspath->flags) == -1) { - logit(LOG_ERR, "mrt_dump_entry: attr_dump error"); + if (mrt_attr_dump(bptr, attr_len, &p->aspath->flags) == -1) { + logit(LOG_ERR, "mrt_dump_entry: mrt_attr_dump error"); buf_free(buf); return (-1); } |