void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */
void *fib_get_chain(struct fib *f, const net_addr *a); /* Find first node in linked list from hash table */
-void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */
+void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */
void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */
void fib_delete(struct fib *, void *); /* Remove fib entry */
void fib_free(struct fib *); /* Destroy the fib */
type *z; \
for(;;) { \
if (!fn_) \
- { \
+ { \
if (++hpos_ >= count_) \
break; \
fn_ = (fib)->hash_table[hpos_]; \
uint addr_type; /* Type of address data stored in table (NET_*) */
int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */
+ u32 rt_count; /* Number of routes in the table */
struct hostcache *hostcache;
struct rtable_config *config; /* Configuration of this table */
struct config *deleted; /* Table doesn't exist in current configuration,
#ifdef CONFIG_BGP
struct {
u8 suppressed; /* Used for deterministic MED comparison */
+ s8 stale; /* Route is LLGR_STALE, -1 if unknown */
} bgp;
#endif
#ifdef CONFIG_BABEL
#define REF_FILTERED 2 /* Route is rejected by import filter */
#define REF_STALE 4 /* Route is stale in a refresh cycle */
#define REF_DISCARD 8 /* Route is scheduled for discard */
+#define REF_MODIFY 16 /* Route is scheduled for modify */
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
#define RA_ANY 3 /* Announcement of any route change */
#define RA_MERGED 4 /* Announcement of optimal route merged with next ones */
-/* Return value of import_control() callback */
+/* Return value of preexport() callback */
#define RIC_ACCEPT 1 /* Accepted by protocol */
#define RIC_PROCESS 0 /* Process it through import filter */
#define RIC_REJECT -1 /* Rejected by protocol */
#define RIC_DROP -2 /* Silently dropped by protocol */
+extern list routing_tables;
struct config;
void rt_init(void);
void rt_commit(struct config *new, struct config *old);
void rt_lock_table(rtable *);
void rt_unlock_table(rtable *);
-void rt_setup(pool *, rtable *, char *, struct rtable_config *);
+void rt_setup(pool *, rtable *, struct rtable_config *);
static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
static inline net *net_find_valid(rtable *tab, const net_addr *addr)
{ net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? n : NULL; }
void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
/* rte_update() moved to protocol.h to avoid dependency conflicts */
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
-rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent);
+rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
void rt_refresh_begin(rtable *t, struct channel *c);
void rt_refresh_end(rtable *t, struct channel *c);
+void rt_modify_stale(rtable *t, struct channel *c);
void rt_schedule_prune(rtable *t);
void rte_dump(rte *);
void rte_free(rte *);
rte *rte_do_cow(rte *);
static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
rte *rte_cow_rta(rte *r, linpool *lp);
+void rte_make_tmp_attr(struct rte *r, struct ea_list *e, uint id, uint type, u32 val);
+uint rte_store_tmp_attr(struct rte *r, uint id);
void rt_dump(rtable *);
void rt_dump_all(void);
int rt_feed_channel(struct channel *c);
void rt_feed_channel_abort(struct channel *c);
+int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
+int rt_reload_channel(struct channel *c);
+void rt_reload_channel_abort(struct channel *c);
+void rt_prune_sync(rtable *t, int all);
struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
+/* Default limit for ECMP next hops, defined in sysdep code */
+extern const int rt_default_ecmp;
+
struct rt_show_data_rtable {
node n;
rtable *table;
#define RTS_PIPE 12 /* Inter-table wormhole */
#define RTS_BABEL 13 /* Babel route */
#define RTS_RPKI 14 /* Route Origin Authorization */
-
+#define RTS_PERF 15 /* Perf checker */
+#define RTS_MAX 16
#define RTC_UNICAST 0
#define RTC_BROADCAST 1
*/
typedef struct eattr {
- word id; /* EA_CODE(EAP_..., protocol-dependent ID) */
+ word id; /* EA_CODE(PROTOCOL_..., protocol-dependent ID) */
byte flags; /* Protocol-dependent flags */
byte type; /* Attribute type and several flags (EAF_...) */
union {
} u;
} eattr;
-#define EAP_GENERIC 0 /* Generic attributes */
-#define EAP_BGP 1 /* BGP attributes */
-#define EAP_RIP 2 /* RIP */
-#define EAP_OSPF 3 /* OSPF */
-#define EAP_KRT 4 /* Kernel route attributes */
-#define EAP_BABEL 5 /* Babel attributes */
-#define EAP_MAX 6
#define EA_CODE(proto,id) (((proto) << 8) | (id))
-#define EA_PROTO(ea) ((ea) >> 8)
#define EA_ID(ea) ((ea) & 0xff)
+#define EA_PROTO(ea) ((ea) >> 8)
+#define EA_ID_FLAG(ea) (1 << EA_ID(ea))
+#define EA_CUSTOM(id) ((id) | EA_CUSTOM_BIT)
+#define EA_IS_CUSTOM(ea) ((ea) & EA_CUSTOM_BIT)
+#define EA_CUSTOM_ID(ea) ((ea) & ~EA_CUSTOM_BIT)
+
+const char *ea_custom_name(uint ea);
-#define EA_GEN_IGP_METRIC EA_CODE(EAP_GENERIC, 0)
+#define EA_GEN_IGP_METRIC EA_CODE(PROTOCOL_NONE, 0)
#define EA_CODE_MASK 0xffff
+#define EA_CUSTOM_BIT 0x8000
#define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */
#define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */
ea_list *ea_append(ea_list *to, ea_list *what);
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
+#define ea_normalize(ea) do { \
+ if (ea->next) { \
+ ea_list *t = alloca(ea_scan(ea)); \
+ ea_merge(ea, t); \
+ ea = t; \
+ } \
+ ea_sort(ea); \
+} while(0) \
+
+static inline eattr *
+ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
+{
+ ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
+ eattr *e = &a->attrs[0];
+
+ a->flags = EALF_SORTED;
+ a->count = 1;
+ a->next = *to;
+ *to = a;
+
+ e->id = id;
+ e->type = type;
+ e->flags = flags;
+
+ if (type & EAF_EMBEDDED)
+ e->u.data = (u32) val;
+ else
+ e->u.ptr = (struct adata *) val;
+
+ return e;
+}
+
+static inline void
+ea_set_attr_u32(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, u32 val)
+{ ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); }
+
+static inline void
+ea_set_attr_ptr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, struct adata *val)
+{ ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); }
+
+static inline void
+ea_set_attr_data(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, void *data, uint len)
+{
+ struct adata *a = lp_alloc_adata(pool, len);
+ memcpy(a->data, data, len);
+ ea_set_attr(to, pool, id, flags, type, (uintptr_t) a);
+}
+
+
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
static inline size_t nexthop_size(const struct nexthop *nh)
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
void rta_dump(rta *);
void rta_dump_all(void);
-void rta_show(struct cli *, rta *, ea_list *);
+void rta_show(struct cli *, rta *);
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls);
static inline void rt_lock_hostentry(struct hostentry *he) { if (he) he->uc++; }
static inline void rt_unlock_hostentry(struct hostentry *he) { if (he) he->uc--; }
-
-extern struct protocol *attr_class_to_protocol[EAP_MAX];
-
/*
* Default protocol preferences
*/
-#define DEF_PREF_DIRECT 240 /* Directly connected */
+#define DEF_PREF_DIRECT 240 /* Directly connected */
#define DEF_PREF_STATIC 200 /* Static route */
#define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */
#define DEF_PREF_BABEL 130 /* Babel */