BGP: Minor cleanups

This commit is contained in:
Ondrej Zajicek (work) 2017-02-07 15:55:51 +01:00
parent d8022d26fc
commit 82f42ea091
4 changed files with 67 additions and 52 deletions

View file

@ -2040,6 +2040,16 @@ using the following configuration parameters:
source address for the BGP session. Default: the address of the local source address for the BGP session. Default: the address of the local
end of the interface our neighbor is connected to. end of the interface our neighbor is connected to.
<tag><label id="bgp-strict-bind">strict bind <m/switch/</tag>
Specify whether BGP listening socket should be bound to a specific local
address (the same as the <cf/source address/) and associated interface,
or to all addresses. Binding to a specific address could be useful in
cases like running multiple BIRD instances on a machine, each using its
IP address. Note that listening sockets bound to a specific address and
to all addresses collide, therefore either all BGP protocols (of the
same address family and using the same local port) should have set
<cf/strict bind/, or none of them. Default: disabled.
<tag><label id="bgp-next-hop-self">next hop self</tag> <tag><label id="bgp-next-hop-self">next hop self</tag>
Avoid calculation of the Next Hop attribute and always advertise our own Avoid calculation of the Next Hop attribute and always advertise our own
source address as a next hop. This needs to be used only occasionally to source address as a next hop. This needs to be used only occasionally to
@ -2112,7 +2122,7 @@ using the following configuration parameters:
Note that full (ICMP protection, for example) <rfc id="5082"> support is Note that full (ICMP protection, for example) <rfc id="5082"> support is
provided by Linux only. Default: disabled. provided by Linux only. Default: disabled.
<tag><label id="bgp-pass">password <m/string/</tag> <tag><label id="bgp-password">password <m/string/</tag>
Use this password for MD5 authentication of BGP sessions (<rfc id="2385">). When Use this password for MD5 authentication of BGP sessions (<rfc id="2385">). When
used on BSD systems, see also <cf/setkey/ option below. Default: no used on BSD systems, see also <cf/setkey/ option below. Default: no
authentication. authentication.
@ -2270,13 +2280,6 @@ using the following configuration parameters:
This option is relevant to IPv4 mode with enabled capability This option is relevant to IPv4 mode with enabled capability
advertisement only. Default: on. advertisement only. Default: on.
<tag><label id="bgp-route-limit">route limit <m/number/</tag>
The maximal number of routes that may be imported from the protocol. If
the route limit is exceeded, the connection is closed with an error.
Limit is currently implemented as <cf>import limit <m/number/ action
restart</cf>. This option is obsolete and it is replaced by
<ref id="proto-import-limit" name="import limit option">. Default: no limit.
<tag><label id="bgp-disable-after-error">disable after error <m/switch/</tag> <tag><label id="bgp-disable-after-error">disable after error <m/switch/</tag>
When an error is encountered (either locally or by the other side), When an error is encountered (either locally or by the other side),
disable the instance automatically and wait for an administrator to fix disable the instance automatically and wait for an administrator to fix

View file

@ -1325,29 +1325,23 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
static adata null_adata; /* adata of length 0 */ static adata null_adata; /* adata of length 0 */
static inline void
bgp_cluster_list_prepend(ea_list **attrs, struct linpool *pool, u32 id)
{
eattr *a = bgp_find_attr(*attrs, BA_CLUSTER_LIST);
adata *d = int_set_add(pool, a ? a->u.ptr : NULL, id);
bgp_set_attr_ptr(attrs, pool, BA_CLUSTER_LIST, 0, d);
}
static ea_list * static ea_list *
bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs, struct linpool *pool) bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs0, struct linpool *pool)
{ {
struct proto *SRC = e->attrs->src->proto; struct proto *SRC = e->attrs->src->proto;
struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL;
struct bgp_export_state s = { .proto = p, .channel =c, .pool = pool, .src = src, .route = e }; struct bgp_export_state s = { .proto = p, .channel =c, .pool = pool, .src = src, .route = e };
ea_list *attrs = attrs0;
eattr *a; eattr *a;
adata *ad;
/* ORIGIN attribute - mandatory, attach if missing */ /* ORIGIN attribute - mandatory, attach if missing */
if (! bgp_find_attr(attrs, BA_ORIGIN)) if (! bgp_find_attr(attrs0, BA_ORIGIN))
bgp_set_attr_u32(&attrs, pool, BA_ORIGIN, 0, src ? ORIGIN_INCOMPLETE : ORIGIN_IGP); bgp_set_attr_u32(&attrs, pool, BA_ORIGIN, 0, src ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
/* AS_PATH attribute */ /* AS_PATH attribute - mandatory */
a = bgp_find_attr(attrs, BA_AS_PATH); a = bgp_find_attr(attrs0, BA_AS_PATH);
adata *ad = a ? a->u.ptr : &null_adata; ad = a ? a->u.ptr : &null_adata;
/* AS_PATH attribute - strip AS_CONFED* segments outside confederation */ /* AS_PATH attribute - strip AS_CONFED* segments outside confederation */
if ((!p->cf->confederation || !p->is_interior) && as_path_contains_confed(ad)) if ((!p->cf->confederation || !p->is_interior) && as_path_contains_confed(ad))
@ -1374,33 +1368,40 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at
bgp_set_attr_ptr(&attrs, pool, BA_AS_PATH, 0, ad); bgp_set_attr_ptr(&attrs, pool, BA_AS_PATH, 0, ad);
/* MULTI_EXIT_DESC attribute - accept only if set in export filter */ /* MULTI_EXIT_DESC attribute - accept only if set in export filter */
a = bgp_find_attr(attrs, BA_MULTI_EXIT_DISC); a = bgp_find_attr(attrs0, BA_MULTI_EXIT_DISC);
if (a && !(a->type & EAF_FRESH)) if (a && !(a->type & EAF_FRESH))
bgp_unset_attr(&attrs, pool, BA_MULTI_EXIT_DISC); bgp_unset_attr(&attrs, pool, BA_MULTI_EXIT_DISC);
} }
/* NEXT_HOP attribute - delegated to AF-specific hook */ /* NEXT_HOP attribute - delegated to AF-specific hook */
a = bgp_find_attr(attrs, BA_NEXT_HOP); a = bgp_find_attr(attrs0, BA_NEXT_HOP);
bgp_update_next_hop(&s, a, &attrs); bgp_update_next_hop(&s, a, &attrs);
/* LOCAL_PREF attribute - required for IBGP, attach if missing */ /* LOCAL_PREF attribute - required for IBGP, attach if missing */
if (p->is_interior && ! bgp_find_attr(attrs, BA_LOCAL_PREF)) if (p->is_interior && ! bgp_find_attr(attrs0, BA_LOCAL_PREF))
bgp_set_attr_u32(&attrs, pool, BA_LOCAL_PREF, 0, p->cf->default_local_pref); bgp_set_attr_u32(&attrs, pool, BA_LOCAL_PREF, 0, p->cf->default_local_pref);
/* IBGP route reflection, RFC 4456 */ /* IBGP route reflection, RFC 4456 */
if (src && src->is_internal && p->is_internal && (src->local_as == p->local_as)) if (src && src->is_internal && p->is_internal && (src->local_as == p->local_as))
{ {
/* ORIGINATOR_ID attribute - attach if not already set */ /* ORIGINATOR_ID attribute - attach if not already set */
if (! bgp_find_attr(attrs, BA_ORIGINATOR_ID)) if (! bgp_find_attr(attrs0, BA_ORIGINATOR_ID))
bgp_set_attr_u32(&attrs, pool, BA_ORIGINATOR_ID, 0, src->remote_id); bgp_set_attr_u32(&attrs, pool, BA_ORIGINATOR_ID, 0, src->remote_id);
/* CLUSTER_LIST attribute - prepend cluster ID */ /* CLUSTER_LIST attribute - prepend cluster ID */
if (src->rr_cluster_id) a = bgp_find_attr(attrs0, BA_CLUSTER_LIST);
bgp_cluster_list_prepend(&attrs, pool, src->rr_cluster_id); ad = a ? a->u.ptr : NULL;
/* Handle different src and dst cluster ID - prepend both ones */ /* Prepend src cluster ID */
if (src->rr_cluster_id)
ad = int_set_add(pool, ad, src->rr_cluster_id);
/* Prepend dst cluster ID if src and dst clusters are different */
if (p->rr_cluster_id && (src->rr_cluster_id != p->rr_cluster_id)) if (p->rr_cluster_id && (src->rr_cluster_id != p->rr_cluster_id))
bgp_cluster_list_prepend(&attrs, pool, p->rr_cluster_id); ad = int_set_add(pool, ad, p->rr_cluster_id);
/* Should be at least one prepended cluster ID */
bgp_set_attr_ptr(&attrs, pool, BA_CLUSTER_LIST, 0, ad);
} }
/* AS4_* transition attributes, RFC 6793 4.2.2 */ /* AS4_* transition attributes, RFC 6793 4.2.2 */
@ -1421,6 +1422,12 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at
} }
} }
/*
* Presence of mandatory attributes ORIGIN and AS_PATH is ensured by above
* conditions. Presence and validity of quasi-mandatory NEXT_HOP attribute
* should be checked in AF-specific hooks.
*/
/* Apply per-attribute export hooks for validatation and normalization */ /* Apply per-attribute export hooks for validatation and normalization */
return bgp_export_attrs(&s, attrs); return bgp_export_attrs(&s, attrs);
} }

View file

@ -73,7 +73,7 @@ struct bgp_config {
u16 local_port; /* Local listening port */ u16 local_port; /* Local listening port */
u16 remote_port; /* Neighbor destination port */ u16 remote_port; /* Neighbor destination port */
int multihop; /* Number of hops if multihop */ int multihop; /* Number of hops if multihop */
int strict_bind; /* Bind listening socket to local address XXXX */ int strict_bind; /* Bind listening socket to local address */
int ttl_security; /* Enable TTL security [RFC 5082] */ int ttl_security; /* Enable TTL security [RFC 5082] */
int compare_path_lengths; /* Use path lengths when selecting best route */ int compare_path_lengths; /* Use path lengths when selecting best route */
int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */
@ -509,22 +509,18 @@ void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to);
#define BAF_PARTIAL 0x20 #define BAF_PARTIAL 0x20
#define BAF_EXT_LEN 0x10 #define BAF_EXT_LEN 0x10
#define BA_ORIGIN 0x01 /* [RFC1771] */ /* WM */ #define BA_ORIGIN 0x01 /* RFC 4271 */ /* WM */
#define BA_AS_PATH 0x02 /* WM */ #define BA_AS_PATH 0x02 /* WM */
#define BA_NEXT_HOP 0x03 /* WM */ #define BA_NEXT_HOP 0x03 /* WM */
#define BA_MULTI_EXIT_DISC 0x04 /* ON */ #define BA_MULTI_EXIT_DISC 0x04 /* ON */
#define BA_LOCAL_PREF 0x05 /* WD */ #define BA_LOCAL_PREF 0x05 /* WD */
#define BA_ATOMIC_AGGR 0x06 /* WD */ #define BA_ATOMIC_AGGR 0x06 /* WD */
#define BA_AGGREGATOR 0x07 /* OT */ #define BA_AGGREGATOR 0x07 /* OT */
#define BA_COMMUNITY 0x08 /* [RFC1997] */ /* OT */ #define BA_COMMUNITY 0x08 /* RFC 1997 */ /* OT */
#define BA_ORIGINATOR_ID 0x09 /* [RFC1966] */ /* ON */ #define BA_ORIGINATOR_ID 0x09 /* RFC 4456 */ /* ON */
#define BA_CLUSTER_LIST 0x0a /* ON */ #define BA_CLUSTER_LIST 0x0a /* RFC 4456 */ /* ON */
/* We don't support these: */ #define BA_MP_REACH_NLRI 0x0e /* RFC 4760 */
#define BA_DPA 0x0b /* ??? */ #define BA_MP_UNREACH_NLRI 0x0f /* RFC 4760 */
#define BA_ADVERTISER 0x0c /* [RFC1863] */
#define BA_RCID_PATH 0x0d
#define BA_MP_REACH_NLRI 0x0e /* [RFC2283] */
#define BA_MP_UNREACH_NLRI 0x0f
#define BA_EXT_COMMUNITY 0x10 /* RFC 4360 */ #define BA_EXT_COMMUNITY 0x10 /* RFC 4360 */
#define BA_AS4_PATH 0x11 /* RFC 6793 */ #define BA_AS4_PATH 0x11 /* RFC 6793 */
#define BA_AS4_AGGREGATOR 0x12 /* RFC 6793 */ #define BA_AS4_AGGREGATOR 0x12 /* RFC 6793 */

View file

@ -713,9 +713,13 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
#define REPORT(msg, args...) \ #define REPORT(msg, args...) \
({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); }) ({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); })
#define DISCARD(msg, args...) \
({ REPORT(msg, ## args); return; })
#define WITHDRAW(msg, args...) \ #define WITHDRAW(msg, args...) \
({ REPORT(msg, ## args); s->err_withdraw = 1; return; }) ({ REPORT(msg, ## args); s->err_withdraw = 1; return; })
#define BAD_AFI "Unexpected AF <%u/%u> in UPDATE"
#define BAD_NEXT_HOP "Invalid NEXT_HOP attribute" #define BAD_NEXT_HOP "Invalid NEXT_HOP attribute"
#define NO_NEXT_HOP "Missing NEXT_HOP attribute" #define NO_NEXT_HOP "Missing NEXT_HOP attribute"
@ -836,21 +840,27 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to)
static uint static uint
bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED) bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED)
{ {
// FIXME
return 0; return 0;
} }
static void static void
bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED) bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED)
{ {
// FIXME /*
* Although we expect no next hop and RFC 7606 7.11 states that attribute
* MP_REACH_NLRI with unexpected next hop length is considered malformed,
* FlowSpec RFC 5575 4 states that next hop shall be ignored on receipt.
*/
return; return;
} }
static void static void
bgp_update_next_hop_none(struct bgp_export_state *s UNUSED, eattr *a UNUSED, ea_list **to UNUSED) bgp_update_next_hop_none(struct bgp_export_state *s, eattr *a, ea_list **to)
{ {
// FIXME /* NEXT_HOP shall not pass */
if (a)
bgp_unset_attr(to, s->pool, BA_NEXT_HOP);
} }
@ -1652,15 +1662,15 @@ bgp_create_end_mark(struct bgp_channel *c, byte *buf)
} }
static inline void static inline void
bgp_rx_end_mark(struct bgp_proto *p, u32 afi) bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
{ {
struct bgp_proto *p = s->proto;
struct bgp_channel *c = bgp_get_channel(p, afi); struct bgp_channel *c = bgp_get_channel(p, afi);
BGP_TRACE(D_PACKETS, "Got END-OF-RIB"); BGP_TRACE(D_PACKETS, "Got END-OF-RIB");
/* XXXX handle unknown AF in MP_*_NLRI */
if (!c) if (!c)
return; DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
if (c->load_state == BFS_LOADING) if (c->load_state == BFS_LOADING)
c->load_state = BFS_NONE; c->load_state = BFS_NONE;
@ -1678,9 +1688,8 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
struct bgp_channel *c = bgp_get_channel(s->proto, afi); struct bgp_channel *c = bgp_get_channel(s->proto, afi);
rta *a = NULL; rta *a = NULL;
/* XXXX handle unknown AF in MP_*_NLRI */
if (!c) if (!c)
return; DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
s->channel = c; s->channel = c;
s->add_path = c->add_path_rx; s->add_path = c->add_path_rx;
@ -1791,12 +1800,12 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
/* Check for End-of-RIB marker */ /* Check for End-of-RIB marker */
if (!s.attr_len && !s.ip_unreach_len && !s.ip_reach_len) if (!s.attr_len && !s.ip_unreach_len && !s.ip_reach_len)
{ bgp_rx_end_mark(p, BGP_AF_IPV4); goto done; } { bgp_rx_end_mark(&s, BGP_AF_IPV4); goto done; }
/* Check for MP End-of-RIB marker */ /* Check for MP End-of-RIB marker */
if ((s.attr_len < 8) && !s.ip_unreach_len && !s.ip_reach_len && if ((s.attr_len < 8) && !s.ip_unreach_len && !s.ip_reach_len &&
!s.mp_reach_len && !s.mp_unreach_len && s.mp_unreach_af) /* XXXX See RFC 7606 5.2 */ !s.mp_reach_len && !s.mp_unreach_len && s.mp_unreach_af)
{ bgp_rx_end_mark(p, s.mp_unreach_af); goto done; } { bgp_rx_end_mark(&s, s.mp_unreach_af); goto done; }
if (s.ip_unreach_len) if (s.ip_unreach_len)
bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_unreach_nlri, s.ip_unreach_len, NULL, NULL, 0); bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_unreach_nlri, s.ip_unreach_len, NULL, NULL, 0);