Commit b99d3786 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Minor BGP changes related to error wait time.

parent 72382626
......@@ -74,7 +74,6 @@ static int bgp_counter; /* Number of protocol instances using the listening so
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 void bgp_stop(struct bgp_proto *p);
static sock *bgp_setup_listen_sk(void);
......@@ -221,9 +220,6 @@ bgp_close_conn(struct bgp_conn *conn)
/**
* bgp_update_startup_delay - update a startup delay
* @p: BGP instance
* @conn: related BGP connection
* @code: BGP error code
* @subcode: BGP error subcode
*
* This function updates a startup delay that is used to postpone next BGP connect.
* It also handles disable_after_error and might stop BGP instance when error
......@@ -232,26 +228,11 @@ bgp_close_conn(struct bgp_conn *conn)
* It should be called when BGP protocol error happened.
*/
void
bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned code, unsigned subcode)
bgp_update_startup_delay(struct bgp_proto *p)
{
struct bgp_config *cf = p->cf;
/* Don't handle cease messages as errors */
if (code == 6 && !subcode && p->last_error_class != BE_AUTO_DOWN)
{
p->startup_delay = 0;
return;
}
/* During start, we only consider errors on outgoing connection, because
otherwise delay timer for outgoing connection is already running and
we could increase delay time two times (or more) per one attempt to
connect.
*/
if ((p->p.proto_state == PS_START) && (conn != &p->outgoing_conn))
return;
DBG("BGP: Updating startup delay %d %d\n", code, subcode);
DBG("BGP: Updating startup delay\n");
if (p->last_proto_error && ((now - p->last_proto_error) >= cf->error_amnesia_time))
p->startup_delay = 0;
......@@ -262,25 +243,17 @@ bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned co
{
p->startup_delay = 0;
p->p.disabled = 1;
if (p->p.proto_state == PS_START)
bgp_stop(p);
return;
}
if (!p->startup_delay)
p->startup_delay = cf->error_delay_time_min;
else
{
p->startup_delay *= 2;
if (p->startup_delay > cf->error_delay_time_max)
p->startup_delay = cf->error_delay_time_max;
}
p->startup_delay = MIN(2 * p->startup_delay, cf->error_delay_time_max);
}
static void
bgp_graceful_close_conn(struct bgp_conn *conn)
bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
{
switch (conn->state)
{
......@@ -294,7 +267,7 @@ bgp_graceful_close_conn(struct bgp_conn *conn)
case BS_OPENSENT:
case BS_OPENCONFIRM:
case BS_ESTABLISHED:
bgp_error(conn, 6, 0, NULL, 0);
bgp_error(conn, 6, subcode, NULL, 0);
return;
default:
bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
......@@ -307,7 +280,7 @@ bgp_down(struct bgp_proto *p)
if (p->start_state > BSS_PREPARE)
bgp_close(p, 1);
DBG("BGP: DOWN\n");
BGP_TRACE(D_EVENTS, "Down");
proto_notify_state(&p->p, PS_DOWN);
}
......@@ -327,12 +300,12 @@ bgp_decision(void *vp)
bgp_down(p);
}
static void
bgp_stop(struct bgp_proto *p)
void
bgp_stop(struct bgp_proto *p, unsigned subcode)
{
proto_notify_state(&p->p, PS_STOP);
bgp_graceful_close_conn(&p->outgoing_conn);
bgp_graceful_close_conn(&p->incoming_conn);
bgp_graceful_close_conn(&p->outgoing_conn, subcode);
bgp_graceful_close_conn(&p->incoming_conn, subcode);
ev_schedule(p->event);
}
......@@ -359,7 +332,7 @@ bgp_conn_leave_established_state(struct bgp_proto *p)
p->conn = NULL;
if (p->p.proto_state == PS_UP)
bgp_stop(p);
bgp_stop(p, 0);
}
void
......@@ -501,7 +474,7 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
static void
bgp_active(struct bgp_proto *p)
{
int delay = MIN(1, p->cf->start_delay_time);
int delay = MAX(1, p->cf->start_delay_time);
struct bgp_conn *conn = &p->outgoing_conn;
BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
......@@ -517,7 +490,8 @@ bgp_apply_limits(struct bgp_proto *p)
{
log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
bgp_stop(p);
bgp_update_startup_delay(p);
bgp_stop(p, 1); // Errcode 6, 1 - max number of prefixes reached
return -1;
}
......@@ -684,7 +658,7 @@ bgp_neigh_notify(neighbor *n)
{
BGP_TRACE(D_EVENTS, "Neighbor lost");
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
bgp_stop(p);
bgp_stop(p, 0);
}
}
}
......@@ -772,11 +746,23 @@ static int
bgp_shutdown(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
unsigned subcode;
BGP_TRACE(D_EVENTS, "Shutdown requested");
bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
if (P->reconfiguring)
{
if (P->cf_new)
subcode = 6; // Errcode 6, 6 - other configuration change
else
subcode = 3; // Errcode 6, 3 - peer de-configured
}
else
subcode = 2; // Errcode 6, 2 - administrative shutdown
p->startup_delay = 0;
bgp_stop(p);
bgp_stop(p, subcode);
return p->p.proto_state;
}
......@@ -815,12 +801,13 @@ bgp_init(struct proto_config *C)
void
bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len)
{
struct bgp_proto *p = c->bgp;
if (c->state == BS_CLOSE)
return;
bgp_log_error(c->bgp, "Error", code, subcode, data, (len > 0) ? len : -len);
bgp_store_error(c->bgp, c, BE_BGP_TX, (code << 16) | subcode);
bgp_update_startup_delay(c->bgp, c, code, subcode);
bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, (len > 0) ? len : -len);
bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode);
bgp_conn_enter_close_state(c);
c->notify_code = code;
......@@ -828,6 +815,12 @@ bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int l
c->notify_data = data;
c->notify_size = (len > 0) ? len : 0;
bgp_schedule_packet(c, PKT_NOTIFICATION);
if (code != 6)
{
bgp_update_startup_delay(p);
bgp_stop(p, 0);
}
}
/**
......
......@@ -129,12 +129,14 @@ void bgp_start_timer(struct timer *t, int value);
void bgp_check(struct bgp_config *c);
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
void bgp_close_conn(struct bgp_conn *c);
void bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned code, unsigned subcode);
void bgp_update_startup_delay(struct bgp_proto *p);
void bgp_conn_enter_established_state(struct bgp_conn *conn);
void bgp_conn_enter_close_state(struct bgp_conn *conn);
void bgp_conn_enter_idle_state(struct bgp_conn *conn);
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
int bgp_apply_limits(struct bgp_proto *p);
void bgp_stop(struct bgp_proto *p, unsigned subcode);
#ifdef LOCAL_DEBUG
......@@ -184,7 +186,7 @@ void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk);
int bgp_rx(struct birdsock *sk, int size);
const byte * bgp_error_dsc(byte *buff, unsigned code, unsigned subcode);
void bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
/* Packet types */
......
......@@ -619,14 +619,14 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
{
/* Should close the other connection */
BGP_TRACE(D_EVENTS, "Connection collision, giving up the other connection");
bgp_error(other, 6, 0, NULL, 0);
bgp_error(other, 6, 7, NULL, 0);
break;
}
/* Fall thru */
case BS_ESTABLISHED:
/* Should close this connection */
BGP_TRACE(D_EVENTS, "Connection collision, giving up this connection");
bgp_error(conn, 6, 0, NULL, 0);
bgp_error(conn, 6, 7, NULL, 0);
return;
default:
bug("bgp_rx_open: Unknown state");
......@@ -957,14 +957,15 @@ bgp_error_dsc(byte *buff, unsigned code, unsigned subcode)
}
void
bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
{
const byte *name;
byte namebuf[32];
byte *t, argbuf[36];
unsigned i;
if (code == 6 && !subcode) /* Don't report Cease messages */
/* Don't report Cease messages generated by myself */
if (code == 6 && class == BE_BGP_TX)
return;
name = bgp_error_dsc(namebuf, code, subcode);
......@@ -994,10 +995,10 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
unsigned code = pkt[19];
unsigned subcode = pkt[20];
int delay = 1;
int err = (code != 6);
bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21);
bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode);
#ifndef IPV6
if ((code == 2) && ((subcode == 4) || (subcode == 7))
......@@ -1014,14 +1015,19 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
{
/* We try connect without capabilities */
log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name);
conn->bgp->start_state = BSS_CONNECT_NOCAP;
delay = 0;
p->start_state = BSS_CONNECT_NOCAP;
err = 0;
}
#endif
if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
bgp_conn_enter_close_state(conn);
bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
if (err)
{
bgp_update_startup_delay(p);
bgp_stop(p, 0);
}
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment