+Version 3.0alpha2 (2023-05-11)
+ o Fixed memory leaks and use-after free bugs
+ o Simple thread work balancing
+ o MRT switched off
+ o Slow kernel route synchronization to be fixed later
+
+Version 3.0alpha1 (2023-04-18)
+ o Worker threads for BGP, Pipe, RPKI and BFD
+ o Configurable number of threads
+ o Asynchronous route export
+ o Flat attribute structure
+ o Inline import tables
+ o Export tables merged with BGP prefix / attribute buckets
+ o Fixed ROA check locking inversion in route table dumps
+ o MRT switched off
+
+Version 3.0-alpha0 (2022-02-07)
+ o Removal of fixed protocol-specific route attributes
+ o Asynchronous route export
+ o Explicit table import / export hooks
+ o Partially lockless route attribute cache
+ o Thread-safe resource management
+ o Thread-safe interface notifications
+ o Thread-safe protocol API
+ o Adoption of BFD IO loop for general use
+ o Parallel Pipe protocol
+ o Parallel RPKI protocol
+ o Parallel BGP protocol
+ o Lots of refactoring
+ o Bugfixes and improvements as they came along
+
+ Version 2.13 (2023-04-21)
+ o Babel: IPv4 via IPv6 extension (RFC 9229)
+ o Babel: Improve authentication on lossy networks
+ o BGP: New 'allow bgp_med' option
+ o BSD: Support for IPv4 routes with IPv6 nexthop on FreeBSD
+ o Experimental BMP protocol implementation
+ o Important bugfixes
+
+ Notes:
+
+ We changed versioning scheme from <epoch>.<major>.<minor> to more common
+ <major>.<minor>.<patch> . From now on, you may expect that BIRD 2.13.x will be
+ strictly only fixing bugs found in 2.13, whereas BIRD 2.14 will also contain
+ new features.
+
+ This BIRD version contains an alpha release of BMP protocol implementation.
+ It is not ready for production usage and therefore it is not compiled by
+ default and have to be enabled during installation.
+
+
Version 2.0.12 (2023-01-23)
o Filter: New 'onlink' route attribute
o Compile-time option to use 4-way tries instead of 16-way ones
c->preference = cf->preference;
c->debug = cf->debug;
c->merge_limit = cf->merge_limit;
- c->in_keep_filtered = cf->in_keep_filtered;
+ c->in_keep = cf->in_keep;
c->rpki_reload = cf->rpki_reload;
+ c->bmp_hack = cf->bmp_hack;
c->channel_state = CS_DOWN;
- c->export_state = ES_DOWN;
c->last_state_change = current_time();
c->reloadable = 1;
* Routing entry hooks (called only for routes belonging to this protocol):
*
* rte_recalculate Called at the beginning of the best route selection
- * rte_better Compare two rte's and decide which one is better (1=first, 0=second).
- * rte_same Compare two rte's and decide whether they are identical (1=yes, 0=no).
* rte_mergable Compare two rte's and decide whether they could be merged (1=yes, 0=no).
-- * rte_insert Called whenever a rte is inserted to a routing table.
-- * rte_remove Called whenever a rte is removed from the routing table.
*/
- int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *);
- int (*rte_better)(struct rte *, struct rte *);
+ int (*rte_recalculate)(struct rtable_private *, struct network *, struct rte *, struct rte *, struct rte *);
int (*rte_mergable)(struct rte *, struct rte *);
- struct rte * (*rte_modify)(struct rte *, struct linpool *);
-- void (*rte_insert)(struct network *, struct rte *);
-- void (*rte_remove)(struct network *, struct rte *);
- u32 (*rte_igp_metric)(struct rte *);
+ u32 (*rte_igp_metric)(const struct rte *);
/* Hic sunt protocol-specific data */
};
static inline struct channel_config *proto_cf_main_channel(struct proto_config *pc)
{ return proto_cf_find_channel(pc, pc->net_type); }
-struct channel *proto_find_channel_by_table(struct proto *p, struct rtable *t);
+struct channel *proto_find_channel_by_table(struct proto *p, rtable *t);
struct channel *proto_find_channel_by_name(struct proto *p, const char *n);
struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
+ void proto_remove_channel(struct proto *p, struct channel *c);
int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf);
void channel_set_state(struct channel *c, uint state);
},
};
-static inline int
-bgp_attr_known(uint code)
+eattr *
+bgp_find_attr(ea_list *attrs, uint code)
{
- return (code < ARRAY_SIZE(bgp_attr_table)) && bgp_attr_table[code].name;
+ return ea_find(attrs, BGP_EA_ID(code));
}
-void bgp_fix_attr_flags(ea_list *attrs)
+void
+bgp_register_attrs(void)
+{
+ for (uint i=0; i<ARRAY_SIZE(bgp_attr_table); i++)
+ {
+ if (!bgp_attr_table[i].name)
+ bgp_attr_table[i] = (union bgp_attr_desc) {
+ .name = mb_sprintf(&root_pool, "bgp_unknown_0x%02x", i),
+ .type = T_OPAQUE,
+ .flags = BAF_OPTIONAL,
+ .readonly = 1,
+ .export = bgp_export_unknown,
+ .encode = bgp_encode_raw,
+ .decode = bgp_decode_unknown,
+ .format = bgp_format_unknown,
+ };
+
+ ea_register_init(&bgp_attr_table[i].class);
+ }
+}
+
++void
++bgp_fix_attr_flags(ea_list *attrs)
+ {
+ for (u8 i = 0; i < attrs->count; i++)
+ {
+ attrs->attrs[i].flags = bgp_attr_table[EA_ID(attrs->attrs[i].id)].flags;
+ }
+ }
+
++
/*
* Attribute export
*/
#include "lib/string.h"
#include "bgp.h"
+ #include "proto/bmp/bmp.h"
+static void bgp_listen_create(void *);
static list STATIC_LIST_INIT(bgp_sockets); /* Global list of listening sockets */
+static list STATIC_LIST_INIT(bgp_listen_pending); /* Global list of listening socket open requests */
+static event bgp_listen_event = { .hook = bgp_listen_create };
+static DOMAIN(rtable) bgp_listen_domain;
+static pool *bgp_listen_pool;
static void bgp_connect(struct bgp_proto *p);
static void bgp_active(struct bgp_proto *p);
conn->keepalive_timer = NULL;
rfree(conn->hold_timer);
conn->hold_timer = NULL;
+
rfree(conn->tx_ev);
conn->tx_ev = NULL;
- rfree(conn->sk);
+
+ sk_close(conn->sk);
conn->sk = NULL;
+ mb_free(conn->local_open_msg);
+ conn->local_open_msg = NULL;
+ mb_free(conn->remote_open_msg);
+ conn->remote_open_msg = NULL;
+ conn->local_open_length = 0;
+ conn->remote_open_length = 0;
+
mb_free(conn->local_caps);
conn->local_caps = NULL;
mb_free(conn->remote_caps);
conn->sk->rx_hook = NULL;
/* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
- bgp_start_timer(conn->hold_timer, 10);
+ bgp_start_timer(p, conn->hold_timer, 10);
if (os == BS_ESTABLISHED)
- bgp_conn_leave_established_state(p);
+ bgp_conn_leave_established_state(conn, p);
}
void
bgp_close_conn(conn);
bgp_conn_set_state(conn, BS_IDLE);
- ev_schedule(p->event);
+ proto_send_event(&p->p, p->event);
if (os == BS_ESTABLISHED)
- bgp_conn_leave_established_state(p);
+ bgp_conn_leave_established_state(conn, p);
}
/**
#define BGP_RX_BUFFER_EXT_SIZE 65535
#define BGP_TX_BUFFER_EXT_SIZE 65535
-#define BGP_CF_WALK_CHANNELS(P,C) WALK_LIST(C, P->c.channels) if (C->c.channel == &channel_bgp)
-#define BGP_WALK_CHANNELS(P,C) WALK_LIST(C, P->p.channels) if (C->c.channel == &channel_bgp)
+#define BGP_CF_WALK_CHANNELS(P,C) WALK_LIST(C, P->c.channels) if (C->c.class == &channel_bgp)
+#define BGP_WALK_CHANNELS(P,C) WALK_LIST(C, P->p.channels) if (C->c.class == &channel_bgp)
+ #define BGP_MSG_HDR_MARKER_SIZE 16
+ #define BGP_MSG_HDR_MARKER_POS 0
+ #define BGP_MSG_HDR_LENGTH_SIZE 2
+ #define BGP_MSG_HDR_LENGTH_POS BGP_MSG_HDR_MARKER_SIZE
+ #define BGP_MSG_HDR_TYPE_SIZE 1
+ #define BGP_MSG_HDR_TYPE_POS (BGP_MSG_HDR_MARKER_SIZE + BGP_MSG_HDR_LENGTH_SIZE)
+
static inline int bgp_channel_is_ipv4(struct bgp_channel *c)
{ return BGP_AFI(c->afi) == BGP_AFI_IPV4; }
void bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len);
const char *bgp_format_role_name(u8 role);
+ void bgp_fix_attr_flags(ea_list *attrs);
+
static inline int
-rte_resolvable(rte *rt)
+rte_resolvable(const rte *rt)
{
- return rt->attrs->dest != RTD_UNREACHABLE;
+ eattr *nhea = ea_find(rt->attrs, &ea_gen_nexthop);
+ if (!nhea)
+ return 0;
+
+ struct nexthop_adata *nhad = (void *) nhea->u.ptr;
+ return NEXTHOP_IS_REACHABLE(nhad) || (nhad->dest != RTD_UNREACHABLE);
}
+extern struct rte_owner_class bgp_rte_owner_class;
#ifdef LOCAL_DEBUG
#define BGP_FORCE_DEBUG 1
int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end);
ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len);
-void bgp_finish_attrs(struct bgp_parse_state *s, rta *a);
+void bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to);
+
+void bgp_setup_out_table(struct bgp_channel *c);
+
+void bgp_init_pending_tx(struct bgp_channel *c);
+void bgp_free_pending_tx(struct bgp_channel *c);
-void bgp_init_bucket_table(struct bgp_channel *c);
-void bgp_free_bucket_table(struct bgp_channel *c);
-void bgp_free_bucket(struct bgp_channel *c, struct bgp_bucket *b);
-void bgp_defer_bucket(struct bgp_channel *c, struct bgp_bucket *b);
void bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b);
+int bgp_done_bucket(struct bgp_channel *c, struct bgp_bucket *b);
-void bgp_init_prefix_table(struct bgp_channel *c);
-void bgp_free_prefix_table(struct bgp_channel *c);
-void bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *bp);
+void bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket *buck);
-int bgp_rte_better(struct rte *, struct rte *);
-int bgp_rte_mergable(rte *pri, rte *sec);
-int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
-struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
-u32 bgp_rte_igp_metric(struct rte *);
-void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
+int bgp_rte_better(const rte *, const rte *);
+int bgp_rte_mergable(const rte *pri, const rte *sec);
+int bgp_rte_recalculate(struct rtable_private *table, net *net, struct rte_storage *new, struct rte_storage *old, struct rte_storage *old_best);
+void bgp_rte_modify_stale(struct rt_export_request *req, const net_addr *n, struct rt_pending_export *first, struct rt_pending_export *last, const rte **feed, uint count);
+u32 bgp_rte_igp_metric(const rte *);
+void bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old);
int bgp_preexport(struct channel *, struct rte *);
-int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
-void bgp_get_route_info(struct rte *, byte *buf);
-int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad);
+void bgp_get_route_info(const rte *, byte *);
+int bgp_total_aigp_metric_(const rte *e, u64 *metric, const struct adata **ad);
+
+static inline struct bgp_proto *bgp_rte_proto(const rte *rte)
+{
+ return (rte->src->owner->class == &bgp_rte_owner_class) ?
+ SKIP_BACK(struct bgp_proto, p.sources, rte->src->owner) : NULL;
+}
+ byte * bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, const struct rte *new, const struct rte_src *src);
+
#define BGP_AIGP_METRIC 1
#define BGP_AIGP_MAX U64(0xffffffffffffffff)