Adds support for fallback to capabilityless BGP connect
When capability related error is received, next connect will be without capabilities. Also cease error subcodes descriptions (according to [RFC4486]) are added.
This commit is contained in:
parent
591211557f
commit
165a622727
3 changed files with 47 additions and 11 deletions
|
@ -368,6 +368,10 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn)
|
|||
static void
|
||||
bgp_send_open(struct bgp_conn *conn)
|
||||
{
|
||||
conn->start_state = conn->bgp->start_state;
|
||||
conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP);
|
||||
conn->peer_as4_support = 0; // Default value, possibly changed by receiving capability.
|
||||
|
||||
DBG("BGP: Sending open\n");
|
||||
conn->sk->rx_hook = bgp_rx;
|
||||
conn->sk->tx_hook = bgp_tx;
|
||||
|
|
|
@ -51,9 +51,10 @@ struct bgp_conn {
|
|||
int packets_to_send; /* Bitmap of packet types to be sent */
|
||||
int notify_code, notify_subcode, notify_size;
|
||||
byte *notify_data;
|
||||
int error_flag; /* Error state, ignore all input */
|
||||
u32 advertised_as; /* Temporary value for AS number received */
|
||||
int as4_support; /* Peer supports 4B AS numbers [RFC4893] */
|
||||
int start_state; /* protocol start_state snapshot when connection established */
|
||||
int want_as4_support; /* Connection tries to establish AS4 session */
|
||||
int peer_as4_support; /* Peer supports 4B AS numbers [RFC4893] */
|
||||
unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */
|
||||
};
|
||||
|
||||
|
|
|
@ -69,13 +69,21 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
|
|||
put_u16(buf+1, (p->local_as < 0xFFFF) ? p->local_as : AS_TRANS);
|
||||
put_u16(buf+3, p->cf->hold_time);
|
||||
put_u32(buf+5, p->local_id);
|
||||
|
||||
if (conn->start_state == BSS_CONNECT_NOCAP)
|
||||
{
|
||||
BGP_TRACE(D_PACKETS, "Skipping capabilities");
|
||||
buf[9] = 0;
|
||||
return buf + 10;
|
||||
}
|
||||
|
||||
/* Skipped 3 B for length field and Capabilities parameter header */
|
||||
cap = buf + 12;
|
||||
|
||||
#ifdef IPV6
|
||||
cap = bgp_put_cap_ipv6(conn, cap);
|
||||
#endif
|
||||
if (p->cf->enable_as4)
|
||||
if (conn->want_as4_support)
|
||||
cap = bgp_put_cap_as4(conn, cap);
|
||||
|
||||
cap_len = cap - buf - 12;
|
||||
|
@ -418,9 +426,8 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
|
|||
case 65:
|
||||
if (cl != 4)
|
||||
goto err;
|
||||
conn->as4_support = 1;
|
||||
|
||||
if (p->cf->enable_as4)
|
||||
conn->peer_as4_support = 1;
|
||||
if (conn->want_as4_support)
|
||||
conn->advertised_as = get_u32(opt + 2);
|
||||
break;
|
||||
|
||||
|
@ -501,7 +508,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
|||
id = get_u32(pkt+24);
|
||||
BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
|
||||
|
||||
conn->as4_support = 0; // Default value, possibly changed by capability.
|
||||
if (bgp_parse_options(conn, pkt+29, pkt[28]))
|
||||
return;
|
||||
|
||||
|
@ -548,7 +554,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
|||
conn->hold_time = MIN(hold, p->cf->hold_time);
|
||||
conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
|
||||
p->remote_id = id;
|
||||
p->as4_session = p->cf->enable_as4 && conn->as4_support;
|
||||
p->as4_session = conn->want_as4_support && conn->peer_as4_support;
|
||||
|
||||
DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n", conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, p->as4_session);
|
||||
|
||||
|
@ -820,7 +826,15 @@ static struct {
|
|||
{ 3, 11, "Malformed AS_PATH" },
|
||||
{ 4, 0, "Hold timer expired" },
|
||||
{ 5, 0, "Finite state machine error" },
|
||||
{ 6, 0, "Cease" }
|
||||
{ 6, 0, "Cease" }, /* Subcodes are according to [RFC4486] */
|
||||
{ 6, 1, "Maximum number of prefixes reached" },
|
||||
{ 6, 2, "Administrative shutdown" },
|
||||
{ 6, 3, "Peer de-configured" },
|
||||
{ 6, 4, "Administrative reset" },
|
||||
{ 6, 5, "Connection rejected" },
|
||||
{ 6, 6, "Other configuration change" },
|
||||
{ 6, 7, "Connection collision resolution" },
|
||||
{ 6, 8, "Out of Resources" }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -875,6 +889,7 @@ bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, b
|
|||
static void
|
||||
bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
|
||||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
if (len < 21)
|
||||
{
|
||||
bgp_error(conn, 1, 2, pkt+16, 2);
|
||||
|
@ -883,9 +898,25 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
|
|||
|
||||
unsigned code = pkt[19];
|
||||
unsigned subcode = pkt[20];
|
||||
int delay = 1;
|
||||
|
||||
#ifndef IPV6
|
||||
if ((code == 2) && ((subcode == 4) || (subcode == 7)))
|
||||
{
|
||||
/* Error related to capability:
|
||||
* 4 - Peer does not support capabilities at all.
|
||||
* 7 - Peer request some capability. Strange unless it is IPv6 only peer.
|
||||
* We try connect without capabilities
|
||||
*/
|
||||
BGP_TRACE(D_EVENTS, "Capability related error received, capabilities disabled");
|
||||
conn->bgp->start_state = BSS_CONNECT_NOCAP;
|
||||
delay = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
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_update_startup_delay(conn->bgp, conn, code, subcode);
|
||||
if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
|
||||
bgp_conn_enter_close_state(conn);
|
||||
bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue