File: [local] / src / usr.sbin / bgpd / rde.h (download)
Revision 1.36, Thu Mar 11 17:12:51 2004 UTC (20 years, 2 months ago) by claudio
Branch: MAIN
CVS Tags: OPENBSD_3_5_BASE, OPENBSD_3_5 Changes since 1.35: +6 -2 lines
Add basic support for communities. Currently it is only possible to filter
on communities, e.g match from any community 24640:* set localpref 666
OK henning@
|
/* $OpenBSD: rde.h,v 1.36 2004/03/11 17:12:51 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
* Andre Oppermann <oppermann@pipeline.ch>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __RDE_H__
#define __RDE_H__
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include "bgpd.h"
/* XXX generic stuff, should be somewhere else */
/* Address Family Numbers as per rfc1700 */
#define AFI_IPv4 1
#define AFI_IPv6 2
/* Subsequent Address Family Identifier as per rfc2858 */
#define SAFI_UNICAST 1
#define SAFI_MULTICAST 2
#define SAFI_BOTH 3
/* rde internal structures */
enum peer_state {
PEER_NONE,
PEER_DOWN,
PEER_UP,
PEER_ERR /* error occured going to PEER_DOWN state */
};
/*
* How do we identify peers between the session handler and the rde?
* Currently I assume that we can do that with the neighbor_ip...
*/
LIST_HEAD(rde_peer_head, rde_peer);
LIST_HEAD(aspath_head, rde_aspath);
RB_HEAD(uptree_prefix, update_prefix);
RB_HEAD(uptree_attr, update_attr);
TAILQ_HEAD(uplist_prefix, update_prefix);
TAILQ_HEAD(uplist_attr, update_attr);
struct rde_peer {
LIST_ENTRY(rde_peer) hash_l; /* hash list over all peers */
LIST_ENTRY(rde_peer) peer_l; /* list of all peers */
struct aspath_head path_h; /* list of all as paths */
struct peer_config conf;
enum peer_state state;
u_int32_t prefix_cnt;
u_int32_t remote_bgpid;
struct bgpd_addr remote_addr;
struct bgpd_addr local_addr;
u_int32_t up_pcnt;
u_int32_t up_acnt;
u_int32_t up_nlricnt;
u_int32_t up_wcnt;
struct uptree_prefix up_prefix;
struct uptree_attr up_attrs;
struct uplist_attr updates;
struct uplist_prefix withdraws;
};
#define AS_SET 1
#define AS_SEQUENCE 2
#define ASPATH_HEADER_SIZE sizeof(struct aspath_hdr)
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;
};
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.
*/
};
enum attrtypes {
ATTR_UNDEF,
ATTR_ORIGIN,
ATTR_ASPATH,
ATTR_NEXTHOP,
ATTR_MED,
ATTR_LOCALPREF,
ATTR_ATOMIC_AGGREGATE,
ATTR_AGGREGATOR,
ATTR_COMMUNITIES
};
/* attribute flags. 4 low order bits reserved */
#define ATTR_EXTLEN 0x10
#define ATTR_PARTIAL 0x20
#define ATTR_TRANSITIVE 0x40
#define ATTR_OPTIONAL 0x80
/* default attribute flags for well known attributes */
#define ATTR_WELL_KNOWN ATTR_TRANSITIVE
struct attr {
u_int8_t flags;
u_int8_t type;
u_int16_t len;
u_char *data;
TAILQ_ENTRY(attr) attr_l;
};
TAILQ_HEAD(attr_list, attr);
#define ORIGIN_IGP 0
#define ORIGIN_EGP 1
#define ORIGIN_INCOMPLETE 2
struct attr_flags {
struct aspath *aspath;
struct in_addr nexthop; /* exit nexthop */
u_int32_t med; /* multi exit disc */
u_int32_t lpref; /* local pref */
u_int8_t origin;
u_int8_t wflags; /* internally used */
struct attr_list others;
};
enum nexthop_state {
NEXTHOP_LOOKUP,
NEXTHOP_UNREACH,
NEXTHOP_REACH
};
struct nexthop {
LIST_ENTRY(nexthop) nexthop_l;
enum nexthop_state state;
#if 0
/*
* currently we use the boolean nexthop state, this could be exchanged
* with a variable coast with a max for unreachable.
*/
u_int32_t costs;
#endif
struct aspath_head path_h;
struct bgpd_addr exit_nexthop;
struct bgpd_addr true_nexthop;
struct bgpd_addr nexthop_net;
u_int8_t nexthop_netlen;
u_int8_t flags;
#define NEXTHOP_CONNECTED 0x1
#define NEXTHOP_ANNOUNCE 0x2
};
struct path_table {
struct aspath_head *path_hashtbl;
u_int32_t path_hashmask;
};
LIST_HEAD(prefix_head, prefix);
struct rde_aspath {
LIST_ENTRY(rde_aspath) peer_l, path_l, nexthop_l;
struct prefix_head prefix_h;
struct rde_peer *peer;
struct nexthop *nexthop;
u_int16_t prefix_cnt; /* # of prefixes */
u_int16_t active_cnt; /* # of active prefixes */
struct attr_flags flags;
};
struct pt_entry {
LIST_ENTRY(pt_entry) pt_l; /* currently we are using a
hash list for prefixes */
struct bgpd_addr prefix;
u_int8_t prefixlen;
struct prefix_head prefix_h;
struct prefix *active; /* for fast access */
/*
* Route Flap Damping structures
* Currently I think they belong into the prefix but for the moment
* we just ignore the dampening at all.
*/
};
struct prefix {
LIST_ENTRY(prefix) prefix_l, path_l;
struct rde_aspath *aspath;
struct pt_entry *prefix;
struct rde_peer *peer;
time_t lastchange;
/* currently I can't think of additional prefix flags.
* NOTE: the selected route is stored in prefix->active */
};
/* prototypes */
/* rde.c */
void rde_send_kroute(struct prefix *, struct prefix *);
void rde_send_nexthop(struct bgpd_addr *, int);
void rde_generate_updates(struct prefix *, struct prefix *);
u_int16_t rde_local_as(void);
int rde_noevaluate(void);
/* rde_attr.c */
void attr_init(struct attr_flags *);
int attr_parse(u_char *, u_int16_t, struct attr_flags *, int,
enum enforce_as, u_int16_t);
u_char *attr_error(u_char *, u_int16_t, struct attr_flags *,
u_int8_t *, u_int16_t *);
u_int8_t attr_missing(struct attr_flags *, int);
int attr_compare(struct attr_flags *, struct attr_flags *);
void attr_copy(struct attr_flags *, struct attr_flags *);
void attr_move(struct attr_flags *, struct attr_flags *);
void attr_free(struct attr_flags *);
int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *,
u_int16_t);
int attr_optadd(struct attr_flags *, u_int8_t, u_int8_t,
u_char *, u_int16_t);
struct attr *attr_optget(struct attr_flags *, u_int8_t);
void attr_optfree(struct attr_flags *);
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);
u_char *aspath_dump(struct aspath *);
u_int16_t aspath_length(struct aspath *);
u_int16_t aspath_count(struct aspath *);
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 *);
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);
int aspath_match(struct aspath *, enum as_spec, u_int16_t);
int community_match(void *, u_int16_t, int, int);
/* rde_rib.c */
void path_init(u_int32_t);
void path_shutdown(void);
void path_update(struct rde_peer *, struct attr_flags *,
struct bgpd_addr *, int);
struct rde_aspath *path_get(struct aspath *, struct rde_peer *);
struct rde_aspath *path_add(struct rde_peer *, struct attr_flags *);
void path_remove(struct rde_aspath *);
void path_updateall(struct rde_aspath *, enum nexthop_state);
void path_destroy(struct rde_aspath *);
int path_empty(struct rde_aspath *);
struct prefix *prefix_get(struct rde_aspath *, struct bgpd_addr *, int);
struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int);
struct pt_entry *prefix_move(struct rde_aspath *, struct prefix *);
void prefix_remove(struct rde_peer *, struct bgpd_addr *, int);
struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *);
void prefix_updateall(struct rde_aspath *, enum nexthop_state);
void prefix_destroy(struct prefix *);
void prefix_network_clean(struct rde_peer *, time_t);
void nexthop_init(u_int32_t);
void nexthop_shutdown(void);
void nexthop_add(struct rde_aspath *);
void nexthop_remove(struct rde_aspath *);
void nexthop_update(struct kroute_nexthop *);
/* rde_decide.c */
void prefix_evaluate(struct prefix *, struct pt_entry *);
void up_init(struct rde_peer *);
void up_down(struct rde_peer *);
void up_generate_updates(struct rde_peer *,
struct prefix *, struct prefix *);
int up_dump_prefix(u_char *, int, struct uplist_prefix *,
struct rde_peer *);
int up_dump_attrnlri(u_char *, int, struct rde_peer *);
void up_dump_upcall(struct pt_entry *, void *);
/* rde_prefix.c */
void pt_init(void);
void pt_shutdown(void);
int pt_empty(struct pt_entry *);
struct pt_entry *pt_get(struct bgpd_addr *, int);
struct pt_entry *pt_add(struct bgpd_addr *, int);
void pt_remove(struct pt_entry *);
struct pt_entry *pt_lookup(struct bgpd_addr *);
void pt_dump(void (*)(struct pt_entry *, void *), void *);
/* rde_filter.c */
enum filter_actions rde_filter(struct rde_peer *, struct attr_flags *,
struct bgpd_addr *, u_int8_t, enum directions);
void rde_apply_set(struct attr_flags *, struct filter_set *);
int rde_filter_community(struct attr_flags *, int, int);
#endif /* __RDE_H__ */