Annotation of embedaddon/bird2/nest/route.h, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Internet Routing Daemon -- Routing Table
! 3: *
! 4: * (c) 1998--2000 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #ifndef _BIRD_ROUTE_H_
! 10: #define _BIRD_ROUTE_H_
! 11:
! 12: #include "lib/lists.h"
! 13: #include "lib/resource.h"
! 14: #include "lib/net.h"
! 15:
! 16: struct ea_list;
! 17: struct protocol;
! 18: struct proto;
! 19: struct rte_src;
! 20: struct symbol;
! 21: struct filter;
! 22: struct cli;
! 23:
! 24: /*
! 25: * Generic data structure for storing network prefixes. Also used
! 26: * for the master routing table. Currently implemented as a hash
! 27: * table.
! 28: *
! 29: * Available operations:
! 30: * - insertion of new entry
! 31: * - deletion of entry
! 32: * - searching for entry by network prefix
! 33: * - asynchronous retrieval of fib contents
! 34: */
! 35:
! 36: struct fib_node {
! 37: struct fib_node *next; /* Next in hash chain */
! 38: struct fib_iterator *readers; /* List of readers of this node */
! 39: byte flags; /* User-defined, will be removed */
! 40: net_addr addr[0];
! 41: };
! 42:
! 43: struct fib_iterator { /* See lib/slists.h for an explanation */
! 44: struct fib_iterator *prev, *next; /* Must be synced with struct fib_node! */
! 45: byte efef; /* 0xff to distinguish between iterator and node */
! 46: byte pad[3];
! 47: struct fib_node *node; /* Or NULL if freshly merged */
! 48: uint hash;
! 49: };
! 50:
! 51: typedef void (*fib_init_fn)(void *);
! 52:
! 53: struct fib {
! 54: pool *fib_pool; /* Pool holding all our data */
! 55: slab *fib_slab; /* Slab holding all fib nodes */
! 56: struct fib_node **hash_table; /* Node hash table */
! 57: uint hash_size; /* Number of hash table entries (a power of two) */
! 58: uint hash_order; /* Binary logarithm of hash_size */
! 59: uint hash_shift; /* 32 - hash_order */
! 60: uint addr_type; /* Type of address data stored in fib (NET_*) */
! 61: uint node_size; /* FIB node size, 0 for nonuniform */
! 62: uint node_offset; /* Offset of fib_node struct inside of user data */
! 63: uint entries; /* Number of entries */
! 64: uint entries_min, entries_max; /* Entry count limits (else start rehashing) */
! 65: fib_init_fn init; /* Constructor */
! 66: };
! 67:
! 68: static inline void * fib_node_to_user(struct fib *f, struct fib_node *e)
! 69: { return e ? (void *) ((char *) e - f->node_offset) : NULL; }
! 70:
! 71: static inline struct fib_node * fib_user_to_node(struct fib *f, void *e)
! 72: { return e ? (void *) ((char *) e + f->node_offset) : NULL; }
! 73:
! 74: void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
! 75: void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */
! 76: void *fib_get_chain(struct fib *f, const net_addr *a); /* Find first node in linked list from hash table */
! 77: void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */
! 78: void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */
! 79: void fib_delete(struct fib *, void *); /* Remove fib entry */
! 80: void fib_free(struct fib *); /* Destroy the fib */
! 81: void fib_check(struct fib *); /* Consistency check for debugging */
! 82:
! 83: void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */
! 84: struct fib_node *fit_get(struct fib *, struct fib_iterator *);
! 85: void fit_put(struct fib_iterator *, struct fib_node *);
! 86: void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos);
! 87:
! 88:
! 89: #define FIB_WALK(fib, type, z) do { \
! 90: struct fib_node *fn_, **ff_ = (fib)->hash_table; \
! 91: uint count_ = (fib)->hash_size; \
! 92: type *z; \
! 93: while (count_--) \
! 94: for (fn_ = *ff_++; z = fib_node_to_user(fib, fn_); fn_=fn_->next)
! 95:
! 96: #define FIB_WALK_END } while (0)
! 97:
! 98: #define FIB_ITERATE_INIT(it, fib) fit_init(it, fib)
! 99:
! 100: #define FIB_ITERATE_START(fib, it, type, z) do { \
! 101: struct fib_node *fn_ = fit_get(fib, it); \
! 102: uint count_ = (fib)->hash_size; \
! 103: uint hpos_ = (it)->hash; \
! 104: type *z; \
! 105: for(;;) { \
! 106: if (!fn_) \
! 107: { \
! 108: if (++hpos_ >= count_) \
! 109: break; \
! 110: fn_ = (fib)->hash_table[hpos_]; \
! 111: continue; \
! 112: } \
! 113: z = fib_node_to_user(fib, fn_);
! 114:
! 115: #define FIB_ITERATE_END fn_ = fn_->next; } } while(0)
! 116:
! 117: #define FIB_ITERATE_PUT(it) fit_put(it, fn_)
! 118:
! 119: #define FIB_ITERATE_PUT_NEXT(it, fib) fit_put_next(fib, it, fn_, hpos_)
! 120:
! 121: #define FIB_ITERATE_UNLINK(it, fib) fit_get(fib, it)
! 122:
! 123:
! 124: /*
! 125: * Master Routing Tables. Generally speaking, each of them contains a FIB
! 126: * with each entry pointing to a list of route entries representing routes
! 127: * to given network (with the selected one at the head).
! 128: *
! 129: * Each of the RTE's contains variable data (the preference and protocol-dependent
! 130: * metrics) and a pointer to a route attribute block common for many routes).
! 131: *
! 132: * It's guaranteed that there is at most one RTE for every (prefix,proto) pair.
! 133: */
! 134:
! 135: struct rtable_config {
! 136: node n;
! 137: char *name;
! 138: struct rtable *table;
! 139: struct proto_config *krt_attached; /* Kernel syncer attached to this table */
! 140: uint addr_type; /* Type of address data stored in table (NET_*) */
! 141: int gc_max_ops; /* Maximum number of operations before GC is run */
! 142: int gc_min_time; /* Minimum time between two consecutive GC runs */
! 143: byte sorted; /* Routes of network are sorted according to rte_better() */
! 144: };
! 145:
! 146: typedef struct rtable {
! 147: node n; /* Node in list of all tables */
! 148: struct fib fib;
! 149: char *name; /* Name of this table */
! 150: list channels; /* List of attached channels (struct channel) */
! 151: uint addr_type; /* Type of address data stored in table (NET_*) */
! 152: int pipe_busy; /* Pipe loop detection */
! 153: int use_count; /* Number of protocols using this table */
! 154: u32 rt_count; /* Number of routes in the table */
! 155: struct hostcache *hostcache;
! 156: struct rtable_config *config; /* Configuration of this table */
! 157: struct config *deleted; /* Table doesn't exist in current configuration,
! 158: * delete as soon as use_count becomes 0 and remove
! 159: * obstacle from this routing table.
! 160: */
! 161: struct event *rt_event; /* Routing table event */
! 162: btime gc_time; /* Time of last GC */
! 163: int gc_counter; /* Number of operations since last GC */
! 164: byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */
! 165: byte hcu_scheduled; /* Hostcache update is scheduled */
! 166: byte nhu_state; /* Next Hop Update state */
! 167: struct fib_iterator prune_fit; /* Rtable prune FIB iterator */
! 168: struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */
! 169: } rtable;
! 170:
! 171: #define NHU_CLEAN 0
! 172: #define NHU_SCHEDULED 1
! 173: #define NHU_RUNNING 2
! 174: #define NHU_DIRTY 3
! 175:
! 176: typedef struct network {
! 177: struct rte *routes; /* Available routes for this network */
! 178: struct fib_node n; /* FIB flags reserved for kernel syncer */
! 179: } net;
! 180:
! 181: struct hostcache {
! 182: slab *slab; /* Slab holding all hostentries */
! 183: struct hostentry **hash_table; /* Hash table for hostentries */
! 184: unsigned hash_order, hash_shift;
! 185: unsigned hash_max, hash_min;
! 186: unsigned hash_items;
! 187: linpool *lp; /* Linpool for trie */
! 188: struct f_trie *trie; /* Trie of prefixes that might affect hostentries */
! 189: list hostentries; /* List of all hostentries */
! 190: byte update_hostcache;
! 191: };
! 192:
! 193: struct hostentry {
! 194: node ln;
! 195: ip_addr addr; /* IP address of host, part of key */
! 196: ip_addr link; /* (link-local) IP address of host, used as gw
! 197: if host is directly attached */
! 198: struct rtable *tab; /* Dependent table, part of key */
! 199: struct hostentry *next; /* Next in hash chain */
! 200: unsigned hash_key; /* Hash key */
! 201: unsigned uc; /* Use count */
! 202: struct rta *src; /* Source rta entry */
! 203: byte dest; /* Chosen route destination type (RTD_...) */
! 204: byte nexthop_linkable; /* Nexthop list is completely non-device */
! 205: u32 igp_metric; /* Chosen route IGP metric */
! 206: };
! 207:
! 208: typedef struct rte {
! 209: struct rte *next;
! 210: net *net; /* Network this RTE belongs to */
! 211: struct channel *sender; /* Channel used to send the route to the routing table */
! 212: struct rta *attrs; /* Attributes of this route */
! 213: byte flags; /* Flags (REF_...) */
! 214: byte pflags; /* Protocol-specific flags */
! 215: word pref; /* Route preference */
! 216: btime lastmod; /* Last modified */
! 217: union { /* Protocol-dependent data (metrics etc.) */
! 218: #ifdef CONFIG_RIP
! 219: struct {
! 220: struct iface *from; /* Incoming iface */
! 221: u8 metric; /* RIP metric */
! 222: u16 tag; /* External route tag */
! 223: } rip;
! 224: #endif
! 225: #ifdef CONFIG_OSPF
! 226: struct {
! 227: u32 metric1, metric2; /* OSPF Type 1 and Type 2 metrics */
! 228: u32 tag; /* External route tag */
! 229: u32 router_id; /* Router that originated this route */
! 230: } ospf;
! 231: #endif
! 232: #ifdef CONFIG_BGP
! 233: struct {
! 234: u8 suppressed; /* Used for deterministic MED comparison */
! 235: s8 stale; /* Route is LLGR_STALE, -1 if unknown */
! 236: } bgp;
! 237: #endif
! 238: #ifdef CONFIG_BABEL
! 239: struct {
! 240: u16 seqno; /* Babel seqno */
! 241: u16 metric; /* Babel metric */
! 242: u64 router_id; /* Babel router id */
! 243: } babel;
! 244: #endif
! 245: struct { /* Routes generated by krt sync (both temporary and inherited ones) */
! 246: s8 src; /* Alleged route source (see krt.h) */
! 247: u8 proto; /* Kernel source protocol ID */
! 248: u8 seen; /* Seen during last scan */
! 249: u8 best; /* Best route in network, propagated to core */
! 250: u32 metric; /* Kernel metric */
! 251: } krt;
! 252: } u;
! 253: } rte;
! 254:
! 255: #define REF_COW 1 /* Copy this rte on write */
! 256: #define REF_FILTERED 2 /* Route is rejected by import filter */
! 257: #define REF_STALE 4 /* Route is stale in a refresh cycle */
! 258: #define REF_DISCARD 8 /* Route is scheduled for discard */
! 259: #define REF_MODIFY 16 /* Route is scheduled for modify */
! 260:
! 261: /* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
! 262: static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
! 263:
! 264: /* Route just has REF_FILTERED flag */
! 265: static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); }
! 266:
! 267:
! 268: /* Types of route announcement, also used as flags */
! 269: #define RA_UNDEF 0 /* Undefined RA type */
! 270: #define RA_OPTIMAL 1 /* Announcement of optimal route change */
! 271: #define RA_ACCEPTED 2 /* Announcement of first accepted route */
! 272: #define RA_ANY 3 /* Announcement of any route change */
! 273: #define RA_MERGED 4 /* Announcement of optimal route merged with next ones */
! 274:
! 275: /* Return value of preexport() callback */
! 276: #define RIC_ACCEPT 1 /* Accepted by protocol */
! 277: #define RIC_PROCESS 0 /* Process it through import filter */
! 278: #define RIC_REJECT -1 /* Rejected by protocol */
! 279: #define RIC_DROP -2 /* Silently dropped by protocol */
! 280:
! 281: extern list routing_tables;
! 282: struct config;
! 283:
! 284: void rt_init(void);
! 285: void rt_preconfig(struct config *);
! 286: void rt_commit(struct config *new, struct config *old);
! 287: void rt_lock_table(rtable *);
! 288: void rt_unlock_table(rtable *);
! 289: void rt_setup(pool *, rtable *, struct rtable_config *);
! 290: static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
! 291: static inline net *net_find_valid(rtable *tab, const net_addr *addr)
! 292: { net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? n : NULL; }
! 293: static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
! 294: void *net_route(rtable *tab, const net_addr *n);
! 295: int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
! 296: rte *rte_find(net *net, struct rte_src *src);
! 297: rte *rte_get_temp(struct rta *);
! 298: void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
! 299: /* rte_update() moved to protocol.h to avoid dependency conflicts */
! 300: int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
! 301: rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
! 302: void rt_refresh_begin(rtable *t, struct channel *c);
! 303: void rt_refresh_end(rtable *t, struct channel *c);
! 304: void rt_modify_stale(rtable *t, struct channel *c);
! 305: void rt_schedule_prune(rtable *t);
! 306: void rte_dump(rte *);
! 307: void rte_free(rte *);
! 308: rte *rte_do_cow(rte *);
! 309: static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
! 310: rte *rte_cow_rta(rte *r, linpool *lp);
! 311: void rte_init_tmp_attrs(struct rte *r, linpool *lp, uint max);
! 312: void rte_make_tmp_attr(struct rte *r, uint id, uint type, uintptr_t val);
! 313: void rte_make_tmp_attrs(struct rte **r, struct linpool *pool, struct rta **old_attrs);
! 314: uintptr_t rte_store_tmp_attr(struct rte *r, uint id);
! 315: void rt_dump(rtable *);
! 316: void rt_dump_all(void);
! 317: int rt_feed_channel(struct channel *c);
! 318: void rt_feed_channel_abort(struct channel *c);
! 319: int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
! 320: int rt_reload_channel(struct channel *c);
! 321: void rt_reload_channel_abort(struct channel *c);
! 322: void rt_prune_sync(rtable *t, int all);
! 323: int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, int refeed);
! 324: struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
! 325:
! 326:
! 327: /* Default limit for ECMP next hops, defined in sysdep code */
! 328: extern const int rt_default_ecmp;
! 329:
! 330: struct rt_show_data_rtable {
! 331: node n;
! 332: rtable *table;
! 333: struct channel *export_channel;
! 334: };
! 335:
! 336: struct rt_show_data {
! 337: net_addr *addr;
! 338: list tables;
! 339: struct rt_show_data_rtable *tab; /* Iterator over table list */
! 340: struct rt_show_data_rtable *last_table; /* Last table in output */
! 341: struct fib_iterator fit; /* Iterator over networks in table */
! 342: int verbose, tables_defined_by;
! 343: const struct filter *filter;
! 344: struct proto *show_protocol;
! 345: struct proto *export_protocol;
! 346: struct channel *export_channel;
! 347: struct config *running_on_config;
! 348: int export_mode, primary_only, filtered, stats, show_for;
! 349:
! 350: int table_open; /* Iteration (fit) is open */
! 351: int net_counter, rt_counter, show_counter, table_counter;
! 352: int net_counter_last, rt_counter_last, show_counter_last;
! 353: };
! 354:
! 355: void rt_show(struct rt_show_data *);
! 356: struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, rtable *t);
! 357:
! 358: /* Value of table definition mode in struct rt_show_data */
! 359: #define RSD_TDB_DEFAULT 0 /* no table specified */
! 360: #define RSD_TDB_INDIRECT 0 /* show route ... protocol P ... */
! 361: #define RSD_TDB_ALL RSD_TDB_SET /* show route ... table all ... */
! 362: #define RSD_TDB_DIRECT RSD_TDB_SET | RSD_TDB_NMN /* show route ... table X table Y ... */
! 363:
! 364: #define RSD_TDB_SET 0x1 /* internal: show empty tables */
! 365: #define RSD_TDB_NMN 0x2 /* internal: need matching net */
! 366:
! 367: /* Value of export_mode in struct rt_show_data */
! 368: #define RSEM_NONE 0 /* Export mode not used */
! 369: #define RSEM_PREEXPORT 1 /* Routes ready for export, before filtering */
! 370: #define RSEM_EXPORT 2 /* Routes accepted by export filter */
! 371: #define RSEM_NOEXPORT 3 /* Routes rejected by export filter */
! 372:
! 373: /*
! 374: * Route Attributes
! 375: *
! 376: * Beware: All standard BGP attributes must be represented here instead
! 377: * of making them local to the route. This is needed to ensure proper
! 378: * construction of BGP route attribute lists.
! 379: */
! 380:
! 381: /* Nexthop structure */
! 382: struct nexthop {
! 383: ip_addr gw; /* Next hop */
! 384: struct iface *iface; /* Outgoing interface */
! 385: struct nexthop *next;
! 386: byte flags;
! 387: byte weight;
! 388: byte labels_orig; /* Number of labels before hostentry was applied */
! 389: byte labels; /* Number of all labels */
! 390: u32 label[0];
! 391: };
! 392:
! 393: #define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */
! 394:
! 395:
! 396: struct rte_src {
! 397: struct rte_src *next; /* Hash chain */
! 398: struct proto *proto; /* Protocol the source is based on */
! 399: u32 private_id; /* Private ID, assigned by the protocol */
! 400: u32 global_id; /* Globally unique ID of the source */
! 401: unsigned uc; /* Use count */
! 402: };
! 403:
! 404:
! 405: typedef struct rta {
! 406: struct rta *next, **pprev; /* Hash chain */
! 407: u32 uc; /* Use count */
! 408: u32 hash_key; /* Hash over important fields */
! 409: struct ea_list *eattrs; /* Extended Attribute chain */
! 410: struct rte_src *src; /* Route source that created the route */
! 411: struct hostentry *hostentry; /* Hostentry for recursive next-hops */
! 412: ip_addr from; /* Advertising router */
! 413: u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */
! 414: u8 source; /* Route source (RTS_...) */
! 415: u8 scope; /* Route scope (SCOPE_... -- see ip.h) */
! 416: u8 dest; /* Route destination type (RTD_...) */
! 417: u8 aflags;
! 418: struct nexthop nh; /* Next hop */
! 419: } rta;
! 420:
! 421: #define RTS_DUMMY 0 /* Dummy route to be removed soon */
! 422: #define RTS_STATIC 1 /* Normal static route */
! 423: #define RTS_INHERIT 2 /* Route inherited from kernel */
! 424: #define RTS_DEVICE 3 /* Device route */
! 425: #define RTS_STATIC_DEVICE 4 /* Static device route */
! 426: #define RTS_REDIRECT 5 /* Learned via redirect */
! 427: #define RTS_RIP 6 /* RIP route */
! 428: #define RTS_OSPF 7 /* OSPF route */
! 429: #define RTS_OSPF_IA 8 /* OSPF inter-area route */
! 430: #define RTS_OSPF_EXT1 9 /* OSPF external route type 1 */
! 431: #define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
! 432: #define RTS_BGP 11 /* BGP route */
! 433: #define RTS_PIPE 12 /* Inter-table wormhole */
! 434: #define RTS_BABEL 13 /* Babel route */
! 435: #define RTS_RPKI 14 /* Route Origin Authorization */
! 436: #define RTS_PERF 15 /* Perf checker */
! 437: #define RTS_MAX 16
! 438:
! 439: #define RTC_UNICAST 0
! 440: #define RTC_BROADCAST 1
! 441: #define RTC_MULTICAST 2
! 442: #define RTC_ANYCAST 3 /* IPv6 Anycast */
! 443:
! 444: #define RTD_NONE 0 /* Undefined next hop */
! 445: #define RTD_UNICAST 1 /* Next hop is neighbor router */
! 446: #define RTD_BLACKHOLE 2 /* Silently drop packets */
! 447: #define RTD_UNREACHABLE 3 /* Reject as unreachable */
! 448: #define RTD_PROHIBIT 4 /* Administratively prohibited */
! 449: #define RTD_MAX 5
! 450:
! 451: /* Flags for net->n.flags, used by kernel syncer */
! 452: #define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
! 453: #define KRF_SYNC_ERROR 0x40 /* Error during kernel table synchronization */
! 454:
! 455: #define RTAF_CACHED 1 /* This is a cached rta */
! 456:
! 457: #define IGP_METRIC_UNKNOWN 0x80000000 /* Default igp_metric used when no other
! 458: protocol-specific metric is availabe */
! 459:
! 460:
! 461: const char * rta_dest_names[RTD_MAX];
! 462:
! 463: static inline const char *rta_dest_name(uint n)
! 464: { return (n < RTD_MAX) ? rta_dest_names[n] : "???"; }
! 465:
! 466: /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
! 467: static inline int rte_is_reachable(rte *r)
! 468: { return r->attrs->dest == RTD_UNICAST; }
! 469:
! 470:
! 471: /*
! 472: * Extended Route Attributes
! 473: */
! 474:
! 475: typedef struct eattr {
! 476: word id; /* EA_CODE(PROTOCOL_..., protocol-dependent ID) */
! 477: byte flags; /* Protocol-dependent flags */
! 478: byte type; /* Attribute type and several flags (EAF_...) */
! 479: union {
! 480: u32 data;
! 481: const struct adata *ptr; /* Attribute data elsewhere */
! 482: } u;
! 483: } eattr;
! 484:
! 485:
! 486: #define EA_CODE(proto,id) (((proto) << 8) | (id))
! 487: #define EA_ID(ea) ((ea) & 0xff)
! 488: #define EA_PROTO(ea) ((ea) >> 8)
! 489: #define EA_ID_FLAG(ea) (1 << EA_ID(ea))
! 490: #define EA_CUSTOM(id) ((id) | EA_CUSTOM_BIT)
! 491: #define EA_IS_CUSTOM(ea) ((ea) & EA_CUSTOM_BIT)
! 492: #define EA_CUSTOM_ID(ea) ((ea) & ~EA_CUSTOM_BIT)
! 493:
! 494: const char *ea_custom_name(uint ea);
! 495:
! 496: #define EA_GEN_IGP_METRIC EA_CODE(PROTOCOL_NONE, 0)
! 497:
! 498: #define EA_CODE_MASK 0xffff
! 499: #define EA_CUSTOM_BIT 0x8000
! 500: #define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */
! 501: #define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */
! 502: #define EA_BIT_GET(ea) ((ea) >> 24)
! 503:
! 504: #define EAF_TYPE_MASK 0x1f /* Mask with this to get type */
! 505: #define EAF_TYPE_INT 0x01 /* 32-bit unsigned integer number */
! 506: #define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */
! 507: #define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */
! 508: #define EAF_TYPE_ROUTER_ID 0x05 /* Router ID (IPv4 address) */
! 509: #define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
! 510: #define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
! 511: #define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
! 512: #define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
! 513: #define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */
! 514: #define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */
! 515: #define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */
! 516: #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */
! 517: #define EAF_ORIGINATED 0x20 /* The attribute has originated locally */
! 518: #define EAF_FRESH 0x40 /* An uncached attribute (e.g. modified in export filter) */
! 519:
! 520: typedef struct adata {
! 521: uint length; /* Length of data */
! 522: byte data[0];
! 523: } adata;
! 524:
! 525: extern const adata null_adata; /* adata of length 0 */
! 526:
! 527: static inline struct adata *
! 528: lp_alloc_adata(struct linpool *pool, uint len)
! 529: {
! 530: struct adata *ad = lp_alloc(pool, sizeof(struct adata) + len);
! 531: ad->length = len;
! 532: return ad;
! 533: }
! 534:
! 535: static inline int adata_same(const struct adata *a, const struct adata *b)
! 536: { return (a->length == b->length && !memcmp(a->data, b->data, a->length)); }
! 537:
! 538:
! 539: typedef struct ea_list {
! 540: struct ea_list *next; /* In case we have an override list */
! 541: byte flags; /* Flags: EALF_... */
! 542: byte rfu;
! 543: word count; /* Number of attributes */
! 544: eattr attrs[0]; /* Attribute definitions themselves */
! 545: } ea_list;
! 546:
! 547: #define EALF_SORTED 1 /* Attributes are sorted by code */
! 548: #define EALF_BISECT 2 /* Use interval bisection for searching */
! 549: #define EALF_CACHED 4 /* Attributes belonging to cached rta */
! 550: #define EALF_TEMP 8 /* Temporary ea_list added by make_tmp_attrs hooks */
! 551:
! 552: struct rte_src *rt_find_source(struct proto *p, u32 id);
! 553: struct rte_src *rt_get_source(struct proto *p, u32 id);
! 554: static inline void rt_lock_source(struct rte_src *src) { src->uc++; }
! 555: static inline void rt_unlock_source(struct rte_src *src) { src->uc--; }
! 556: void rt_prune_sources(void);
! 557:
! 558: struct ea_walk_state {
! 559: ea_list *eattrs; /* Ccurrent ea_list, initially set by caller */
! 560: eattr *ea; /* Current eattr, initially NULL */
! 561: u32 visited[4]; /* Bitfield, limiting max to 128 */
! 562: };
! 563:
! 564: eattr *ea_find(ea_list *, unsigned ea);
! 565: eattr *ea_walk(struct ea_walk_state *s, uint id, uint max);
! 566: int ea_get_int(ea_list *, unsigned ea, int def);
! 567: void ea_dump(ea_list *);
! 568: void ea_sort(ea_list *); /* Sort entries in all sub-lists */
! 569: unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */
! 570: void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffer */
! 571: int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
! 572: uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
! 573: ea_list *ea_append(ea_list *to, ea_list *what);
! 574: void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
! 575:
! 576: #define ea_normalize(ea) do { \
! 577: if (ea->next) { \
! 578: ea_list *t = alloca(ea_scan(ea)); \
! 579: ea_merge(ea, t); \
! 580: ea = t; \
! 581: } \
! 582: ea_sort(ea); \
! 583: if (ea->count == 0) \
! 584: ea = NULL; \
! 585: } while(0) \
! 586:
! 587: static inline eattr *
! 588: ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
! 589: {
! 590: ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
! 591: eattr *e = &a->attrs[0];
! 592:
! 593: a->flags = EALF_SORTED;
! 594: a->count = 1;
! 595: a->next = *to;
! 596: *to = a;
! 597:
! 598: e->id = id;
! 599: e->type = type;
! 600: e->flags = flags;
! 601:
! 602: if (type & EAF_EMBEDDED)
! 603: e->u.data = (u32) val;
! 604: else
! 605: e->u.ptr = (struct adata *) val;
! 606:
! 607: return e;
! 608: }
! 609:
! 610: static inline void
! 611: ea_set_attr_u32(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, u32 val)
! 612: { ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); }
! 613:
! 614: static inline void
! 615: ea_set_attr_ptr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, struct adata *val)
! 616: { ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); }
! 617:
! 618: static inline void
! 619: ea_set_attr_data(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, void *data, uint len)
! 620: {
! 621: struct adata *a = lp_alloc_adata(pool, len);
! 622: memcpy(a->data, data, len);
! 623: ea_set_attr(to, pool, id, flags, type, (uintptr_t) a);
! 624: }
! 625:
! 626:
! 627: #define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
! 628:
! 629: static inline size_t nexthop_size(const struct nexthop *nh)
! 630: { return sizeof(struct nexthop) + sizeof(u32)*nh->labels; }
! 631: int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops */
! 632: static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
! 633: { return (x == y) || nexthop__same(x, y); }
! 634: struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
! 635: struct nexthop *nexthop_sort(struct nexthop *x);
! 636: static inline void nexthop_link(struct rta *a, struct nexthop *from)
! 637: { memcpy(&a->nh, from, nexthop_size(from)); }
! 638: void nexthop_insert(struct nexthop **n, struct nexthop *y);
! 639: int nexthop_is_sorted(struct nexthop *x);
! 640:
! 641: void rta_init(void);
! 642: static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; }
! 643: #define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
! 644: rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
! 645: static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; }
! 646: static inline rta *rta_clone(rta *r) { r->uc++; return r; }
! 647: void rta__free(rta *r);
! 648: static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
! 649: rta *rta_do_cow(rta *o, linpool *lp);
! 650: static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
! 651: void rta_dump(rta *);
! 652: void rta_dump_all(void);
! 653: void rta_show(struct cli *, rta *);
! 654:
! 655: u32 rt_get_igp_metric(rte *rt);
! 656: struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
! 657: void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls);
! 658:
! 659: static inline void
! 660: rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, mpls_label_stack *mls)
! 661: {
! 662: rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls);
! 663: }
! 664:
! 665: /*
! 666: * rta_set_recursive_next_hop() acquires hostentry from hostcache and fills
! 667: * rta->hostentry field. New hostentry has zero use count. Cached rta locks its
! 668: * hostentry (increases its use count), uncached rta does not lock it. Hostentry
! 669: * with zero use count is removed asynchronously during host cache update,
! 670: * therefore it is safe to hold such hostentry temorarily. Hostentry holds a
! 671: * lock for a 'source' rta, mainly to share multipath nexthops.
! 672: *
! 673: * There is no need to hold a lock for hostentry->dep table, because that table
! 674: * contains routes responsible for that hostentry, and therefore is non-empty if
! 675: * given hostentry has non-zero use count. If the hostentry has zero use count,
! 676: * the entry is removed before dep is referenced.
! 677: *
! 678: * The protocol responsible for routes with recursive next hops should hold a
! 679: * lock for a 'source' table governing that routes (argument tab to
! 680: * rta_set_recursive_next_hop()), because its routes reference hostentries
! 681: * (through rta) related to the governing table. When all such routes are
! 682: * removed, rtas are immediately removed achieving zero uc. Then the 'source'
! 683: * table lock could be immediately released, although hostentries may still
! 684: * exist - they will be freed together with the 'source' table.
! 685: */
! 686:
! 687: static inline void rt_lock_hostentry(struct hostentry *he) { if (he) he->uc++; }
! 688: static inline void rt_unlock_hostentry(struct hostentry *he) { if (he) he->uc--; }
! 689:
! 690: /*
! 691: * Default protocol preferences
! 692: */
! 693:
! 694: #define DEF_PREF_DIRECT 240 /* Directly connected */
! 695: #define DEF_PREF_STATIC 200 /* Static route */
! 696: #define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */
! 697: #define DEF_PREF_BABEL 130 /* Babel */
! 698: #define DEF_PREF_RIP 120 /* RIP */
! 699: #define DEF_PREF_BGP 100 /* BGP */
! 700: #define DEF_PREF_RPKI 100 /* RPKI */
! 701: #define DEF_PREF_INHERITED 10 /* Routes inherited from other routing daemons */
! 702:
! 703: /*
! 704: * Route Origin Authorization
! 705: */
! 706:
! 707: #define ROA_UNKNOWN 0
! 708: #define ROA_VALID 1
! 709: #define ROA_INVALID 2
! 710:
! 711: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>