From ac3ad139f648184d44707ab145fde3a03ef5cb6e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 7 Dec 2016 18:28:07 +0100 Subject: BGP: Add support for flowspec (RFC 5575) --- proto/bgp/config.Y | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'proto/bgp/config.Y') diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 10a338d8..2a54db17 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -28,7 +28,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE, BGP_CLUSTER_LIST, IGP, TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, - STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST) + STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6) %type bgp_afi @@ -139,6 +139,8 @@ bgp_afi: | IPV6 { $$ = BGP_AF_IPV6; } | IPV4 MULTICAST { $$ = BGP_AF_IPV4_MC; } | IPV6 MULTICAST { $$ = BGP_AF_IPV6_MC; } + | FLOW4 { $$ = BGP_AF_FLOW4; } + | FLOW6 { $$ = BGP_AF_FLOW6; } ; bgp_channel_start: bgp_afi -- cgit v1.2.3 From f8aad5d5b7601d0500841e57bafa5796cc3156ab Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Fri, 23 Dec 2016 23:03:26 +0100 Subject: Minor cleanups --- nest/proto.c | 2 +- nest/route.h | 1 + proto/bgp/bgp.c | 8 +++++--- proto/bgp/bgp.h | 12 ------------ proto/bgp/config.Y | 1 + proto/bgp/packets.c | 8 ++++++-- 6 files changed, 14 insertions(+), 18 deletions(-) (limited to 'proto/bgp/config.Y') diff --git a/nest/proto.c b/nest/proto.c index 815d0652..0a7a32a6 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -490,7 +490,7 @@ int channel_reconfigure(struct channel *c, struct channel_config *cf) { /* FIXME: better handle these changes, also handle in_keep_filtered */ - if ((c->table != cf->table->table) || (c->ra_mode != cf->ra_mode)) + if ((c->table != cf->table->table) || (cf->ra_mode && (c->ra_mode != cf->ra_mode))) return 0; int import_changed = !filter_same(c->in_filter, cf->in_filter); diff --git a/nest/route.h b/nest/route.h index d652ca15..12e67d61 100644 --- a/nest/route.h +++ b/nest/route.h @@ -258,6 +258,7 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); /* Types of route announcement, also used as flags */ +#define RA_UNDEF 0 /* Undefined RA type */ #define RA_OPTIMAL 1 /* Announcement of optimal route change */ #define RA_ACCEPTED 2 /* Announcement of first accepted route */ #define RA_ANY 3 /* Announcement of any route change */ diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 5df2e38d..83c16889 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -524,9 +524,13 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) c->add_path_rx = (loc->add_path & BGP_ADD_PATH_RX) && (rem->add_path & BGP_ADD_PATH_TX); c->add_path_tx = (loc->add_path & BGP_ADD_PATH_TX) && (rem->add_path & BGP_ADD_PATH_RX); - // XXXX reset back to non-ANY? + /* Update RA mode */ if (c->add_path_tx) c->c.ra_mode = RA_ANY; + else if (c->cf->secondary) + c->c.ra_mode = RA_ACCEPTED; + else + c->c.ra_mode = RA_OPTIMAL; } p->afi_map = mb_alloc(p->p.pool, num * sizeof(u32)); @@ -1411,8 +1415,6 @@ bgp_channel_init(struct channel *C, struct channel_config *CF) struct bgp_channel *c = (void *) C; struct bgp_channel_config *cf = (void *) CF; - C->ra_mode = cf->secondary ? RA_ACCEPTED : RA_OPTIMAL; - c->cf = cf; c->afi = cf->afi; c->desc = bgp_get_af_desc(c->afi); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index a8a04947..7f5be4ea 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -453,18 +453,6 @@ bgp_unset_attr(ea_list **to, struct linpool *pool, uint code) { eattr *e = bgp_set_attr(to, pool, code, 0, 0); e->type = EAF_TYPE_UNDEF; } - - -/* Hack: although BA_NEXT_HOP attribute has type EAF_TYPE_IP_ADDRESS, in IPv6 - * we store two addesses in it - a global address and a link local address. - */ -#ifdef XXX -#define NEXT_HOP_LENGTH (2*sizeof(ip_addr)) -static inline void set_next_hop(byte *b, ip_addr addr) { ((ip_addr *) b)[0] = addr; ((ip_addr *) b)[1] = IPA_NONE; } -#define NEXT_HOP_LENGTH sizeof(ip_addr) -static inline void set_next_hop(byte *b, ip_addr addr) { ((ip_addr *) b)[0] = addr; } -#endif - 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); diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 2a54db17..7c89fd50 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -152,6 +152,7 @@ bgp_channel_start: bgp_afi this_channel = channel_config_new(&channel_bgp, desc->net, this_proto); BGP_CC->c.name = desc->name; + BGP_CC->c.ra_mode = RA_UNDEF; BGP_CC->afi = $1; BGP_CC->gr_able = 0xff; /* undefined */ }; diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 43149a0c..a7df1c63 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -277,6 +277,12 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) /* Create capability list in buffer */ + /* + * Note that max length is ~ 20+14*af_count. With max 6 channels that is + * 104. Option limit is 253 and buffer size is 4096, so we cannot overflow + * unless we add new capabilities or more AFs. + */ + WALK_AF_CAPS(caps, ac) if (ac->ready) { @@ -350,8 +356,6 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) *buf++ = 0; /* Capability data length */ } - /* FIXME: Should not XXXX 255 */ - return buf; } -- cgit v1.2.3 From d8022d26fc64121c3416abfdb4c38fcbaf81c12e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 24 Jan 2017 02:00:35 +0100 Subject: BGP: Partial support for IPv4 routes with IPv6 next hop (RFC 5549) Mostly capability signalling --- proto/bgp/attrs.c | 2 ++ proto/bgp/bgp.c | 15 +++++++++++++++ proto/bgp/bgp.h | 4 ++++ proto/bgp/config.Y | 1 + proto/bgp/packets.c | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+) (limited to 'proto/bgp/config.Y') diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 35aecdb0..c557403b 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1285,6 +1285,8 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li if (src == NULL) return 0; + // XXXX: Check next hop AF + /* IBGP route reflection, RFC 4456 */ if (p->is_internal && src->is_internal && (p->local_as == src->local_as)) { diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 83c16889..61d24f42 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -521,6 +521,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) if (peer->gr_aware) c->load_state = BFS_LOADING; + c->ext_next_hop = c->cf->ext_next_hop && (bgp_channel_is_ipv6(c) || rem->ext_next_hop); c->add_path_rx = (loc->add_path & BGP_ADD_PATH_RX) && (rem->add_path & BGP_ADD_PATH_TX); c->add_path_tx = (loc->add_path & BGP_ADD_PATH_TX) && (rem->add_path & BGP_ADD_PATH_RX); @@ -1788,6 +1789,7 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps) uint any_mp_bgp = 0; uint any_gr_able = 0; uint any_add_path = 0; + uint any_ext_next_hop = 0; u32 *afl1 = alloca(caps->af_count * sizeof(u32)); u32 *afl2 = alloca(caps->af_count * sizeof(u32)); uint afn1, afn2; @@ -1797,6 +1799,7 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps) any_mp_bgp |= ac->ready; any_gr_able |= ac->gr_able; any_add_path |= ac->add_path; + any_ext_next_hop |= ac->ext_next_hop; } if (any_mp_bgp) @@ -1814,6 +1817,18 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps) if (caps->route_refresh) cli_msg(-1006, " Route refresh"); + if (any_ext_next_hop) + { + cli_msg(-1006, " Extended next hop"); + + afn1 = 0; + WALK_AF_CAPS(caps, ac) + if (ac->ext_next_hop) + afl1[afn1++] = ac->afi; + + bgp_show_afis(-1006, " IPv6 nexthop:", afl1, afn1); + } + if (caps->ext_messages) cli_msg(-1006, " Extended message"); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 7f5be4ea..e5d86075 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -123,6 +123,7 @@ struct bgp_channel_config { u8 gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */ u8 secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */ u8 gr_able; /* Allow full graceful restart for the channel */ + u8 ext_next_hop; /* Allow both IPv4 and IPv6 next hops */ u8 add_path; /* Use ADD-PATH extension [RFC 7911] */ struct rtable_config *igp_table; /* Table used for recursive next hop lookups */ @@ -154,6 +155,7 @@ struct bgp_af_caps { u8 ready; /* Multiprotocol capability, RFC 4760 */ u8 gr_able; /* Graceful restart support, RFC 4724 */ u8 gr_af_flags; /* Graceful restart per-AF flags */ + u8 ext_next_hop; /* Extended IPv6 next hop, RFC 5549 */ u8 add_path; /* Multiple paths support, RFC 7911 */ }; @@ -274,6 +276,8 @@ struct bgp_channel { u8 gr_ready; /* Neighbor could do GR on this AF */ u8 gr_active; /* Neighbor is doing GR and keeping fwd state */ + u8 ext_next_hop; /* Session allows both IPv4 and IPv6 next hops */ + u8 add_path_rx; /* Session expects receive of ADD-PATH extended NLRI */ u8 add_path_tx; /* Session expects transmit of ADD-PATH extended NLRI */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 7c89fd50..8c63b331 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -169,6 +169,7 @@ bgp_channel_item: | GATEWAY RECURSIVE { BGP_CC->gw_mode = GW_RECURSIVE; } | SECONDARY bool { BGP_CC->secondary = $2; } | GRACEFUL RESTART bool { BGP_CC->gr_able = $3; } + | EXTENDED NEXT HOP bool { BGP_CC->ext_next_hop = $4; } | ADD PATHS RX { BGP_CC->add_path = BGP_ADD_PATH_RX; } | ADD PATHS TX { BGP_CC->add_path = BGP_ADD_PATH_TX; } | ADD PATHS bool { BGP_CC->add_path = $3 ? BGP_ADD_PATH_FULL : 0; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index a7df1c63..dbc5fe12 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -228,6 +228,7 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) struct bgp_channel *c; struct bgp_caps *caps; struct bgp_af_caps *ac; + uint any_ext_next_hop = 0; uint any_add_path = 0; byte *data; @@ -259,6 +260,9 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) ac->afi = c->afi; ac->ready = 1; + ac->ext_next_hop = bgp_channel_is_ipv4(c) && c->cf->ext_next_hop; + any_ext_next_hop |= ac->ext_next_hop; + ac->add_path = c->cf->add_path; any_add_path |= ac->add_path; @@ -298,6 +302,23 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf) *buf++ = 0; /* Capability data length */ } + if (any_ext_next_hop) + { + *buf++ = 5; /* Capability 5: Support for extended next hop */ + *buf++ = 0; /* Capability data length, will be fixed later */ + data = buf; + + WALK_AF_CAPS(caps, ac) + if (ac->ext_next_hop) + { + put_af4(buf, ac->afi); + put_u16(buf+4, BGP_AFI_IPV6); + buf += 6; + } + + data[-1] = buf - data; + } + if (caps->ext_messages) { *buf++ = 6; /* Capability 6: Support for extended messages */ @@ -394,6 +415,23 @@ bgp_read_capabilities(struct bgp_conn *conn, struct bgp_caps *caps, byte *pos, i caps->route_refresh = 1; break; + case 5: /* Extended next hop encoding capability, RFC 5549 */ + if (cl % 6) + goto err; + + for (i = 0; i < cl; i += 6) + { + /* Specified only for IPv4 prefixes with IPv6 next hops */ + if ((get_u16(pos+2+i+0) != BGP_AFI_IPV4) || + (get_u16(pos+2+i+4) != BGP_AFI_IPV6)) + continue; + + af = get_af4(pos+2+i); + ac = bgp_get_af_caps(caps, af); + ac->ext_next_hop = 1; + } + break; + case 6: /* Extended message length capability, RFC draft */ if (cl != 0) goto err; -- cgit v1.2.3