1 /* $OpenBSD: rde.h,v 1.134 2010/05/03 13:09:38 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and 5 * Andre Oppermann <oppermann@pipeline.ch> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #ifndef __RDE_H__ 20 #define __RDE_H__ 21 22 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/tree.h> 25 26 #include "bgpd.h" 27 28 /* rde internal structures */ 29 30 enum peer_state { 31 PEER_NONE, 32 PEER_DOWN, 33 PEER_UP, 34 PEER_ERR /* error occurred going to PEER_DOWN state */ 35 }; 36 37 /* 38 * How do we identify peers between the session handler and the rde? 39 * Currently I assume that we can do that with the neighbor_ip... 40 */ 41 LIST_HEAD(rde_peer_head, rde_peer); 42 LIST_HEAD(aspath_head, rde_aspath); 43 RB_HEAD(uptree_prefix, update_prefix); 44 RB_HEAD(uptree_attr, update_attr); 45 RB_HEAD(rib_tree, rib_entry); 46 TAILQ_HEAD(uplist_prefix, update_prefix); 47 TAILQ_HEAD(uplist_attr, update_attr); 48 49 struct rde_peer { 50 LIST_ENTRY(rde_peer) hash_l; /* hash list over all peers */ 51 LIST_ENTRY(rde_peer) peer_l; /* list of all peers */ 52 struct aspath_head path_h; /* list of all as paths */ 53 struct peer_config conf; 54 struct bgpd_addr remote_addr; 55 struct bgpd_addr local_v4_addr; 56 struct bgpd_addr local_v6_addr; 57 struct uptree_prefix up_prefix; 58 struct uptree_attr up_attrs; 59 struct uplist_attr updates[AID_MAX]; 60 struct uplist_prefix withdraws[AID_MAX]; 61 struct capabilities capa; 62 u_int64_t prefix_rcvd_update; 63 u_int64_t prefix_rcvd_withdraw; 64 u_int64_t prefix_sent_update; 65 u_int64_t prefix_sent_withdraw; 66 u_int32_t prefix_cnt; /* # of prefixes */ 67 u_int32_t remote_bgpid; /* host byte order! */ 68 u_int32_t up_pcnt; 69 u_int32_t up_acnt; 70 u_int32_t up_nlricnt; 71 u_int32_t up_wcnt; 72 enum peer_state state; 73 u_int16_t ribid; 74 u_int16_t short_as; 75 u_int8_t reconf_in; /* in filter changed */ 76 u_int8_t reconf_out; /* out filter changed */ 77 }; 78 79 #define AS_SET 1 80 #define AS_SEQUENCE 2 81 #define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char)) 82 83 LIST_HEAD(aspath_list, aspath); 84 85 struct aspath { 86 LIST_ENTRY(aspath) entry; 87 int refcnt; /* reference count */ 88 u_int16_t len; /* total length of aspath in octets */ 89 u_int16_t ascnt; /* number of AS hops in data */ 90 u_char data[1]; /* placeholder for actual data */ 91 }; 92 93 enum attrtypes { 94 ATTR_UNDEF, 95 ATTR_ORIGIN, 96 ATTR_ASPATH, 97 ATTR_NEXTHOP, 98 ATTR_MED, 99 ATTR_LOCALPREF, 100 ATTR_ATOMIC_AGGREGATE, 101 ATTR_AGGREGATOR, 102 ATTR_COMMUNITIES, 103 ATTR_ORIGINATOR_ID, 104 ATTR_CLUSTER_LIST, 105 ATTR_MP_REACH_NLRI=14, 106 ATTR_MP_UNREACH_NLRI=15, 107 ATTR_EXT_COMMUNITIES=16, 108 ATTR_AS4_PATH=17, 109 ATTR_AS4_AGGREGATOR=18 110 }; 111 112 /* attribute flags. 4 low order bits reserved */ 113 #define ATTR_EXTLEN 0x10 114 #define ATTR_PARTIAL 0x20 115 #define ATTR_TRANSITIVE 0x40 116 #define ATTR_OPTIONAL 0x80 117 118 /* default attribute flags for well known attributes */ 119 #define ATTR_WELL_KNOWN ATTR_TRANSITIVE 120 121 struct attr { 122 LIST_ENTRY(attr) entry; 123 u_char *data; 124 int refcnt; 125 u_int32_t hash; 126 u_int16_t len; 127 u_int8_t flags; 128 u_int8_t type; 129 }; 130 131 struct mpattr { 132 void *reach; 133 void *unreach; 134 u_int16_t reach_len; 135 u_int16_t unreach_len; 136 }; 137 138 LIST_HEAD(attr_list, attr); 139 140 struct path_table { 141 struct aspath_head *path_hashtbl; 142 u_int32_t path_hashmask; 143 }; 144 145 LIST_HEAD(prefix_head, prefix); 146 147 #define F_ATTR_ORIGIN 0x00001 148 #define F_ATTR_ASPATH 0x00002 149 #define F_ATTR_NEXTHOP 0x00004 150 #define F_ATTR_LOCALPREF 0x00008 151 #define F_ATTR_MED 0x00010 152 #define F_ATTR_MED_ANNOUNCE 0x00020 153 #define F_ATTR_MP_REACH 0x00040 154 #define F_ATTR_MP_UNREACH 0x00080 155 #define F_ATTR_AS4BYTE_NEW 0x00100 /* AS4_PATH or AS4_AGGREGATOR */ 156 #define F_ATTR_LOOP 0x00200 /* path would cause a route loop */ 157 #define F_PREFIX_ANNOUNCED 0x00400 158 #define F_ANN_DYNAMIC 0x00800 159 #define F_NEXTHOP_SELF 0x01000 160 #define F_NEXTHOP_REJECT 0x02000 161 #define F_NEXTHOP_BLACKHOLE 0x04000 162 #define F_NEXTHOP_NOMODIFY 0x08000 163 #define F_ATTR_PARSE_ERR 0x10000 164 #define F_ATTR_LINKED 0x20000 165 166 167 #define ORIGIN_IGP 0 168 #define ORIGIN_EGP 1 169 #define ORIGIN_INCOMPLETE 2 170 171 #define DEFAULT_LPREF 100 172 173 struct rde_aspath { 174 LIST_ENTRY(rde_aspath) path_l, peer_l, nexthop_l; 175 struct prefix_head prefix_h; 176 struct attr **others; 177 struct rde_peer *peer; 178 struct aspath *aspath; 179 struct nexthop *nexthop; /* may be NULL */ 180 u_int32_t med; /* multi exit disc */ 181 u_int32_t lpref; /* local pref */ 182 u_int32_t weight; /* low prio lpref */ 183 u_int32_t prefix_cnt; /* # of prefixes */ 184 u_int32_t active_cnt; /* # of active prefixes */ 185 u_int32_t flags; /* internally used */ 186 u_int16_t rtlabelid; /* route label id */ 187 u_int16_t pftableid; /* pf table id */ 188 u_int8_t origin; 189 u_int8_t others_len; 190 }; 191 192 enum nexthop_state { 193 NEXTHOP_LOOKUP, 194 NEXTHOP_UNREACH, 195 NEXTHOP_REACH 196 }; 197 198 struct nexthop { 199 LIST_ENTRY(nexthop) nexthop_l; 200 struct aspath_head path_h; 201 struct bgpd_addr exit_nexthop; 202 struct bgpd_addr true_nexthop; 203 struct bgpd_addr nexthop_net; 204 #if 0 205 /* 206 * currently we use the boolean nexthop state, this could be exchanged 207 * with a variable cost with a max for unreachable. 208 */ 209 u_int32_t costs; 210 #endif 211 int refcnt; /* filterset reference counter */ 212 enum nexthop_state state; 213 u_int8_t nexthop_netlen; 214 u_int8_t flags; 215 #define NEXTHOP_CONNECTED 0x01 216 }; 217 218 /* generic entry without address specific part */ 219 struct pt_entry { 220 RB_ENTRY(pt_entry) pt_e; 221 u_int8_t aid; 222 u_int8_t prefixlen; 223 u_int16_t refcnt; 224 }; 225 226 struct pt_entry4 { 227 RB_ENTRY(pt_entry) pt_e; 228 u_int8_t aid; 229 u_int8_t prefixlen; 230 u_int16_t refcnt; 231 struct in_addr prefix4; 232 }; 233 234 struct pt_entry6 { 235 RB_ENTRY(pt_entry) pt_e; 236 u_int8_t aid; 237 u_int8_t prefixlen; 238 u_int16_t refcnt; 239 struct in6_addr prefix6; 240 }; 241 242 struct pt_entry_vpn4 { 243 RB_ENTRY(pt_entry) pt_e; 244 u_int8_t aid; 245 u_int8_t prefixlen; 246 u_int16_t refcnt; 247 struct in_addr prefix4; 248 u_int64_t rd; 249 u_int8_t labelstack[21]; 250 u_int8_t labellen; 251 u_int8_t pad1; 252 u_int8_t pad2; 253 }; 254 255 struct rib_context { 256 LIST_ENTRY(rib_context) entry; 257 struct rib_entry *ctx_re; 258 struct rib *ctx_rib; 259 void (*ctx_upcall)(struct rib_entry *, void *); 260 void (*ctx_done)(void *); 261 void (*ctx_wait)(void *); 262 void *ctx_arg; 263 unsigned int ctx_count; 264 u_int8_t ctx_aid; 265 }; 266 267 struct rib_entry { 268 RB_ENTRY(rib_entry) rib_e; 269 struct prefix_head prefix_h; 270 struct prefix *active; /* for fast access */ 271 struct pt_entry *prefix; 272 u_int16_t ribid; 273 u_int16_t flags; 274 }; 275 276 struct rib { 277 char name[PEER_DESCR_LEN]; 278 struct rib_tree rib; 279 u_int rtableid; 280 u_int16_t flags; 281 u_int16_t id; 282 enum reconf_action state; 283 }; 284 285 #define RIB_FAILED 0xffff 286 287 struct prefix { 288 LIST_ENTRY(prefix) rib_l, path_l; 289 struct rde_aspath *aspath; 290 struct pt_entry *prefix; 291 struct rib_entry *rib; /* NULL for Adj-RIB-In */ 292 time_t lastchange; 293 }; 294 295 extern struct rde_memstats rdemem; 296 297 /* prototypes */ 298 /* rde.c */ 299 void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t); 300 void rde_send_nexthop(struct bgpd_addr *, int); 301 void rde_send_pftable(u_int16_t, struct bgpd_addr *, 302 u_int8_t, int); 303 void rde_send_pftable_commit(void); 304 305 void rde_generate_updates(u_int16_t, struct prefix *, 306 struct prefix *); 307 u_int32_t rde_local_as(void); 308 int rde_noevaluate(void); 309 int rde_decisionflags(void); 310 int rde_as4byte(struct rde_peer *); 311 312 /* rde_attr.c */ 313 int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *, 314 u_int16_t); 315 int attr_writebuf(struct buf *, u_int8_t, u_int8_t, void *, 316 u_int16_t); 317 void attr_init(u_int32_t); 318 void attr_shutdown(void); 319 int attr_optadd(struct rde_aspath *, u_int8_t, u_int8_t, 320 void *, u_int16_t); 321 struct attr *attr_optget(const struct rde_aspath *, u_int8_t); 322 void attr_copy(struct rde_aspath *, struct rde_aspath *); 323 int attr_compare(struct rde_aspath *, struct rde_aspath *); 324 void attr_freeall(struct rde_aspath *); 325 void attr_free(struct rde_aspath *, struct attr *); 326 #define attr_optlen(x) \ 327 ((x)->len > 255 ? (x)->len + 4 : (x)->len + 3) 328 329 int aspath_verify(void *, u_int16_t, int); 330 #define AS_ERR_LEN -1 331 #define AS_ERR_TYPE -2 332 #define AS_ERR_BAD -3 333 void aspath_init(u_int32_t); 334 void aspath_shutdown(void); 335 struct aspath *aspath_get(void *, u_int16_t); 336 void aspath_put(struct aspath *); 337 u_char *aspath_inflate(void *, u_int16_t, u_int16_t *); 338 u_char *aspath_deflate(u_char *, u_int16_t *, int *); 339 void aspath_merge(struct rde_aspath *, struct attr *); 340 u_char *aspath_dump(struct aspath *); 341 u_int16_t aspath_length(struct aspath *); 342 u_int16_t aspath_count(const void *, u_int16_t); 343 u_int32_t aspath_neighbor(struct aspath *); 344 int aspath_loopfree(struct aspath *, u_int32_t); 345 int aspath_compare(struct aspath *, struct aspath *); 346 u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *); 347 int aspath_match(struct aspath *, enum as_spec, u_int32_t); 348 int community_match(struct rde_aspath *, int, int); 349 int community_set(struct rde_aspath *, int, int); 350 void community_delete(struct rde_aspath *, int, int); 351 int community_ext_match(struct rde_aspath *, 352 struct filter_extcommunity *, u_int16_t); 353 int community_ext_set(struct rde_aspath *, 354 struct filter_extcommunity *, u_int16_t); 355 void community_ext_delete(struct rde_aspath *, 356 struct filter_extcommunity *, u_int16_t); 357 int community_ext_conv(struct filter_extcommunity *, u_int16_t, 358 u_int64_t *); 359 360 /* rde_rib.c */ 361 extern u_int16_t rib_size; 362 extern struct rib *ribs; 363 364 u_int16_t rib_new(char *, u_int, u_int16_t); 365 u_int16_t rib_find(char *); 366 void rib_free(struct rib *); 367 struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int); 368 struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *); 369 void rib_dump(struct rib *, void (*)(struct rib_entry *, void *), 370 void *, u_int8_t); 371 void rib_dump_r(struct rib_context *); 372 void rib_dump_runner(void); 373 int rib_dump_pending(void); 374 375 void path_init(u_int32_t); 376 void path_shutdown(void); 377 int path_update(struct rib *, struct rde_peer *, 378 struct rde_aspath *, struct bgpd_addr *, int); 379 int path_compare(struct rde_aspath *, struct rde_aspath *); 380 struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); 381 void path_remove(struct rde_aspath *); 382 void path_destroy(struct rde_aspath *); 383 int path_empty(struct rde_aspath *); 384 struct rde_aspath *path_copy(struct rde_aspath *); 385 struct rde_aspath *path_get(void); 386 void path_put(struct rde_aspath *); 387 388 #define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) 389 int prefix_compare(const struct bgpd_addr *, 390 const struct bgpd_addr *, int); 391 struct prefix *prefix_get(struct rib *, struct rde_peer *, 392 struct bgpd_addr *, int, u_int32_t); 393 int prefix_add(struct rib *, struct rde_aspath *, 394 struct bgpd_addr *, int); 395 void prefix_move(struct rde_aspath *, struct prefix *); 396 int prefix_remove(struct rib *, struct rde_peer *, 397 struct bgpd_addr *, int, u_int32_t); 398 int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); 399 struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, 400 u_int32_t); 401 void prefix_updateall(struct rde_aspath *, enum nexthop_state, 402 enum nexthop_state); 403 void prefix_destroy(struct prefix *); 404 void prefix_network_clean(struct rde_peer *, time_t, u_int32_t); 405 406 void nexthop_init(u_int32_t); 407 void nexthop_shutdown(void); 408 void nexthop_modify(struct rde_aspath *, struct bgpd_addr *, 409 enum action_types, u_int8_t); 410 void nexthop_link(struct rde_aspath *); 411 void nexthop_unlink(struct rde_aspath *); 412 int nexthop_delete(struct nexthop *); 413 void nexthop_update(struct kroute_nexthop *); 414 struct nexthop *nexthop_get(struct bgpd_addr *); 415 int nexthop_compare(struct nexthop *, struct nexthop *); 416 417 /* rde_decide.c */ 418 void prefix_evaluate(struct prefix *, struct rib_entry *); 419 420 /* rde_update.c */ 421 void up_init(struct rde_peer *); 422 void up_down(struct rde_peer *); 423 int up_test_update(struct rde_peer *, struct prefix *); 424 int up_generate(struct rde_peer *, struct rde_aspath *, 425 struct bgpd_addr *, u_int8_t); 426 void up_generate_updates(struct filter_head *, struct rde_peer *, 427 struct prefix *, struct prefix *); 428 void up_generate_default(struct filter_head *, struct rde_peer *, 429 u_int8_t); 430 int up_generate_marker(struct rde_peer *, u_int8_t); 431 int up_dump_prefix(u_char *, int, struct uplist_prefix *, 432 struct rde_peer *); 433 int up_dump_attrnlri(u_char *, int, struct rde_peer *); 434 u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *, 435 u_int8_t); 436 int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *, 437 u_int8_t); 438 439 /* rde_prefix.c */ 440 #define pt_empty(pt) ((pt)->refcnt == 0) 441 #define pt_ref(pt) do { \ 442 ++(pt)->refcnt; \ 443 if ((pt)->refcnt == 0) \ 444 fatalx("pt_ref: overflow"); \ 445 } while(0) 446 #define pt_unref(pt) do { \ 447 if ((pt)->refcnt == 0) \ 448 fatalx("pt_unref: underflow"); \ 449 --(pt)->refcnt; \ 450 } while(0) 451 452 void pt_init(void); 453 void pt_shutdown(void); 454 void pt_getaddr(struct pt_entry *, struct bgpd_addr *); 455 struct pt_entry *pt_fill(struct bgpd_addr *, int); 456 struct pt_entry *pt_get(struct bgpd_addr *, int); 457 struct pt_entry *pt_add(struct bgpd_addr *, int); 458 void pt_remove(struct pt_entry *); 459 struct pt_entry *pt_lookup(struct bgpd_addr *); 460 int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); 461 462 463 /* rde_filter.c */ 464 enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, 465 struct filter_head *, struct rde_peer *, 466 struct rde_aspath *, struct bgpd_addr *, u_int8_t, 467 struct rde_peer *, enum directions); 468 void rde_apply_set(struct rde_aspath *, struct filter_set_head *, 469 u_int8_t, struct rde_peer *, struct rde_peer *); 470 int rde_filter_equal(struct filter_head *, struct filter_head *, 471 struct rde_peer *, enum directions); 472 473 /* util.c */ 474 u_int32_t aspath_extract(const void *, int); 475 476 #endif /* __RDE_H__ */ 477