From 7e5f769d91319b4130f7d611dd14252806892ace Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Fri, 15 Mar 2019 20:54:01 +0100 Subject: [PATCH 01/22] BGP: Handle case where capabilites are not used If peer does not announce capabilities at all, or when we have capabilities disabled, handle that as implicit IPv4 unicast. --- proto/bgp/bgp.c | 8 ++++++++ proto/bgp/bgp.h | 1 + proto/bgp/packets.c | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 8dedde9f..56401a08 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -491,6 +491,7 @@ bgp_conn_enter_openconfirm_state(struct bgp_conn *conn) } static const struct bgp_af_caps dummy_af_caps = { }; +static const struct bgp_af_caps basic_af_caps = { .ready = 1 }; void bgp_conn_enter_established_state(struct bgp_conn *conn) @@ -541,6 +542,13 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi); const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); + /* Use default if capabilities were not announced */ + if (!local->length && (c->afi == BGP_AF_IPV4)) + loc = &basic_af_caps; + + if (!peer->length && (c->afi == BGP_AF_IPV4)) + rem = &basic_af_caps; + /* Ignore AFIs that were not announced in multiprotocol capability */ if (!loc || !loc->ready) loc = &dummy_af_caps; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index cfc88d8e..56dbf485 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -215,6 +215,7 @@ struct bgp_caps { u8 llgr_aware; /* Long-lived GR capability, RFC draft */ u16 af_count; /* Number of af_data items */ + u16 length; /* Length of capabilities in OPEN msg */ struct bgp_af_caps af_data[0]; /* Per-AF capability data */ }; diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 26716573..4ae6c5cf 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -217,6 +217,7 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) struct bgp_af_caps *ac; uint any_ext_next_hop = 0; uint any_add_path = 0; + byte *buf_head = buf; byte *data; /* Prepare bgp_caps structure */ @@ -394,6 +395,8 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) data[-1] = buf - data; } + caps->length = buf - buf_head; + return buf; } @@ -405,6 +408,8 @@ bgp_read_capabilities(struct bgp_conn *conn, struct bgp_caps *caps, byte *pos, i int i, cl; u32 af; + caps->length += len; + while (len > 0) { if (len < 2 || len < (2 + pos[1])) From 3c3605818fb304f8de6975c56096bfafa43a8b6b Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 19 Mar 2019 17:44:50 +0100 Subject: [PATCH 02/22] BGP: Mandatory option for channels Allow to mark channel to be mandatory, and do not allow BGP sessions if no common AFI/SAFI is established. --- doc/bird.sgml | 9 +++++++++ proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 3 ++- proto/bgp/packets.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index e531da40..8d93f8ac 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -2565,6 +2565,15 @@ be used in explicit configuration.

BGP channels have additional config options (together with the common ones): +

As you can see, a filter has a header, a list of local variables, and a body. The header consists of the type name; -pairs where each pair defines one local variable. The body consists of +pairs where each pair declares one local variable. The body consists of { statements }. Each { statements }) which is useful if you want to make a bigger @@ -1188,7 +1188,7 @@ called like in C: name(); with_parameters(5);. Function may return values using the return command. Returning a value exits from current function (this is similar to C). -

Filters are declared in a way similar to functions except they can't have +

Filters are defined in a way similar to functions except they can't have explicit parameters. They get a route table entry as an implicit parameter, it is also passed automatically to any functions called. The filter must terminate with either

A filter is implicitly passed a route, and it can access its attributes just -like it accesses variables. Attempts to access undefined attribute result in a -runtime error; you can check if an attribute is defined by using the -defined( attribute ) operator. One notable exception to this -rule are attributes of bgppath and *clist types, where undefined value is -regarded as empty bgppath/*clist for most purposes. +like it accesses variables. There are common route attributes, protocol-specific +route attributes and custom route attributes. Most common attributes are +mandatory (always defined), while remaining are optional. Attempts to access +undefined attribute result in a runtime error; you can check if an attribute is +defined by using the defined( attribute ) operator. One notable +exception to this rule are attributes of bgppath and *clist types, where +undefined value is regarded as empty bgppath/*clist for most purposes. + +Attributes can be defined by just setting them in filters. Custom attributes +have to be first declared by global +option. You can also undefine optional attribute back to non-existence by using +the unset( operator. + +Common route attributes are: -

There also exist protocol-specific attributes which are described in the -corresponding protocol sections. +

Protocol-specific route attributes are described in the corresponding +protocol sections. Other statements @@ -1653,7 +1662,7 @@ corresponding protocol sections.