/* $OpenBSD: rde.h,v 1.23 2004/02/09 01:56:18 henning Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker and * Andre Oppermann * * 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 #include #include #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; /* total number of AS's */ /* probably we should switch these to int or something similar */ /* char *str; string representation of aspath for regex search. */ }; 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 }; /* 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; in_addr_t nexthop; /* exit nexthop */ u_int32_t med; /* multi exit disc */ u_int32_t lpref; /* local pref */ u_int8_t origin; 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 }; 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; int 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); /* rde_rib.c */ int attr_compare(struct attr_flags *, struct attr_flags *); void attr_copy(struct attr_flags *, struct attr_flags *); int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *, u_int16_t); void attr_optadd(struct attr_flags *, u_int8_t, u_int8_t, u_char *, u_int16_t); void attr_optfree(struct attr_flags *); int aspath_verify(void *, u_int16_t, u_int16_t); #define AS_ERR_LOOP -1 #define AS_ERR_LEN -2 #define AS_ERR_TYPE -3 #define AS_ERR_BAD -4 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_neighbour(struct aspath *); u_int32_t aspath_hash(struct aspath *); int aspath_compare(struct aspath *, struct aspath *); void path_init(u_int32_t); 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_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); 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 *); #endif /* __RDE_H__ */