OpenBSD-4.6/usr.sbin/bgpd/rde.h

Compare this file to the similar file:
Show the results in this format:

/*	$OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 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"

/* rde internal structures */

enum peer_state {
	PEER_NONE,
	PEER_DOWN,
	PEER_UP,
	PEER_ERR	/* error occurred 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);
RB_HEAD(rib_tree, rib_entry);
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;
	struct bgpd_addr		 remote_addr;
	struct bgpd_addr		 local_v4_addr;
	struct bgpd_addr		 local_v6_addr;
	struct uptree_prefix		 up_prefix;
	struct uptree_attr		 up_attrs;
	struct uplist_attr		 updates;
	struct uplist_prefix		 withdraws;
	struct uplist_attr		 updates6;
	struct uplist_prefix		 withdraws6;
	struct capabilities		 capa_announced;
	struct capabilities		 capa_received;
	u_int64_t			 prefix_rcvd_update;
	u_int64_t			 prefix_rcvd_withdraw;
	u_int64_t			 prefix_sent_update;
	u_int64_t			 prefix_sent_withdraw;
	u_int32_t			 prefix_cnt; /* # of prefixes */
	u_int32_t			 remote_bgpid; /* host byte order! */
	u_int32_t			 up_pcnt;
	u_int32_t			 up_acnt;
	u_int32_t			 up_nlricnt;
	u_int32_t			 up_wcnt;
	enum peer_state			 state;
	u_int16_t			 ribid;
	u_int16_t			 short_as;
	u_int8_t			 reconf_in;	/* in filter changed */
	u_int8_t			 reconf_out;	/* out filter changed */
};

#define AS_SET			1
#define AS_SEQUENCE		2
#define ASPATH_HEADER_SIZE	(sizeof(struct aspath) - sizeof(u_char))

LIST_HEAD(aspath_list, aspath);

struct aspath {
	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[1]; /* placeholder for actual data */
};

enum attrtypes {
	ATTR_UNDEF,
	ATTR_ORIGIN,
	ATTR_ASPATH,
	ATTR_NEXTHOP,
	ATTR_MED,
	ATTR_LOCALPREF,
	ATTR_ATOMIC_AGGREGATE,
	ATTR_AGGREGATOR,
	ATTR_COMMUNITIES,
	ATTR_ORIGINATOR_ID,
	ATTR_CLUSTER_LIST,
	ATTR_MP_REACH_NLRI=14,
	ATTR_MP_UNREACH_NLRI=15,
	ATTR_EXT_COMMUNITIES=16,
	ATTR_AS4_PATH=17,
	ATTR_AS4_AGGREGATOR=18
};

/* 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 {
	LIST_ENTRY(attr)		 entry;
	u_char				*data;
	int				 refcnt;
	u_int32_t			 hash;
	u_int16_t			 len;
	u_int8_t			 flags;
	u_int8_t			 type;
};

struct mpattr {
	void		*reach;
	void		*unreach;
	u_int16_t	 reach_len;
	u_int16_t	 unreach_len;
};

LIST_HEAD(attr_list, attr);

struct path_table {
	struct aspath_head	*path_hashtbl;
	u_int32_t		 path_hashmask;
};

LIST_HEAD(prefix_head, prefix);

#define	F_ATTR_ORIGIN		0x00001
#define	F_ATTR_ASPATH		0x00002
#define	F_ATTR_NEXTHOP		0x00004
#define	F_ATTR_LOCALPREF	0x00008
#define	F_ATTR_MED		0x00010
#define	F_ATTR_MED_ANNOUNCE	0x00020
#define	F_ATTR_MP_REACH		0x00040
#define	F_ATTR_MP_UNREACH	0x00080
#define	F_ATTR_AS4BYTE_NEW	0x00100	/* AS4_PATH or AS4_AGGREGATOR */
#define	F_ATTR_LOOP		0x00200 /* path would cause a route loop */
#define	F_PREFIX_ANNOUNCED	0x00400
#define	F_ANN_DYNAMIC		0x00800
#define	F_NEXTHOP_SELF		0x01000
#define	F_NEXTHOP_REJECT	0x02000
#define	F_NEXTHOP_BLACKHOLE	0x04000
#define	F_NEXTHOP_NOMODIFY	0x08000
#define	F_ATTR_LINKED		0x20000


#define ORIGIN_IGP		0
#define ORIGIN_EGP		1
#define ORIGIN_INCOMPLETE	2

#define DEFAULT_LPREF		100

struct rde_aspath {
	LIST_ENTRY(rde_aspath)		 path_l, peer_l, nexthop_l;
	struct prefix_head		 prefix_h;
	struct attr			**others;
	struct rde_peer			*peer;
	struct aspath			*aspath;
	struct nexthop			*nexthop;	/* may be NULL */
	u_int32_t			 med;		/* multi exit disc */
	u_int32_t			 lpref;		/* local pref */
	u_int32_t			 weight;	/* low prio lpref */
	u_int32_t			 prefix_cnt; /* # of prefixes */
	u_int32_t			 active_cnt; /* # of active prefixes */
	u_int32_t			 flags;		/* internally used */
	u_int16_t			 rtlabelid;	/* route label id */
	u_int16_t			 pftableid;	/* pf table id */
	u_int8_t			 origin;
	u_int8_t			 others_len;
};

enum nexthop_state {
	NEXTHOP_LOOKUP,
	NEXTHOP_UNREACH,
	NEXTHOP_REACH
};

struct nexthop {
	LIST_ENTRY(nexthop)	nexthop_l;
	struct aspath_head	path_h;
	struct bgpd_addr	exit_nexthop;
	struct bgpd_addr	true_nexthop;
	struct bgpd_addr	nexthop_net;
#if 0
	/*
	 * currently we use the boolean nexthop state, this could be exchanged
	 * with a variable cost with a max for unreachable.
	 */
	u_int32_t		costs;
#endif
	int			refcnt;	/* filterset reference counter */
	enum nexthop_state	state;
	u_int8_t		nexthop_netlen;
	u_int8_t		flags;
#define NEXTHOP_CONNECTED	0x01
};

/* generic entry without address specific part */
struct pt_entry {
	RB_ENTRY(pt_entry)		 pt_e;
	sa_family_t			 af;
	u_int8_t			 prefixlen;
	u_int16_t			 refcnt;
};

struct pt_entry4 {
	RB_ENTRY(pt_entry)		 pt_e;
	sa_family_t			 af;
	u_int8_t			 prefixlen;
	u_int16_t			 refcnt;
	struct in_addr			 prefix4;
};

struct pt_entry6 {
	RB_ENTRY(pt_entry)		 pt_e;
	sa_family_t			 af;
	u_int8_t			 prefixlen;
	u_int16_t			 refcnt;
	struct in6_addr			 prefix6;
};

struct rib_context {
	LIST_ENTRY(rib_context)		 entry;
	struct rib_entry		*ctx_re;
	struct rib			*ctx_rib;
	void		(*ctx_upcall)(struct rib_entry *, void *);
	void		(*ctx_done)(void *);
	void		(*ctx_wait)(void *);
	void				*ctx_arg;
	unsigned int			 ctx_count;
	sa_family_t			 ctx_af;
};

struct rib_entry {
	RB_ENTRY(rib_entry)	 rib_e;
	struct prefix_head	 prefix_h;
	struct prefix		*active; /* for fast access */
	struct pt_entry		*prefix;
	u_int16_t		 ribid;
	u_int16_t		 flags;
};

enum rib_state {
	RIB_NONE,
	RIB_ACTIVE,
	RIB_DELETE
};

struct rib {
	char			name[PEER_DESCR_LEN];
	struct rib_tree		rib;
	enum rib_state		state;
	u_int16_t		flags;
	u_int16_t		id;
};

#define F_RIB_ENTRYLOCK		0x0001
#define F_RIB_NOEVALUATE	0x0002
#define F_RIB_NOFIB		0x0004
#define RIB_FAILED		0xffff

struct prefix {
	LIST_ENTRY(prefix)		 rib_l, path_l;
	struct rde_aspath		*aspath;
	struct pt_entry			*prefix;
	struct rib_entry		*rib;	/* NULL for Adj-RIB-In */
	time_t				 lastchange;
};

extern struct rde_memstats rdemem;

/* prototypes */
/* rde.c */
void		 rde_send_kroute(struct prefix *, struct prefix *);
void		 rde_send_nexthop(struct bgpd_addr *, int);
void		 rde_send_pftable(u_int16_t, struct bgpd_addr *,
		     u_int8_t, int);
void		 rde_send_pftable_commit(void);

void		 rde_generate_updates(u_int16_t, struct prefix *,
		     struct prefix *);
u_int32_t	 rde_local_as(void);
int		 rde_noevaluate(void);
int		 rde_decisionflags(void);
int		 rde_as4byte(struct rde_peer *);

/* rde_attr.c */
int		 attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *,
		     u_int16_t);
int		 attr_writebuf(struct buf *, u_int8_t, u_int8_t, void *,
		     u_int16_t);
void		 attr_init(u_int32_t);
void		 attr_shutdown(void);
int		 attr_optadd(struct rde_aspath *, u_int8_t, u_int8_t,
		     void *, u_int16_t);
struct attr	*attr_optget(const struct rde_aspath *, u_int8_t);
void		 attr_copy(struct rde_aspath *, struct rde_aspath *);
int		 attr_compare(struct rde_aspath *, struct rde_aspath *);
void		 attr_freeall(struct rde_aspath *);
void		 attr_free(struct rde_aspath *, struct attr *);
#define		 attr_optlen(x)	\
    ((x)->len > 255 ? (x)->len + 4 : (x)->len + 3)

int		 aspath_verify(void *, u_int16_t, int);
#define		 AS_ERR_LEN	-1
#define		 AS_ERR_TYPE	-2
#define		 AS_ERR_BAD	-3
void		 aspath_init(u_int32_t);
void		 aspath_shutdown(void);
struct aspath	*aspath_get(void *, u_int16_t);
void		 aspath_put(struct aspath *);
u_char		*aspath_inflate(void *, u_int16_t, u_int16_t *);
u_char		*aspath_deflate(u_char *, u_int16_t *, int *);
void		 aspath_merge(struct rde_aspath *, struct attr *);
u_char		*aspath_dump(struct aspath *);
u_int16_t	 aspath_length(struct aspath *);
u_int16_t	 aspath_count(const void *, u_int16_t);
u_int32_t	 aspath_neighbor(struct aspath *);
int		 aspath_loopfree(struct aspath *, u_int32_t);
int		 aspath_compare(struct aspath *, struct aspath *);
u_char		*aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *);
int		 aspath_match(struct aspath *, enum as_spec, u_int32_t);
int		 community_match(void *, u_int16_t, int, int);
int		 community_set(struct rde_aspath *, int, int);
void		 community_delete(struct rde_aspath *, int, int);

/* rde_rib.c */
extern u_int16_t	 rib_size;
extern struct rib	*ribs;

u_int16_t	 rib_new(int, char *, u_int16_t);
u_int16_t	 rib_find(char *);
void		 rib_free(struct rib *);
struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int);
struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *);
void		 rib_dump(struct rib *, void (*)(struct rib_entry *, void *),
		     void *, sa_family_t);
void		 rib_dump_r(struct rib_context *);
void		 rib_dump_runner(void);
int		 rib_dump_pending(void);

void		 path_init(u_int32_t);
void		 path_shutdown(void);
int		 path_update(struct rib *, struct rde_peer *,
		     struct rde_aspath *, struct bgpd_addr *, int);
int		 path_compare(struct rde_aspath *, struct rde_aspath *);
struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
void		 path_remove(struct rde_aspath *);
void		 path_destroy(struct rde_aspath *);
int		 path_empty(struct rde_aspath *);
struct rde_aspath *path_copy(struct rde_aspath *);
struct rde_aspath *path_get(void);
void		 path_put(struct rde_aspath *);

#define	PREFIX_SIZE(x)	(((x) + 7) / 8 + 1)
int		 prefix_compare(const struct bgpd_addr *,
		    const struct bgpd_addr *, int);
struct prefix	*prefix_get(struct rib *, struct rde_peer *,
		    struct bgpd_addr *, int, u_int32_t);
int		 prefix_add(struct rib *, struct rde_aspath *,
		    struct bgpd_addr *, int);
void		 prefix_move(struct rde_aspath *, struct prefix *);
int		 prefix_remove(struct rib *, struct rde_peer *,
		    struct bgpd_addr *, int, u_int32_t);
int		 prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t);
struct prefix	*prefix_bypeer(struct rib_entry *, struct rde_peer *,
		     u_int32_t);
void		 prefix_updateall(struct rde_aspath *, enum nexthop_state,
		     enum nexthop_state);
void		 prefix_destroy(struct prefix *);
void		 prefix_network_clean(struct rde_peer *, time_t, u_int32_t);

void		 nexthop_init(u_int32_t);
void		 nexthop_shutdown(void);
void		 nexthop_modify(struct rde_aspath *, struct bgpd_addr *,
		     enum action_types, sa_family_t);
void		 nexthop_link(struct rde_aspath *);
void		 nexthop_unlink(struct rde_aspath *);
int		 nexthop_delete(struct nexthop *);
void		 nexthop_update(struct kroute_nexthop *);
struct nexthop	*nexthop_get(struct bgpd_addr *);
int		 nexthop_compare(struct nexthop *, struct nexthop *);

/* rde_decide.c */
void		 prefix_evaluate(struct prefix *, struct rib_entry *);

/* rde_update.c */
void		 up_init(struct rde_peer *);
void		 up_down(struct rde_peer *);
int		 up_test_update(struct rde_peer *, struct prefix *);
int		 up_generate(struct rde_peer *, struct rde_aspath *,
		     struct bgpd_addr *, u_int8_t);
void		 up_generate_updates(struct filter_head *, struct rde_peer *,
		     struct prefix *, struct prefix *);
void		 up_generate_default(struct filter_head *, struct rde_peer *,
		     sa_family_t);
int		 up_dump_prefix(u_char *, int, struct uplist_prefix *,
		     struct rde_peer *);
int		 up_dump_attrnlri(u_char *, int, struct rde_peer *);
u_char		*up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *);
u_char		*up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *);

/* rde_prefix.c */
#define pt_empty(pt)	((pt)->refcnt == 0)
#define pt_ref(pt)	do {				\
	++(pt)->refcnt;					\
	if ((pt)->refcnt == 0)				\
		fatalx("pt_ref: overflow");		\
} while(0)
#define pt_unref(pt)	do {				\
	if ((pt)->refcnt == 0)				\
		fatalx("pt_unref: underflow");		\
	--(pt)->refcnt;					\
} while(0)

void	 pt_init(void);
void	 pt_shutdown(void);
void	 pt_getaddr(struct pt_entry *, struct bgpd_addr *);
struct pt_entry	*pt_fill(struct bgpd_addr *, int);
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 *);
int	 pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *);


/* rde_filter.c */
enum filter_actions rde_filter(u_int16_t, struct rde_aspath **,
		     struct filter_head *, struct rde_peer *,
		     struct rde_aspath *, struct bgpd_addr *, u_int8_t,
		     struct rde_peer *, enum directions);
void		 rde_apply_set(struct rde_aspath *, struct filter_set_head *,
		     sa_family_t, struct rde_peer *, struct rde_peer *);
int		 rde_filter_community(struct rde_aspath *, int, int);
int		 rde_filter_equal(struct filter_head *, struct filter_head *,
		     struct rde_peer *, enum directions);

/* util.c */
u_int32_t	 aspath_extract(const void *, int);

#endif /* __RDE_H__ */