From 261816b0d4f3d4549a4402b95541b82fc7f10a4b Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 15 Nov 2016 16:24:39 +0100 Subject: BGP: Cluster list item should be prepended Commit 3c09af41... changed behavior of int_set_add() from prepend to append, which makes more sense for community list, but prepend must be used for cluster list. Add int_set_prepend() and use it in cluster list handling code. --- proto/bgp/attrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'proto/bgp') diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 0309c1f7..aa2a3b46 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1077,7 +1077,7 @@ static inline void bgp_cluster_list_prepend(rte *e, ea_list **attrs, struct linpool *pool, u32 cid) { eattr *a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); - bgp_attach_attr(attrs, pool, BA_CLUSTER_LIST, (uintptr_t) int_set_add(pool, a ? a->u.ptr : NULL, cid)); + bgp_attach_attr(attrs, pool, BA_CLUSTER_LIST, (uintptr_t) int_set_prepend(pool, a ? a->u.ptr : NULL, cid)); } static int -- cgit v1.2.3 From ed1a908e535e4333b358d83b472453a2ad6d3f51 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Fri, 25 Nov 2016 11:51:38 +0100 Subject: BGP: Fix memory leak in graceful restart code Prefix and bucket tables are initialized when entering established state but not explicitly freed when leaving it (that is handled by protocol restart). With graceful restart, BGP may enter and leave established state multiple times without hard protocol restart causing memory leak. --- lib/hash.h | 6 ++++++ proto/bgp/attrs.c | 26 ++++++++++++++++++++++++++ proto/bgp/bgp.c | 3 +++ proto/bgp/bgp.h | 2 ++ 4 files changed, 37 insertions(+) (limited to 'proto/bgp') diff --git a/lib/hash.h b/lib/hash.h index 4239b1d8..6995bbc8 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -25,6 +25,12 @@ (v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \ }) +#define HASH_FREE(v) \ + ({ \ + mb_free((v).data); \ + (v) = (typeof(v)){ }; \ + }) + #define HASH_FIND(v,id,key...) \ ({ \ u32 _h = HASH_FN(v, id, key); \ diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index aa2a3b46..9d23374a 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -934,6 +934,15 @@ bgp_init_prefix_table(struct bgp_proto *p, u32 order) p->prefix_slab = sl_new(p->p.pool, sizeof(struct bgp_prefix)); } +void +bgp_free_prefix_table(struct bgp_proto *p) +{ + HASH_FREE(p->prefix_hash); + + rfree(p->prefix_slab); + p->prefix_slab = NULL; +} + static struct bgp_prefix * bgp_get_prefix(struct bgp_proto *p, ip_addr prefix, int pxlen, u32 path_id) { @@ -1940,6 +1949,23 @@ bgp_init_bucket_table(struct bgp_proto *p) // fib_init(&p->prefix_fib, p->p.pool, sizeof(struct bgp_prefix), 0, bgp_init_prefix); } +void +bgp_free_bucket_table(struct bgp_proto *p) +{ + mb_free(p->bucket_hash); + p->bucket_hash = NULL; + + struct bgp_bucket *b; + WALK_LIST_FIRST(b, p->bucket_queue) + { + rem_node(&b->send_node); + mb_free(b); + } + + mb_free(p->withdraw_bucket); + p->withdraw_bucket = NULL; +} + void bgp_get_route_info(rte *e, byte *buf, ea_list *attrs) { diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 8ef4b990..0f1c9446 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -416,6 +416,9 @@ bgp_conn_leave_established_state(struct bgp_proto *p) BGP_TRACE(D_EVENTS, "BGP session closed"); p->conn = NULL; + bgp_free_prefix_table(p); + bgp_free_bucket_table(p); + if (p->p.proto_state == PS_UP) bgp_stop(p, 0); } diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index b4067f3a..d028bef4 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -253,8 +253,10 @@ int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_be void bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs); int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *); void bgp_init_bucket_table(struct bgp_proto *); +void bgp_free_bucket_table(struct bgp_proto *p); void bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck); void bgp_init_prefix_table(struct bgp_proto *p, u32 order); +void bgp_free_prefix_table(struct bgp_proto *p); void bgp_free_prefix(struct bgp_proto *p, struct bgp_prefix *bp); uint bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains); void bgp_get_route_info(struct rte *, byte *buf, struct ea_list *attrs); -- cgit v1.2.3 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) --- lib/flowspec.h | 3 + proto/bgp/attrs.c | 16 +++- proto/bgp/bgp.c | 2 +- proto/bgp/bgp.h | 3 + proto/bgp/config.Y | 4 +- proto/bgp/packets.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 247 insertions(+), 6 deletions(-) (limited to 'proto/bgp') diff --git a/lib/flowspec.h b/lib/flowspec.h index 57809bec..aa9735f4 100644 --- a/lib/flowspec.h +++ b/lib/flowspec.h @@ -42,6 +42,9 @@ const char *flow_type_str(enum flow_type type, int ipv6); uint flow_write_length(byte *data, u16 len); +static inline u16 flow_hdr_length(const byte *data) +{ return ((*data & 0xf0) == 0xf0) ? 2 : 1; } + static inline u16 flow_read_length(const byte *data) { return ((*data & 0xf0) == 0xf0) ? get_u16(data) & 0x0fff : *data; } diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 52b56efa..227ddadc 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1221,8 +1221,8 @@ bgp_init_prefix_table(struct bgp_channel *c) { HASH_INIT(c->prefix_hash, c->pool, 8); - c->prefix_slab = sl_new(c->pool, sizeof(struct bgp_prefix) + - net_addr_length[c->c.net_type]); + uint alen = net_addr_length[c->c.net_type]; + c->prefix_slab = alen ? sl_new(c->pool, sizeof(struct bgp_prefix) + alen) : NULL; } static struct bgp_prefix * @@ -1237,7 +1237,11 @@ bgp_get_prefix(struct bgp_channel *c, net_addr *net, u32 path_id) return px; } - px = sl_alloc(c->prefix_slab); + if (c->prefix_slab) + px = sl_alloc(c->prefix_slab); + else + px = mb_alloc(c->pool, sizeof(struct bgp_prefix) + net->length); + px->buck_node.next = NULL; px->buck_node.prev = NULL; px->hash = hash; @@ -1254,7 +1258,11 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) { rem_node(&px->buck_node); HASH_REMOVE2(c->prefix_hash, PXH, c->pool, px); - sl_free(c->prefix_slab, px); + + if (c->prefix_slab) + sl_free(c->prefix_slab, px); + else + mb_free(px); } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 2ca153ab..b7229429 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1846,7 +1846,7 @@ struct protocol proto_bgp = { .template = "bgp%d", .attr_class = EAP_BGP, .preference = DEF_PREF_BGP, - .channel_mask = NB_IP, + .channel_mask = NB_IP | NB_FLOW4 | NB_FLOW6, .proto_size = sizeof(struct bgp_proto), .config_size = sizeof(struct bgp_config), .postconfig = bgp_postconfig, diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 4ecb86a0..db9ee8ea 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -31,6 +31,7 @@ struct eattr; #define BGP_SAFI_UNICAST 1 #define BGP_SAFI_MULTICAST 2 +#define BGP_SAFI_FLOW 133 /* Internal AF codes */ @@ -42,6 +43,8 @@ struct eattr; #define BGP_AF_IPV6 BGP_AF( BGP_AFI_IPV6, BGP_SAFI_UNICAST ) #define BGP_AF_IPV4_MC BGP_AF( BGP_AFI_IPV4, BGP_SAFI_MULTICAST ) #define BGP_AF_IPV6_MC BGP_AF( BGP_AFI_IPV6, BGP_SAFI_MULTICAST ) +#define BGP_AF_FLOW4 BGP_AF( BGP_AFI_IPV4, BGP_SAFI_FLOW ) +#define BGP_AF_FLOW6 BGP_AF( BGP_AFI_IPV6, BGP_SAFI_FLOW ) struct bgp_write_state; 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 diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 66561ee4..1ae75a64 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -20,6 +20,7 @@ #include "nest/mrtdump.h" #include "conf/conf.h" #include "lib/unaligned.h" +#include "lib/flowspec.h" #include "lib/socket.h" #include "nest/cli.h" @@ -793,6 +794,26 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to) WITHDRAW(BAD_NEXT_HOP); } +static uint +bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED) +{ + // FIXME + return 0; +} + +static void +bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED) +{ + // FIXME + return; +} + +static void +bgp_update_next_hop_none(struct bgp_export_state *s UNUSED, eattr *a UNUSED, ea_list **to UNUSED) +{ + // FIXME +} + /* * UPDATE @@ -1066,6 +1087,190 @@ bgp_decode_next_hop_ip6(struct bgp_parse_state *s, byte *data, uint len, rta *a) } +static uint +bgp_encode_nlri_flow4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size) +{ + byte *pos = buf; + + while (!EMPTY_LIST(buck->prefixes) && (size >= 4)) + { + struct bgp_prefix *px = HEAD(buck->prefixes); + struct net_addr_flow4 *net = (void *) px->net; + uint flen = net->length - sizeof(net_addr_flow4); + + /* Encode path ID */ + if (s->add_path) + { + put_u32(pos, px->path_id); + ADVANCE(pos, size, 4); + } + + if (flen > size) + break; + + /* Copy whole flow data including length */ + memcpy(pos, net->data, flen); + ADVANCE(pos, size, flen); + + bgp_free_prefix(s->channel, px); + } + + return pos - buf; +} + +static void +bgp_decode_nlri_flow4(struct bgp_parse_state *s, byte *pos, uint len, rta *a) +{ + while (len) + { + u32 path_id = 0; + + /* Decode path ID */ + if (s->add_path) + { + if (len < 4) + bgp_parse_error(s, 1); + + path_id = get_u32(pos); + ADVANCE(pos, len, 4); + } + + if (len < 2) + bgp_parse_error(s, 1); + + /* Decode flow length */ + uint hlen = flow_hdr_length(pos); + uint dlen = flow_read_length(pos); + uint flen = hlen + dlen; + byte *data = pos + hlen; + + if (len < flen) + bgp_parse_error(s, 1); + + /* Validate flow data */ + enum flow_validated_state r = flow4_validate(data, dlen); + if (r != FLOW_ST_VALID) + { + log(L_REMOTE "%s: Invalid flow route: %s", s->proto->p.name, flow_validated_state_str(r)); + bgp_parse_error(s, 1); + } + + if (data[0] != FLOW_TYPE_DST_PREFIX) + { + log(L_REMOTE "%s: No dst prefix at first pos", s->proto->p.name); + bgp_parse_error(s, 1); + } + + /* Decode dst prefix */ + ip4_addr px = IP4_NONE; + uint pxlen = data[1]; + + // FIXME: Use some generic function + memcpy(&px, data, BYTES(pxlen)); + px = ip4_and(px, ip4_mkmask(pxlen)); + + /* Prepare the flow */ + net_addr *n = alloca(sizeof(struct net_addr_flow4) + flen); + net_fill_flow4(n, px, pxlen, pos, flen); + ADVANCE(pos, len, flen); + + bgp_rte_update(s, n, path_id, a); + } +} + + +static uint +bgp_encode_nlri_flow6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size) +{ + byte *pos = buf; + + while (!EMPTY_LIST(buck->prefixes) && (size >= 4)) + { + struct bgp_prefix *px = HEAD(buck->prefixes); + struct net_addr_flow6 *net = (void *) px->net; + uint flen = net->length - sizeof(net_addr_flow6); + + /* Encode path ID */ + if (s->add_path) + { + put_u32(pos, px->path_id); + ADVANCE(pos, size, 4); + } + + if (flen > size) + break; + + /* Copy whole flow data including length */ + memcpy(pos, net->data, flen); + ADVANCE(pos, size, flen); + + bgp_free_prefix(s->channel, px); + } + + return pos - buf; +} + +static void +bgp_decode_nlri_flow6(struct bgp_parse_state *s, byte *pos, uint len, rta *a) +{ + while (len) + { + u32 path_id = 0; + + /* Decode path ID */ + if (s->add_path) + { + if (len < 4) + bgp_parse_error(s, 1); + + path_id = get_u32(pos); + ADVANCE(pos, len, 4); + } + + if (len < 2) + bgp_parse_error(s, 1); + + /* Decode flow length */ + uint hlen = flow_hdr_length(pos); + uint dlen = flow_read_length(pos); + uint flen = hlen + dlen; + byte *data = pos + hlen; + + if (len < flen) + bgp_parse_error(s, 1); + + /* Validate flow data */ + enum flow_validated_state r = flow6_validate(data, dlen); + if (r != FLOW_ST_VALID) + { + log(L_REMOTE "%s: Invalid flow route: %s", s->proto->p.name, flow_validated_state_str(r)); + bgp_parse_error(s, 1); + } + + if (data[0] != FLOW_TYPE_DST_PREFIX) + { + log(L_REMOTE "%s: No dst prefix at first pos", s->proto->p.name); + bgp_parse_error(s, 1); + } + + /* Decode dst prefix */ + ip6_addr px = IP6_NONE; + uint pxlen = data[1]; + + // FIXME: Use some generic function + memcpy(&px, data, BYTES(pxlen)); + px = ip6_and(px, ip6_mkmask(pxlen)); + + /* Prepare the flow */ + net_addr *n = alloca(sizeof(struct net_addr_flow6) + flen); + net_fill_flow6(n, px, pxlen, pos, flen); + ADVANCE(pos, len, flen); + + bgp_rte_update(s, n, path_id, a); + } +} + + static const struct bgp_af_desc bgp_af_table[] = { { .afi = BGP_AF_IPV4, @@ -1087,6 +1292,16 @@ static const struct bgp_af_desc bgp_af_table[] = { .decode_next_hop = bgp_decode_next_hop_ip4, .update_next_hop = bgp_update_next_hop_ip, }, + { + .afi = BGP_AF_FLOW4, + .net = NET_FLOW4, + .name = "flow4", + .encode_nlri = bgp_encode_nlri_flow4, + .decode_nlri = bgp_decode_nlri_flow4, + .encode_next_hop = bgp_encode_next_hop_none, + .decode_next_hop = bgp_decode_next_hop_none, + .update_next_hop = bgp_update_next_hop_none, + }, { .afi = BGP_AF_IPV6, .net = NET_IP6, @@ -1107,6 +1322,16 @@ static const struct bgp_af_desc bgp_af_table[] = { .decode_next_hop = bgp_decode_next_hop_ip6, .update_next_hop = bgp_update_next_hop_ip, }, + { + .afi = BGP_AF_FLOW6, + .net = NET_FLOW6, + .name = "flow6", + .encode_nlri = bgp_encode_nlri_flow6, + .decode_nlri = bgp_decode_nlri_flow6, + .encode_next_hop = bgp_encode_next_hop_none, + .decode_next_hop = bgp_decode_next_hop_none, + .update_next_hop = bgp_update_next_hop_none, + }, }; const struct bgp_af_desc * -- cgit v1.2.3 From 256cc8ee0867d7f5314d3a3d7db5429d2bf16b4e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 20 Dec 2016 17:39:59 +0100 Subject: BGP: Report capabilities in show protocols all --- proto/bgp/bgp.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++----- proto/bgp/bgp.h | 4 ++ proto/bgp/packets.c | 3 -- 3 files changed, 118 insertions(+), 14 deletions(-) (limited to 'proto/bgp') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b7229429..5df2e38d 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1756,11 +1756,118 @@ bgp_get_status(struct proto *P, byte *buf) bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2); } +static void +bgp_show_afis(int code, char *s, u32 *afis, uint count) +{ + buffer b; + LOG_BUFFER_INIT(b); + + buffer_puts(&b, s); + + for (u32 *af = afis; af < (afis + count); af++) + { + const struct bgp_af_desc *desc = bgp_get_af_desc(*af); + if (desc) + buffer_print(&b, " %s", desc->name); + else + buffer_print(&b, " <%u/%u>", BGP_AFI(*af), BGP_SAFI(*af)); + } + + if (b.pos == b.end) + strcpy(b.end - 32, " ... "); + + cli_msg(code, b.start); +} + +static void +bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps) +{ + struct bgp_af_caps *ac; + uint any_mp_bgp = 0; + uint any_gr_able = 0; + uint any_add_path = 0; + u32 *afl1 = alloca(caps->af_count * sizeof(u32)); + u32 *afl2 = alloca(caps->af_count * sizeof(u32)); + uint afn1, afn2; + + WALK_AF_CAPS(caps, ac) + { + any_mp_bgp |= ac->ready; + any_gr_able |= ac->gr_able; + any_add_path |= ac->add_path; + } + + if (any_mp_bgp) + { + cli_msg(-1006, " Multiprotocol"); + + afn1 = 0; + WALK_AF_CAPS(caps, ac) + if (ac->ready) + afl1[afn1++] = ac->afi; + + bgp_show_afis(-1006, " AF announced:", afl1, afn1); + } + + if (caps->route_refresh) + cli_msg(-1006, " Route refresh"); + + if (caps->ext_messages) + cli_msg(-1006, " Extended message"); + + if (caps->gr_aware) + cli_msg(-1006, " Graceful restart"); + + if (any_gr_able) + { + /* Continues from gr_aware */ + cli_msg(-1006, " Restart time: %u", caps->gr_time); + if (caps->gr_flags & BGP_GRF_RESTART) + cli_msg(-1006, " Restart recovery"); + + afn1 = afn2 = 0; + WALK_AF_CAPS(caps, ac) + { + if (ac->gr_able) + afl1[afn1++] = ac->afi; + + if (ac->gr_af_flags & BGP_GRF_FORWARDING) + afl2[afn2++] = ac->afi; + } + + bgp_show_afis(-1006, " AF supported:", afl1, afn1); + bgp_show_afis(-1006, " AF preserved:", afl2, afn2); + } + + if (caps->as4_support) + cli_msg(-1006, " 4-octet AS numbers"); + + if (any_add_path) + { + cli_msg(-1006, " ADD-PATH"); + + afn1 = afn2 = 0; + WALK_AF_CAPS(caps, ac) + { + if (ac->add_path & BGP_ADD_PATH_RX) + afl1[afn1++] = ac->afi; + + if (ac->add_path & BGP_ADD_PATH_TX) + afl2[afn2++] = ac->afi; + } + + bgp_show_afis(-1006, " RX:", afl1, afn1); + bgp_show_afis(-1006, " TX:", afl2, afn2); + } + + if (caps->enhanced_refresh) + cli_msg(-1006, " Enhanced refresh"); +} + static void bgp_show_proto_info(struct proto *P) { struct bgp_proto *p = (struct bgp_proto *) P; - struct bgp_conn *c = p->conn; cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p)); cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface); @@ -1789,15 +1896,11 @@ bgp_show_proto_info(struct proto *P) else if (P->proto_state == PS_UP) { cli_msg(-1006, " Neighbor ID: %R", p->remote_id); + cli_msg(-1006, " Local capabilities"); + bgp_show_capabilities(p, p->conn->local_caps); + cli_msg(-1006, " Neighbor capabilities"); + bgp_show_capabilities(p, p->conn->remote_caps); /* XXXX - cli_msg(-1006, " Neighbor caps: %s%s%s%s%s%s%s", - c->peer_refresh_support ? " refresh" : "", - c->peer_enhanced_refresh_support ? " enhanced-refresh" : "", - c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""), - c->peer_as4_support ? " AS4" : "", - (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "", - (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "", - c->peer_ext_messages_support ? " ext-messages" : ""); cli_msg(-1006, " Session: %s%s%s%s%s%s%s%s", p->is_internal ? "internal" : "external", p->cf->multihop ? " multihop" : "", @@ -1810,9 +1913,9 @@ bgp_show_proto_info(struct proto *P) */ cli_msg(-1006, " Source address: %I", p->source_addr); cli_msg(-1006, " Hold timer: %d/%d", - tm_remains(c->hold_timer), c->hold_time); + tm_remains(p->conn->hold_timer), p->conn->hold_time); cli_msg(-1006, " Keepalive timer: %d/%d", - tm_remains(c->keepalive_timer), c->keepalive_time); + tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time); } if ((p->last_error_class != BE_NONE) && diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index db9ee8ea..a8a04947 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -174,6 +174,10 @@ struct bgp_caps { struct bgp_af_caps af_data[0]; /* Per-AF capability data */ }; +#define WALK_AF_CAPS(caps,ac) \ + for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++) + + struct bgp_socket { node n; /* Node in global bgp_sockets */ sock *sk; /* Real listening socket */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 1ae75a64..43149a0c 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -185,9 +185,6 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf) /* Capability negotiation as per RFC 5492 */ -#define WALK_AF_CAPS(caps,ac) \ - for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++) - const struct bgp_af_caps * bgp_find_af_caps(struct bgp_caps *caps, u32 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') 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 5509e17d0c1b4e75d5911864f75ba119769e5725 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Sun, 22 Jan 2017 16:32:42 +0100 Subject: BGP: Support for AS confederations (RFC 5065) --- doc/bird.sgml | 26 ++++- nest/a-path.c | 331 ++++++++++++++++++++++++++++++++--------------------- nest/a-path_test.c | 10 +- nest/attrs.h | 7 +- proto/bgp/attrs.c | 88 +++++++------- 5 files changed, 277 insertions(+), 185 deletions(-) (limited to 'proto/bgp') diff --git a/doc/bird.sgml b/doc/bird.sgml index 999fa294..ff2c188f 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1945,12 +1945,11 @@ avoid routing loops.

BIRD supports all requirements of the BGP4 standard as defined in It also supports the community attributes (), -capability negotiation (), MD5 password authentication (), extended communities (), route reflectors (), graceful restart (), multiprotocol extensions -(), 4B AS numbers (), and 4B AS numbers in -extended communities (). - +capability negotiation (), MD5 password authentication +(), extended communities (), route reflectors +(), AS confederations (), graceful restart +(), multiprotocol extensions (), 4B AS numbers +(), and 4B AS numbers in extended communities (). For IPv6, it uses the standard multiprotocol extensions defined in and applied to IPv6 according to . @@ -2134,6 +2133,21 @@ using the following configuration parameters: accepting incoming connections. In passive mode, outgoing connections are not initiated. Default: off. +