From 7e5f769d91319b4130f7d611dd14252806892ace Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Fri, 15 Mar 2019 20:54:01 +0100 Subject: 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 ++++++++ 1 file changed, 8 insertions(+) (limited to 'proto/bgp/bgp.c') 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; -- cgit v1.2.3 From a22c3e59683d0ea6c379a37f990e74a6d281ccef Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 2 Apr 2019 17:22:31 +0200 Subject: BGP: Separate runtime and config usage of local/remote ip and as fields --- proto/bgp/attrs.c | 2 +- proto/bgp/bgp.c | 63 +++++++++++++++++++++++++++-------------------------- proto/bgp/bgp.h | 6 ++--- proto/bgp/packets.c | 6 ++--- proto/mrt/mrt.c | 4 ++-- 5 files changed, 41 insertions(+), 40 deletions(-) (limited to 'proto/bgp/bgp.c') diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index cbb22038..64a25995 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1733,7 +1733,7 @@ bgp_rte_better(rte *new, rte *old) return 0; /* RFC 4271 9.1.2.2. g) Compare peer IP adresses */ - return (ipa_compare(new_bgp->cf->remote_ip, old_bgp->cf->remote_ip) < 0); + return ipa_compare(new_bgp->remote_ip, old_bgp->remote_ip) < 0; } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 56401a08..756f0326 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -387,7 +387,7 @@ bgp_close_conn(struct bgp_conn *conn) void bgp_update_startup_delay(struct bgp_proto *p) { - struct bgp_config *cf = p->cf; + const struct bgp_config *cf = p->cf; DBG("BGP: Updating startup delay\n"); @@ -504,8 +504,8 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) BGP_TRACE(D_EVENTS, "BGP session established"); /* For multi-hop BGP sessions */ - if (ipa_zero(p->source_addr)) - p->source_addr = conn->sk->saddr; + if (ipa_zero(p->local_ip)) + p->local_ip = conn->sk->saddr; /* In case of LLv6 is not valid during BGP start */ if (ipa_zero(p->link_addr) && p->neigh && p->neigh->iface && p->neigh->iface->llv6) @@ -1047,8 +1047,8 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c DBG("BGP: Connecting\n"); sock *s = sk_new(p->p.pool); s->type = SK_TCP_ACTIVE; - s->saddr = p->source_addr; - s->daddr = p->cf->remote_ip; + s->saddr = p->local_ip; + s->daddr = p->remote_ip; s->dport = p->cf->remote_port; s->iface = p->neigh ? p->neigh->iface : NULL; s->vrf = p->p.vrf; @@ -1209,11 +1209,11 @@ bgp_start_neighbor(struct bgp_proto *p) { /* Called only for single-hop BGP sessions */ - if (ipa_zero(p->source_addr)) - p->source_addr = p->neigh->ifa->ip; + if (ipa_zero(p->local_ip)) + p->local_ip = p->neigh->ifa->ip; - if (ipa_is_link_local(p->source_addr)) - p->link_addr = p->source_addr; + if (ipa_is_link_local(p->local_ip)) + p->link_addr = p->local_ip; else if (p->neigh->iface->llv6) p->link_addr = p->neigh->iface->llv6->ip; @@ -1302,7 +1302,7 @@ static void bgp_update_bfd(struct bgp_proto *p, int use_bfd) { if (use_bfd && !p->bfd_req) - p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr, + p->bfd_req = bfd_request_session(p->p.pool, p->remote_ip, p->local_ip, p->cf->multihop ? NULL : p->neigh->iface, bgp_bfd_notify, p); @@ -1383,7 +1383,7 @@ static void bgp_start_locked(struct object_lock *lock) { struct bgp_proto *p = lock->data; - struct bgp_config *cf = p->cf; + const struct bgp_config *cf = p->cf; if (p->p.proto_state != PS_START) { @@ -1400,10 +1400,10 @@ bgp_start_locked(struct object_lock *lock) return; } - neighbor *n = neigh_find(&p->p, cf->remote_ip, cf->iface, NEF_STICKY); + neighbor *n = neigh_find(&p->p, p->remote_ip, cf->iface, NEF_STICKY); if (!n) { - log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface); + log(L_ERR "%s: Invalid remote address %I%J", p->p.name, p->remote_ip, cf->iface); /* As we do not start yet, we can just disable protocol */ p->p.disabled = 1; bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_NEXT_HOP); @@ -1414,7 +1414,7 @@ bgp_start_locked(struct object_lock *lock) p->neigh = n; if (n->scope <= 0) - BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface); + BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", p->remote_ip, cf->iface); else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name); else @@ -1425,9 +1425,18 @@ static int bgp_start(struct proto *P) { struct bgp_proto *p = (struct bgp_proto *) P; - struct object_lock *lock; + const struct bgp_config *cf = p->cf; + + p->local_ip = cf->local_ip; + p->remote_ip = cf->remote_ip; + p->local_as = cf->local_as; + p->remote_as = cf->remote_as; + p->public_as = cf->local_as; + + /* Confederation ID is used for truly external peers */ + if (p->cf->confederation && !p->is_interior) + p->public_as = cf->confederation; - DBG("BGP: Startup.\n"); p->start_state = BSS_PREPARE; p->outgoing_conn.state = BS_IDLE; p->incoming_conn.state = BS_IDLE; @@ -1445,7 +1454,6 @@ bgp_start(struct proto *P) p->rr_cluster_id = p->cf->rr_cluster_id ? p->cf->rr_cluster_id : p->local_id; p->remote_id = 0; - p->source_addr = p->cf->local_ip; p->link_addr = IPA_NONE; /* Lock all channels when in GR recovery mode */ @@ -1460,9 +1468,9 @@ bgp_start(struct proto *P) * Before attempting to create the connection, we need to lock the port, * so that we are the only instance attempting to talk with that neighbor. */ - + struct object_lock *lock; lock = p->lock = olock_new(P->pool); - lock->addr = p->cf->remote_ip; + lock->addr = p->remote_ip; lock->port = p->cf->remote_port; lock->iface = p->cf->iface; lock->vrf = p->cf->iface ? NULL : p->p.vrf; @@ -1570,18 +1578,11 @@ bgp_init(struct proto_config *CF) P->rte_modify = bgp_rte_modify_stale; p->cf = cf; - p->local_as = cf->local_as; - p->remote_as = cf->remote_as; - p->public_as = cf->local_as; p->is_internal = (cf->local_as == cf->remote_as); p->is_interior = p->is_internal || cf->confederation_member; p->rs_client = cf->rs_client; p->rr_client = cf->rr_client; - /* Confederation ID is used for truly external peers */ - if (cf->confederation && !p->is_interior) - p->public_as = cf->confederation; - /* Add all channels */ struct bgp_channel_config *cc; WALK_LIST(cc, CF->channels) @@ -1612,7 +1613,7 @@ bgp_channel_start(struct channel *C) { struct bgp_proto *p = (void *) C->proto; struct bgp_channel *c = (void *) C; - ip_addr src = p->source_addr; + ip_addr src = p->local_ip; if (c->igp_table_ip4) rt_lock_table(c->igp_table_ip4); @@ -1893,8 +1894,8 @@ static int bgp_reconfigure(struct proto *P, struct proto_config *CF) { struct bgp_proto *p = (void *) P; - struct bgp_config *new = (void *) CF; - struct bgp_config *old = p->cf; + const struct bgp_config *new = (void *) CF; + const struct bgp_config *old = p->cf; if (proto_get_router_id(CF) != p->local_id) return 0; @@ -2241,7 +2242,7 @@ bgp_show_proto_info(struct proto *P) cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p)); cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface); - cli_msg(-1006, " Neighbor AS: %u", p->remote_as); + cli_msg(-1006, " Neighbor AS: %u", p->cf->remote_as); if (p->gr_active_num) cli_msg(-1006, " Neighbor graceful restart active"); @@ -2277,7 +2278,7 @@ bgp_show_proto_info(struct proto *P) p->rr_client ? " route-reflector" : "", p->rs_client ? " route-server" : "", p->as4_session ? " AS4" : ""); - cli_msg(-1006, " Source address: %I", p->source_addr); + cli_msg(-1006, " Source address: %I", p->local_ip); cli_msg(-1006, " Hold timer: %t/%u", tm_remains(p->conn->hold_timer), p->conn->hold_time); cli_msg(-1006, " Keepalive timer: %t/%u", diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 8c7d57b9..512410d4 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -256,7 +256,8 @@ struct bgp_conn { struct bgp_proto { struct proto p; - struct bgp_config *cf; /* Shortcut to BGP configuration */ + const struct bgp_config *cf; /* Shortcut to BGP configuration */ + ip_addr local_ip, remote_ip; u32 local_as, remote_as; u32 public_as; /* Externally visible ASN (local_as or confederation id) */ u32 local_id; /* BGP identifier of this router */ @@ -284,8 +285,7 @@ struct bgp_proto { struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */ struct bgp_socket *sock; /* Shared listening socket */ struct bfd_request *bfd_req; /* BFD request, if BFD is used */ - ip_addr source_addr; /* Local address used as an advertised next hop */ - ip_addr link_addr; /* Link-local version of source_addr */ + ip_addr link_addr; /* Link-local version of local_ip */ event *event; /* Event for respawning and shutting process */ timer *startup_timer; /* Timer used to delay protocol startup due to previous errors (startup_delay) */ timer *gr_timer; /* Timer waiting for reestablishment after graceful restart */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index c09e9859..fc572a21 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -100,7 +100,7 @@ init_mrt_bgp_data(struct bgp_conn *conn, struct mrt_bgp_data *d) d->peer_as = p->remote_as; d->local_as = p->local_as; d->index = (p->neigh && p->neigh->iface) ? p->neigh->iface->index : 0; - d->af = ipa_is_ip4(p->cf->remote_ip) ? BGP_AFI_IPV4 : BGP_AFI_IPV6; + d->af = ipa_is_ip4(p->remote_ip) ? BGP_AFI_IPV4 : BGP_AFI_IPV6; d->peer_ip = conn->sk ? conn->sk->daddr : IPA_NONE; d->local_ip = conn->sk ? conn->sk->saddr : IPA_NONE; d->as4 = p_ok ? p->as4_session : 0; @@ -1007,7 +1007,7 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to) WITHDRAW(NO_NEXT_HOP); ip_addr *nh = (void *) a->u.ptr->data; - ip_addr peer = s->proto->cf->remote_ip; + ip_addr peer = s->proto->remote_ip; uint len = a->u.ptr->length; /* Forbid zero next hop */ @@ -2325,7 +2325,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis a->source = RTS_BGP; a->scope = SCOPE_UNIVERSE; - a->from = s->proto->cf->remote_ip; + a->from = s->proto->remote_ip; a->eattrs = ea; c->desc->decode_next_hop(s, nh, nh_len, a); diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index e4f1acea..7a396a84 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -361,7 +361,7 @@ mrt_peer_table_dump(struct mrt_table_dump_state *s) if ((P->proto == &proto_bgp) && (P->proto_state != PS_DOWN)) { struct bgp_proto *p = (void *) P; - mrt_peer_table_entry(s, p->remote_id, p->remote_as, p->cf->remote_ip); + mrt_peer_table_entry(s, p->remote_id, p->remote_as, p->remote_ip); } #endif @@ -429,7 +429,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r) { struct bgp_proto *p = (void *) r->attrs->src->proto; struct mrt_peer_entry *n = - HASH_FIND(s->peer_hash, PEER, p->remote_id, p->remote_as, p->cf->remote_ip); + HASH_FIND(s->peer_hash, PEER, p->remote_id, p->remote_as, p->remote_ip); peer = n ? n->index : 0; } -- cgit v1.2.3 From 23ee6b1cd6dc597876d91db9a015f7a633764808 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 3 Apr 2019 15:54:50 +0200 Subject: BGP: Promiscuous ASN mode Allow to specify just 'internal' or 'external' for remote neighbor instead of specific ASN. In the second case that means BGP peers with any non-local ASNs are accepted. --- doc/bird.sgml | 11 +++++++---- proto/bgp/bgp.c | 25 ++++++++++++++++++++----- proto/bgp/bgp.h | 5 +++++ proto/bgp/config.Y | 4 +++- proto/bgp/packets.c | 9 +++++++-- 5 files changed, 42 insertions(+), 12 deletions(-) (limited to 'proto/bgp/bgp.c') diff --git a/doc/bird.sgml b/doc/bird.sgml index 52c9d6fd..9675caf0 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -2195,12 +2195,15 @@ using the following configuration parameters: