#ifndef __RDE_H__
#define __RDE_H__
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <stdint.h>
#include <stddef.h>
#include "bgpd.h"
#include "chash.h"
#include "log.h"
enum peer_state {
PEER_NONE,
PEER_DOWN,
PEER_UP,
PEER_ERR
};
LIST_HEAD(prefix_list, prefix);
TAILQ_HEAD(prefix_queue, prefix);
RB_HEAD(rib_tree, rib_entry);
TAILQ_HEAD(rib_queue, rib_entry);
struct pq_entry;
TAILQ_HEAD(pq_head, pq_entry);
struct rib_entry {
RB_ENTRY(rib_entry) rib_e;
TAILQ_ENTRY(rib_entry) rib_queue;
struct prefix_queue prefix_h;
struct pt_entry *prefix;
struct pq_head pq_head;
uint32_t pq_peer_id;
uint16_t rib_id;
uint8_t lock;
uint8_t pq_mode;
};
struct rib {
struct rib_tree tree;
char name[PEER_DESCR_LEN];
struct filter_head *in_rules;
struct filter_head *in_rules_tmp;
u_int rtableid;
u_int rtableid_tmp;
enum reconf_action state, fibstate;
uint16_t id;
uint16_t flags;
uint16_t flags_tmp;
};
#define RIB_ADJ_IN 0
#define RIB_LOC_START 1
#define RIB_NOTFOUND 0xffff
RB_HEAD(peer_tree, rde_peer);
CH_HEAD(pend_prefix_hash, pend_prefix);
TAILQ_HEAD(pend_prefix_queue, pend_prefix);
CH_HEAD(pend_attr_hash, pend_prefix);
TAILQ_HEAD(pend_attr_queue, pend_attr);
struct rde_filter;
struct rde_peer {
RB_ENTRY(rde_peer) entry;
struct peer_config conf;
struct rde_peer_stats stats;
struct bgpd_addr remote_addr;
struct bgpd_addr local_v4_addr;
struct bgpd_addr local_v6_addr;
struct capabilities capa;
struct addpath_eval eval;
struct pend_attr_queue updates[AID_MAX];
struct pend_prefix_queue withdraws[AID_MAX];
struct pend_attr_hash pend_attrs;
struct pend_prefix_hash pend_prefixes;
struct rde_filter *out_rules;
struct ibufqueue *ibufq;
struct rib_queue rib_pq_head;
monotime_t staletime[AID_MAX];
uint32_t adjout_bid;
uint32_t remote_bgpid;
uint32_t path_id_tx;
unsigned int local_if_scope;
enum peer_state state;
enum export_type export_type;
enum role role;
uint16_t loc_rib_id;
uint16_t short_as;
uint16_t mrt_idx;
uint8_t recv_eor;
uint8_t sent_eor;
uint8_t reconf_out;
uint8_t reconf_rib;
uint8_t throttled;
uint8_t flags;
};
struct rde_aspa;
struct rde_aspa_state {
uint8_t onlyup;
uint8_t downup;
};
#define AS_SET 1
#define AS_SEQUENCE 2
#define AS_CONFED_SEQUENCE 3
#define AS_CONFED_SET 4
#define ASPATH_HEADER_SIZE (offsetof(struct aspath, data))
struct aspath {
uint32_t source_as;
uint16_t len;
uint16_t ascnt;
u_char data[1];
};
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,
ATTR_PMSI_TUNNEL=22,
ATTR_LARGE_COMMUNITIES=32,
ATTR_OTC=35,
ATTR_FIRST_UNKNOWN,
};
#define ATTR_EXTLEN 0x10
#define ATTR_PARTIAL 0x20
#define ATTR_TRANSITIVE 0x40
#define ATTR_OPTIONAL 0x80
#define ATTR_RESERVED 0x0f
#define ATTR_DEFMASK (ATTR_RESERVED | ATTR_EXTLEN)
#define ATTR_WELL_KNOWN ATTR_TRANSITIVE
struct attr {
uint64_t hash;
u_char *data;
int refcnt;
uint16_t len;
uint8_t flags;
uint8_t type;
};
struct rde_community {
uint64_t hash;
int size;
int nentries;
int flags;
int refcnt;
struct community *communities;
};
#define PARTIAL_COMMUNITIES 0x01
#define PARTIAL_LARGE_COMMUNITIES 0x02
#define PARTIAL_EXT_COMMUNITIES 0x04
#define PARTIAL_DIRTY 0x08
#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
#define F_ATTR_LOOP 0x00200
#define F_PREFIX_ANNOUNCED 0x00400
#define F_ANN_DYNAMIC 0x00800
#define F_ATTR_OTC 0x01000
#define F_ATTR_OTC_LEAK 0x02000
#define F_ATTR_PARSE_ERR 0x10000
#define F_ATTR_LINKED 0x20000
#define ORIGIN_IGP 0
#define ORIGIN_EGP 1
#define ORIGIN_INCOMPLETE 2
#define DEFAULT_LPREF 100
struct rde_aspath {
uint64_t hash;
struct attr **others;
struct aspath *aspath;
struct rde_aspa_state aspa_state;
int refcnt;
uint32_t flags;
#define path_starthash med
uint32_t med;
uint32_t lpref;
uint32_t weight;
uint16_t rtlabelid;
uint16_t pftableid;
uint8_t origin;
#define path_endhash others_len
uint8_t others_len;
uint8_t aspa_generation;
};
enum nexthop_state {
NEXTHOP_LOOKUP,
NEXTHOP_UNREACH,
NEXTHOP_REACH,
NEXTHOP_FLAPPED
};
struct nexthop {
RB_ENTRY(nexthop) entry;
TAILQ_ENTRY(nexthop) runner_l;
struct prefix_list prefix_h;
struct prefix *next_prefix;
struct bgpd_addr exit_nexthop;
struct bgpd_addr true_nexthop;
struct bgpd_addr nexthop_net;
#if 0
uint32_t costs;
#endif
int refcnt;
enum nexthop_state state;
enum nexthop_state oldstate;
uint8_t nexthop_netlen;
uint8_t flags;
#define NEXTHOP_CONNECTED 0x01
};
struct adjout_prefix;
struct pt_entry {
RB_ENTRY(pt_entry) pt_e;
struct adjout_prefix *adjout;
uint32_t adjoutlen;
uint32_t adjoutavail;
uint8_t aid;
uint8_t prefixlen;
uint16_t len;
uint32_t refcnt;
uint8_t data[0];
};
struct prefix {
TAILQ_ENTRY(prefix) rib_l;
LIST_ENTRY(prefix) nexthop_l;
struct rib_entry *re;
struct pt_entry *pt;
struct rde_aspath *aspath;
struct rde_community *communities;
struct rde_peer *peer;
struct nexthop *nexthop;
monotime_t lastchange;
uint32_t path_id;
uint32_t path_id_tx;
uint8_t flags;
uint8_t validation_state;
uint8_t nhflags;
int8_t dmetric;
};
#define PREFIX_NEXTHOP_LINKED 0x01
#define PREFIX_FLAG_FILTERED 0x04
#define PREFIX_DMETRIC_NONE 0
#define PREFIX_DMETRIC_INVALID 1
#define PREFIX_DMETRIC_VALID 2
#define PREFIX_DMETRIC_AS_WIDE 3
#define PREFIX_DMETRIC_ECMP 4
#define PREFIX_DMETRIC_BEST 5
#define NEXTHOP_SELF 0x01
#define NEXTHOP_REJECT 0x02
#define NEXTHOP_BLACKHOLE 0x04
#define NEXTHOP_NOMODIFY 0x08
#define NEXTHOP_MASK 0x0f
#define NEXTHOP_VALID 0x80
struct pq_entry {
TAILQ_ENTRY(pq_entry) entry;
struct prefix *p;
uint32_t path_id_tx;
};
struct adjout_attr {
uint64_t hash;
struct rde_aspath *aspath;
struct rde_community *communities;
struct nexthop *nexthop;
int refcnt;
};
struct adjout_prefix {
uint32_t path_id_tx;
struct adjout_attr *attrs;
struct bitmap peermap;
};
struct pend_attr {
TAILQ_ENTRY(pend_attr) entry;
struct pend_prefix_queue prefixes;
struct adjout_attr *attrs;
uint8_t aid;
};
struct pend_prefix {
TAILQ_ENTRY(pend_prefix) entry;
struct pt_entry *pt;
struct pend_attr *attrs;
uint32_t path_id_tx;
};
struct filterstate {
struct rde_aspath aspath;
struct rde_community communities;
struct nexthop *nexthop;
uint8_t nhflags;
uint8_t vstate;
};
enum eval_mode {
EVAL_NONE,
EVAL_SYNC,
EVAL_REEVAL,
EVAL_DEFAULT,
EVAL_ALL,
};
struct rib_context {
LIST_ENTRY(rib_context) entry;
struct rib_entry *ctx_re;
struct pt_entry *ctx_pt;
uint32_t ctx_id;
void (*ctx_rib_call)(struct rib_entry *, void *);
void (*ctx_prefix_call)(struct pt_entry *,
struct adjout_prefix *, uint32_t, void *);
void (*ctx_done)(void *, uint8_t);
int (*ctx_throttle)(void *);
void *ctx_arg;
struct bgpd_addr ctx_subtree;
unsigned int ctx_count;
uint8_t ctx_aid;
uint8_t ctx_subtreelen;
};
extern struct rde_memstats rdemem;
int mrt_dump_v2_hdr(struct mrt *, struct bgpd_config *);
void mrt_dump_upcall(struct rib_entry *, void *);
void rde_update_err(struct rde_peer *, uint8_t , uint8_t,
struct ibuf *);
void rde_update_log(const char *, uint16_t,
const struct rde_peer *, const struct bgpd_addr *,
const struct bgpd_addr *, uint8_t);
void rde_send_kroute_flush(struct rib *);
void rde_send_kroute(struct rib *, struct prefix *, struct prefix *);
void rde_send_nexthop(struct bgpd_addr *, int);
void rde_pftable_add(uint16_t, struct prefix *);
void rde_pftable_del(uint16_t, struct prefix *);
int rde_evaluate_all(void);
uint32_t rde_local_as(void);
int rde_decisionflags(void);
void rde_peer_send_rrefresh(struct rde_peer *, uint8_t, uint8_t);
int rde_match_peer(struct rde_peer *, struct ctl_neighbor *);
int peer_has_as4byte(struct rde_peer *);
int peer_has_add_path(struct rde_peer *, uint8_t, int);
int peer_has_ext_msg(struct rde_peer *);
int peer_has_ext_nexthop(struct rde_peer *, uint8_t);
int peer_permit_as_set(struct rde_peer *);
void peer_init(struct filter_head *);
void peer_shutdown(void);
void peer_foreach(void (*)(struct rde_peer *, void *), void *);
struct rde_peer *peer_get(uint32_t);
struct rde_peer *peer_match(struct ctl_neighbor *, uint32_t);
struct rde_peer *peer_add(uint32_t, struct peer_config *, struct filter_head *);
struct rde_filter *peer_apply_out_filter(struct rde_peer *,
struct filter_head *);
void rde_enqueue_updates(struct rib_entry *, struct rde_peer *,
struct prefix *, uint32_t, enum eval_mode);
void peer_process_updates(struct rde_peer *, void *);
void peer_up(struct rde_peer *, struct session_up *);
void peer_down(struct rde_peer *);
void peer_delete(struct rde_peer *);
void peer_flush(struct rde_peer *, uint8_t, monotime_t);
void peer_stale(struct rde_peer *, uint8_t, int);
void peer_blast(struct rde_peer *, uint8_t);
void peer_dump(struct rde_peer *, uint8_t);
void peer_begin_rrefresh(struct rde_peer *, uint8_t);
int peer_work_pending(void);
void peer_imsg_push(struct rde_peer *, struct imsg *);
int peer_imsg_pop(struct rde_peer *, struct imsg *);
void peer_imsg_flush(struct rde_peer *);
static inline int
peer_is_up(struct rde_peer *peer)
{
return (peer->state == PEER_UP);
}
RB_PROTOTYPE(peer_tree, rde_peer, entry, peer_cmp);
int attr_writebuf(struct ibuf *, uint8_t, uint8_t, const void *,
uint16_t);
void attr_init(void);
int attr_optadd(struct rde_aspath *, uint8_t, uint8_t,
const void *, uint16_t);
struct attr *attr_optget(const struct rde_aspath *, uint8_t);
void attr_copy(struct rde_aspath *, const struct rde_aspath *);
int attr_equal(const struct rde_aspath *,
const struct rde_aspath *);
void attr_freeall(struct rde_aspath *);
void attr_free(struct rde_aspath *, struct attr *);
void attr_stats(struct ch_stats *);
struct aspath *aspath_get(const void *, uint16_t);
struct aspath *aspath_copy(struct aspath *);
void aspath_put(struct aspath *);
u_char *aspath_deflate(const u_char *, uint16_t *, int *);
int aspath_merge(struct rde_aspath *, struct attr *);
uint32_t aspath_neighbor(struct aspath *);
int aspath_loopfree(struct aspath *, uint32_t);
int aspath_compare(const struct aspath *, const struct aspath *);
int aspath_match(struct aspath *, struct filter_as *, uint32_t);
u_char *aspath_prepend(struct aspath *, uint32_t, int, uint16_t *);
u_char *aspath_override(struct aspath *, uint32_t, uint32_t,
uint16_t *);
int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int);
static inline u_char *
aspath_dump(struct aspath *aspath)
{
return (aspath->data);
}
static inline uint16_t
aspath_length(struct aspath *aspath)
{
return (aspath->len);
}
static inline uint32_t
aspath_origin(struct aspath *aspath)
{
return (aspath->source_as);
}
int community_match(struct rde_community *, struct community *,
struct rde_peer *);
int community_count(struct rde_community *, uint8_t type);
int community_set(struct rde_community *, const struct community *,
struct rde_peer *);
void community_delete(struct rde_community *, const struct community *,
struct rde_peer *);
int community_add(struct rde_community *, int, struct ibuf *);
int community_large_add(struct rde_community *, int, struct ibuf *);
int community_ext_add(struct rde_community *, int, int, struct ibuf *);
int community_writebuf(struct rde_community *, uint8_t, int, struct ibuf *);
void communities_init(void);
void communities_stats(struct ch_stats *);
struct rde_community *communities_lookup(struct rde_community *);
struct rde_community *communities_link(struct rde_community *);
void communities_unlink(struct rde_community *);
int communities_equal(const struct rde_community *,
const struct rde_community *);
void communities_copy(struct rde_community *, struct rde_community *);
void communities_clean(struct rde_community *);
static inline struct rde_community *
communities_ref(struct rde_community *comm)
{
if (comm->refcnt == 0)
fatalx("%s: not-referenced community", __func__);
comm->refcnt++;
rdemem.comm_refs++;
return comm;
}
static inline void
communities_unref(struct rde_community *comm)
{
if (comm == NULL)
return;
rdemem.comm_refs--;
if (--comm->refcnt == 1)
communities_unlink(comm);
}
int community_to_rd(struct community *, uint64_t *);
int prefix_eligible(struct prefix *);
struct prefix *prefix_best(struct rib_entry *);
void prefix_evaluate(struct rib_entry *, struct prefix *,
struct prefix *);
void prefix_evaluate_nexthop(struct prefix *, enum nexthop_state,
enum nexthop_state);
void rde_apply_set(const struct rde_filter_set *, struct rde_peer *,
struct rde_peer *, struct filterstate *, u_int8_t);
int rde_l3vpn_import(struct rde_community *, struct l3vpn *);
void rde_filter_unref(struct rde_filter *);
struct rde_filter *rde_filter_new(size_t);
struct rde_filter *rde_filter_getcache(struct rde_filter *);
void rde_filter_fill(struct rde_filter *, size_t,
const struct filter_rule *);
void rde_filterstate_init(struct filterstate *);
void rde_filterstate_prep(struct filterstate *, struct prefix *);
void rde_filterstate_copy(struct filterstate *, struct filterstate *);
void rde_filterstate_set_vstate(struct filterstate *, uint8_t, uint8_t);
void rde_filterstate_clean(struct filterstate *);
uint64_t rde_filterset_calc_hash(const struct rde_filter_set *);
int rde_filter_skip_rule(struct rde_peer *, struct filter_rule *);
int rde_filter_equal(struct filter_head *, struct filter_head *);
struct rde_filter_set *rde_filterset_imsg_recv(struct imsg *);
void rde_filter_calc_skip_steps(struct filter_head *);
enum filter_action rde_filter(struct filter_head *, struct rde_peer *,
struct rde_peer *, struct bgpd_addr *, uint8_t,
struct filterstate *);
enum filter_action rde_filter_out(struct rde_filter *, struct rde_peer *,
struct rde_peer *, struct bgpd_addr *, uint8_t,
struct filterstate *);
void rde_filtertable_stats(struct ch_stats *);
void rde_filterset_stats(struct ch_stats *);
void pt_init(void);
void pt_shutdown(void);
void pt_getaddr(struct pt_entry *, struct bgpd_addr *);
int pt_getflowspec(struct pt_entry *, uint8_t **);
struct pt_entry *pt_fill(struct bgpd_addr *, u_int);
struct pt_entry *pt_get(struct bgpd_addr *, u_int);
struct pt_entry *pt_get_next(struct bgpd_addr *, u_int);
struct pt_entry *pt_add(struct bgpd_addr *, u_int);
struct pt_entry *pt_get_flow(struct flowspec *);
struct pt_entry *pt_add_flow(struct flowspec *);
struct pt_entry *pt_first(uint8_t);
struct pt_entry *pt_next(struct pt_entry *);
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 *);
int pt_writebuf(struct ibuf *, struct pt_entry *, int, int, uint32_t);
static inline struct pt_entry *
pt_ref(struct pt_entry *pt)
{
++pt->refcnt;
if (pt->refcnt == 0)
fatalx("pt_ref: overflow");
return pt;
}
static inline void
pt_unref(struct pt_entry *pt)
{
if (pt->refcnt == 0)
fatalx("pt_unref: underflow");
if (--pt->refcnt == 0)
pt_remove(pt);
}
extern uint16_t rib_size;
struct rib *rib_new(char *, u_int, uint16_t);
int rib_update(struct rib *);
struct rib *rib_byid(uint16_t);
uint16_t rib_find(char *);
void rib_free(struct rib *);
void rib_shutdown(void);
struct rib_entry *rib_get(struct rib *, struct pt_entry *);
struct rib_entry *rib_get_addr(struct rib *, struct bgpd_addr *, int);
struct rib_entry *rib_match(struct rib *, struct bgpd_addr *);
int rib_dump_pending(void);
void rib_dump_runner(void);
void rib_dump_insert(struct rib_context *);
int rib_dump_new(uint16_t, uint8_t, unsigned int, void *,
void (*)(struct rib_entry *, void *),
void (*)(void *, uint8_t),
int (*)(void *));
int rib_dump_subtree(uint16_t, struct bgpd_addr *, uint8_t,
unsigned int count, void *arg,
void (*)(struct rib_entry *, void *),
void (*)(void *, uint8_t),
int (*)(void *));
void rib_dump_terminate(void *);
void rib_pq_enqueue(struct rib_entry *, struct rde_peer *,
uint32_t, struct prefix *);
void rib_pq_dequeue(struct rib_entry *);
extern struct rib flowrib;
static inline struct rib *
re_rib(struct rib_entry *re)
{
if (re->prefix->aid == AID_FLOWSPECv4 ||
re->prefix->aid == AID_FLOWSPECv6)
return &flowrib;
return rib_byid(re->rib_id);
}
void path_init(void);
struct rde_aspath *path_ref(struct rde_aspath *);
void path_unref(struct rde_aspath *);
int path_equal(const struct rde_aspath *,
const struct rde_aspath *);
struct rde_aspath *path_getcache(struct rde_aspath *);
struct rde_aspath *path_copy(struct rde_aspath *, const struct rde_aspath *);
struct rde_aspath *path_prep(struct rde_aspath *);
struct rde_aspath *path_get(void);
void path_clean(struct rde_aspath *);
void path_put(struct rde_aspath *);
void path_stats(struct ch_stats *);
#define PREFIX_SIZE(x) (((x) + 7) / 8 + 1)
struct prefix *prefix_get(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
int prefix_update(struct rib *, struct rde_peer *, uint32_t,
uint32_t, struct filterstate *, int, struct bgpd_addr *,
int);
int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
int prefix_flowspec_update(struct rde_peer *, struct filterstate *,
struct pt_entry *, uint32_t);
int prefix_flowspec_withdraw(struct rde_peer *, struct pt_entry *);
void prefix_flowspec_dump(uint8_t, void *,
void (*)(struct rib_entry *, void *),
void (*)(void *, uint8_t));
struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *,
uint32_t);
void prefix_destroy(struct prefix *);
static inline struct rde_peer *
prefix_peer(struct prefix *p)
{
return (p->peer);
}
static inline struct rde_aspath *
prefix_aspath(struct prefix *p)
{
return (p->aspath);
}
static inline struct rde_community *
prefix_communities(struct prefix *p)
{
return (p->communities);
}
static inline struct nexthop *
prefix_nexthop(struct prefix *p)
{
return (p->nexthop);
}
static inline uint8_t
prefix_nhflags(struct prefix *p)
{
return (p->nhflags & NEXTHOP_MASK);
}
static inline int
prefix_nhvalid(struct prefix *p)
{
return ((p->nhflags & NEXTHOP_VALID) != 0);
}
static inline uint8_t
prefix_roa_vstate(struct prefix *p)
{
return (p->validation_state & ROA_MASK);
}
static inline uint8_t
prefix_aspa_vstate(struct prefix *p)
{
return (p->validation_state >> 4);
}
static inline void
prefix_set_vstate(struct prefix *p, uint8_t roa_vstate, uint8_t aspa_vstate)
{
p->validation_state = roa_vstate & ROA_MASK;
p->validation_state |= aspa_vstate << 4;
}
static inline struct rib_entry *
prefix_re(struct prefix *p)
{
return (p->re);
}
static inline int
prefix_filtered(struct prefix *p)
{
return ((p->flags & PREFIX_FLAG_FILTERED) != 0);
}
void nexthop_shutdown(void);
int nexthop_pending(void);
void nexthop_runner(void);
void nexthop_modify(struct nexthop *, enum action_types, uint8_t,
struct nexthop **, uint8_t *);
void nexthop_link(struct prefix *);
void nexthop_unlink(struct prefix *);
void nexthop_update(struct kroute_nexthop *);
struct nexthop *nexthop_get(const struct bgpd_addr *);
struct nexthop *nexthop_ref(struct nexthop *);
int nexthop_unref(struct nexthop *);
void adjout_init(void);
struct adjout_prefix *adjout_prefix_get(struct rde_peer *, uint32_t,
struct pt_entry *);
struct adjout_prefix *adjout_prefix_first(struct pt_entry *, uint32_t);
struct adjout_prefix *adjout_prefix_next(struct pt_entry *, uint32_t,
struct adjout_prefix *);
void adjout_prefix_update(struct adjout_prefix *, struct rde_peer *,
struct filterstate *, struct pt_entry *, uint32_t, int);
void adjout_prefix_withdraw(struct rde_peer *, struct pt_entry *,
struct adjout_prefix *, int);
void adjout_prefix_reaper(struct rde_peer *);
void adjout_prefix_dump_cleanup(struct rib_context *);
void adjout_prefix_dump_r(struct rib_context *);
int adjout_prefix_dump_new(struct rde_peer *, uint8_t,
unsigned int, void *,
void (*)(struct pt_entry *, struct adjout_prefix *,
uint32_t, void *),
void (*)(void *, uint8_t), int (*)(void *));
int adjout_prefix_dump_subtree(struct rde_peer *,
struct bgpd_addr *, uint8_t, unsigned int, void *,
void (*)(struct pt_entry *, struct adjout_prefix *,
uint32_t, void *),
void (*)(void *, uint8_t), int (*)(void *));
void adjout_prefix_collect(struct pt_entry *);
void adjout_peer_init(struct rde_peer *);
void adjout_peer_flush_pending(struct rde_peer *);
void adjout_peer_free(struct rde_peer *);
void pend_attr_done(struct pend_attr *, struct rde_peer *);
void pend_eor_add(struct rde_peer *, uint8_t);
void pend_prefix_add(struct rde_peer *, struct adjout_attr *,
struct pt_entry *, uint32_t);
void pend_prefix_free(struct pend_prefix *,
struct pend_prefix_queue *, struct rde_peer *);
void pend_attr_stats(struct ch_stats *);
void pend_prefix_stats(struct ch_stats *);
void adjout_attr_stats(struct ch_stats *);
void up_generate_updates(struct rde_peer *, struct rib_entry *,
enum eval_mode);
void up_generate_addpath(struct rde_peer *, struct rib_entry *,
enum eval_mode);
void up_generate_addpath_all(struct rde_peer *, struct rib_entry *,
enum eval_mode);
void up_generate_default(struct rde_peer *, uint8_t);
int up_is_eor(struct rde_peer *, uint8_t);
void up_dump_withdraws(struct imsgbuf *, struct rde_peer *, uint8_t);
void up_dump_update(struct imsgbuf *, struct rde_peer *, uint8_t);
void aspa_validation(struct rde_aspa *, struct aspath *,
struct rde_aspa_state *);
struct rde_aspa *aspa_table_prep(uint32_t, size_t);
void aspa_add_set(struct rde_aspa *, uint32_t, const uint32_t *,
uint32_t);
void aspa_table_free(struct rde_aspa *);
void aspa_table_stats(const struct rde_aspa *,
struct ctl_show_set *);
int aspa_table_equal(const struct rde_aspa *,
const struct rde_aspa *);
void aspa_table_unchanged(struct rde_aspa *,
const struct rde_aspa *);
#endif