diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2013-11-23 11:50:34 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2013-11-23 11:50:34 +0100 |
commit | 736e143fa50607fcd88132291e96089b899af979 (patch) | |
tree | c0fcd5fb3174bae8a39b3a32dfe582b2ccb6df17 /proto/bgp/bgp.c | |
parent | 094d2bdb79e1ffa0a02761fd651aa0f0b6b0c585 (diff) | |
parent | 2b3d52aa421ae1c31e30107beefd82fddbb42854 (diff) |
Merge branch 'master' into add-path
Conflicts:
filter/filter.c
nest/proto.c
nest/rt-table.c
proto/bgp/bgp.h
proto/bgp/config.Y
Diffstat (limited to 'proto/bgp/bgp.c')
-rw-r--r-- | proto/bgp/bgp.c | 70 |
1 files changed, 65 insertions, 5 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index f290f227..81a263bb 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -59,8 +59,8 @@ #include "nest/iface.h" #include "nest/protocol.h" #include "nest/route.h" -#include "nest/locks.h" #include "nest/cli.h" +#include "nest/locks.h" #include "conf/conf.h" #include "lib/socket.h" #include "lib/resource.h" @@ -76,6 +76,7 @@ static void bgp_close(struct bgp_proto *p, int apply_md5); static void bgp_connect(struct bgp_proto *p); static void bgp_active(struct bgp_proto *p); static sock *bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags); +static void bgp_update_bfd(struct bgp_proto *p, int use_bfd); /** @@ -153,8 +154,12 @@ bgp_initiate(struct bgp_proto *p) if (rv < 0) return; + if (p->cf->bfd) + bgp_update_bfd(p, p->cf->bfd); + if (p->startup_delay) { + p->start_state = BSS_DELAY; BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds", p->startup_delay); bgp_start_timer(p->startup_timer, p->startup_delay); } @@ -386,10 +391,12 @@ bgp_conn_enter_close_state(struct bgp_conn *conn) int os = conn->state; bgp_conn_set_state(conn, BS_CLOSE); - tm_stop(conn->hold_timer); tm_stop(conn->keepalive_timer); conn->sk->rx_hook = NULL; + /* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */ + bgp_start_timer(conn->hold_timer, 10); + if (os == BS_ESTABLISHED) bgp_conn_leave_established_state(p); } @@ -483,9 +490,18 @@ static void bgp_hold_timeout(timer *t) { struct bgp_conn *conn = t->data; + struct bgp_proto *p = conn->bgp; DBG("BGP: Hold timeout\n"); + /* We are already closing the connection - just do hangup */ + if (conn->state == BS_CLOSE) + { + BGP_TRACE(D_EVENTS, "Connection stalled"); + bgp_conn_enter_idle_state(conn); + return; + } + /* If there is something in input queue, we are probably congested and perhaps just not processed BGP packets in time. */ @@ -737,6 +753,9 @@ bgp_neigh_notify(neighbor *n) { struct bgp_proto *p = (struct bgp_proto *) n->proto; + if (! (n->flags & NEF_STICKY)) + return; + if (n->scope > 0) { if ((p->p.proto_state == PS_START) && (p->start_state == BSS_PREPARE)) @@ -756,6 +775,37 @@ bgp_neigh_notify(neighbor *n) } } +static void +bgp_bfd_notify(struct bfd_request *req) +{ + struct bgp_proto *p = req->data; + int ps = p->p.proto_state; + + if (req->down && ((ps == PS_START) || (ps == PS_UP))) + { + BGP_TRACE(D_EVENTS, "BFD session down"); + bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN); + if (ps == PS_UP) + bgp_update_startup_delay(p); + bgp_stop(p, 0); + } +} + +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->cf->multihop ? NULL : p->neigh->iface, + bgp_bfd_notify, p); + + if (!use_bfd && p->bfd_req) + { + rfree(p->bfd_req); + p->bfd_req = NULL; + } +} + static int bgp_reload_routes(struct proto *P) { @@ -816,6 +866,7 @@ bgp_start(struct proto *P) p->outgoing_conn.state = BS_IDLE; p->incoming_conn.state = BS_IDLE; p->neigh = NULL; + p->bfd_req = NULL; rt_lock_table(p->igp_table); @@ -845,7 +896,6 @@ bgp_start(struct proto *P) lock->iface = p->cf->iface; lock->type = OBJLOCK_TCP; lock->port = BGP_PORT; - lock->iface = NULL; lock->hook = bgp_start_locked; lock->data = p; olock_acquire(lock); @@ -883,6 +933,7 @@ bgp_shutdown(struct proto *P) subcode = 4; // Errcode 6, 4 - administrative reset break; + case PDC_RX_LIMIT_HIT: case PDC_IN_LIMIT_HIT: subcode = 1; // Errcode 6, 1 - max number of prefixes reached /* log message for compatibility */ @@ -981,6 +1032,9 @@ bgp_check_config(struct bgp_config *c) ipa_has_link_scope(c->source_addr))) cf_error("Multihop BGP cannot be used with link-local addresses"); + if (c->multihop && c->bfd && ipa_zero(c->source_addr)) + cf_error("Multihop BGP with BFD requires specified source address"); + /* Different default based on rs_client */ if (!c->missing_lladdr) @@ -1012,6 +1066,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C) struct bgp_proto *p = (struct bgp_proto *) P; struct bgp_config *old = p->cf; + if (proto_get_router_id(C) != p->local_id) + return 0; + int same = !memcmp(((byte *) old) + sizeof(struct proto_config), ((byte *) new) + sizeof(struct proto_config), // password item is last and must be checked separately @@ -1020,6 +1077,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C) || (old->password && new->password && !strcmp(old->password, new->password))) && (get_igp_table(old) == get_igp_table(new)); + if (same && (p->start_state > BSS_PREPARE)) + bgp_update_bfd(p, new->bfd); + /* We should update our copy of configuration ptr as old configuration will be freed */ if (same) p->cf = new; @@ -1101,7 +1161,7 @@ bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code) static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" }; static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""}; -static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket" }; +static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "BFD session down" }; static char *bgp_auto_errors[] = { "", "Route limit exceeded"}; static const char * @@ -1195,7 +1255,7 @@ bgp_show_proto_info(struct proto *P) cli_msg(-1006, " Source address: %I", p->source_addr); if (P->cf->in_limit) cli_msg(-1006, " Route limit: %d/%d", - p->p.stats.imp_routes, P->cf->in_limit->limit); + p->p.stats.imp_routes + p->p.stats.filt_routes, P->cf->in_limit->limit); cli_msg(-1006, " Hold timer: %d/%d", tm_remains(c->hold_timer), c->hold_time); cli_msg(-1006, " Keepalive timer: %d/%d", |