BGP: Extended messages support
Implements draft-ietf-idr-bgp-extended-messages-10, for now undocumented and with temporary private capability number.
This commit is contained in:
parent
ab4da3423d
commit
06e0d1b692
5 changed files with 54 additions and 15 deletions
|
@ -1571,7 +1571,7 @@ RFC 4271<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4271.txt">
|
||||||
It also supports the community attributes
|
It also supports the community attributes
|
||||||
(RFC 1997<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1997.txt">),
|
(RFC 1997<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1997.txt">),
|
||||||
capability negotiation
|
capability negotiation
|
||||||
(RFC 3392<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3392.txt">),
|
(RFC 5492<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5492.txt">),
|
||||||
MD5 password authentication
|
MD5 password authentication
|
||||||
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
|
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
|
||||||
extended communities
|
extended communities
|
||||||
|
|
|
@ -569,6 +569,7 @@ bgp_send_open(struct bgp_conn *conn)
|
||||||
conn->peer_gr_time = 0;
|
conn->peer_gr_time = 0;
|
||||||
conn->peer_gr_flags = 0;
|
conn->peer_gr_flags = 0;
|
||||||
conn->peer_gr_aflags = 0;
|
conn->peer_gr_aflags = 0;
|
||||||
|
conn->peer_ext_messages_support = 0;
|
||||||
|
|
||||||
DBG("BGP: Sending open\n");
|
DBG("BGP: Sending open\n");
|
||||||
conn->sk->rx_hook = bgp_rx;
|
conn->sk->rx_hook = bgp_rx;
|
||||||
|
@ -733,8 +734,8 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
|
||||||
s->dport = p->cf->remote_port;
|
s->dport = p->cf->remote_port;
|
||||||
s->iface = p->neigh ? p->neigh->iface : NULL;
|
s->iface = p->neigh ? p->neigh->iface : NULL;
|
||||||
s->ttl = p->cf->ttl_security ? 255 : hops;
|
s->ttl = p->cf->ttl_security ? 255 : hops;
|
||||||
s->rbsize = BGP_RX_BUFFER_SIZE;
|
s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE;
|
||||||
s->tbsize = BGP_TX_BUFFER_SIZE;
|
s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE;
|
||||||
s->tos = IP_PREC_INTERNET_CONTROL;
|
s->tos = IP_PREC_INTERNET_CONTROL;
|
||||||
s->password = p->cf->password;
|
s->password = p->cf->password;
|
||||||
s->tx_hook = bgp_connected;
|
s->tx_hook = bgp_connected;
|
||||||
|
@ -843,6 +844,13 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
|
||||||
if (sk_set_min_ttl(sk, 256 - hops) < 0)
|
if (sk_set_min_ttl(sk, 256 - hops) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
if (p->cf->enable_extended_messages)
|
||||||
|
{
|
||||||
|
sk->rbsize = BGP_RX_BUFFER_EXT_SIZE;
|
||||||
|
sk->tbsize = BGP_TX_BUFFER_EXT_SIZE;
|
||||||
|
sk_reallocate(sk);
|
||||||
|
}
|
||||||
|
|
||||||
bgp_setup_conn(p, &p->incoming_conn);
|
bgp_setup_conn(p, &p->incoming_conn);
|
||||||
bgp_setup_sk(&p->incoming_conn, sk);
|
bgp_setup_sk(&p->incoming_conn, sk);
|
||||||
bgp_send_open(&p->incoming_conn);
|
bgp_send_open(&p->incoming_conn);
|
||||||
|
@ -1518,21 +1526,23 @@ bgp_show_proto_info(struct proto *P)
|
||||||
else if (P->proto_state == PS_UP)
|
else if (P->proto_state == PS_UP)
|
||||||
{
|
{
|
||||||
cli_msg(-1006, " Neighbor ID: %R", p->remote_id);
|
cli_msg(-1006, " Neighbor ID: %R", p->remote_id);
|
||||||
cli_msg(-1006, " Neighbor caps: %s%s%s%s%s%s",
|
cli_msg(-1006, " Neighbor caps: %s%s%s%s%s%s%s",
|
||||||
c->peer_refresh_support ? " refresh" : "",
|
c->peer_refresh_support ? " refresh" : "",
|
||||||
c->peer_enhanced_refresh_support ? " enhanced-refresh" : "",
|
c->peer_enhanced_refresh_support ? " enhanced-refresh" : "",
|
||||||
c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),
|
c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),
|
||||||
c->peer_as4_support ? " AS4" : "",
|
c->peer_as4_support ? " AS4" : "",
|
||||||
(c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
|
(c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
|
||||||
(c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "");
|
(c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "",
|
||||||
cli_msg(-1006, " Session: %s%s%s%s%s%s%s",
|
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->is_internal ? "internal" : "external",
|
||||||
p->cf->multihop ? " multihop" : "",
|
p->cf->multihop ? " multihop" : "",
|
||||||
p->rr_client ? " route-reflector" : "",
|
p->rr_client ? " route-reflector" : "",
|
||||||
p->rs_client ? " route-server" : "",
|
p->rs_client ? " route-server" : "",
|
||||||
p->as4_session ? " AS4" : "",
|
p->as4_session ? " AS4" : "",
|
||||||
p->add_path_rx ? " add-path-rx" : "",
|
p->add_path_rx ? " add-path-rx" : "",
|
||||||
p->add_path_tx ? " add-path-tx" : "");
|
p->add_path_tx ? " add-path-tx" : "",
|
||||||
|
p->ext_messages ? " ext-messages" : "");
|
||||||
cli_msg(-1006, " Source address: %I", p->source_addr);
|
cli_msg(-1006, " Source address: %I", p->source_addr);
|
||||||
if (P->cf->in_limit)
|
if (P->cf->in_limit)
|
||||||
cli_msg(-1006, " Route limit: %d/%d",
|
cli_msg(-1006, " Route limit: %d/%d",
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct bgp_config {
|
||||||
int capabilities; /* Enable capability handshake [RFC3392] */
|
int capabilities; /* Enable capability handshake [RFC3392] */
|
||||||
int enable_refresh; /* Enable local support for route refresh [RFC2918] */
|
int enable_refresh; /* Enable local support for route refresh [RFC2918] */
|
||||||
int enable_as4; /* Enable local support for 4B AS numbers [RFC4893] */
|
int enable_as4; /* Enable local support for 4B AS numbers [RFC4893] */
|
||||||
|
int enable_extended_messages; /* Enable local support for extended messages [draft] */
|
||||||
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
|
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
|
||||||
int rr_client; /* Whether neighbor is RR client of me */
|
int rr_client; /* Whether neighbor is RR client of me */
|
||||||
int rs_client; /* Whether neighbor is RS client of me */
|
int rs_client; /* Whether neighbor is RS client of me */
|
||||||
|
@ -109,6 +110,7 @@ struct bgp_conn {
|
||||||
u16 peer_gr_time;
|
u16 peer_gr_time;
|
||||||
u8 peer_gr_flags;
|
u8 peer_gr_flags;
|
||||||
u8 peer_gr_aflags;
|
u8 peer_gr_aflags;
|
||||||
|
u8 peer_ext_messages_support; /* Peer supports extended message length [draft] */
|
||||||
unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */
|
unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,6 +123,7 @@ struct bgp_proto {
|
||||||
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
|
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
|
||||||
u8 add_path_rx; /* Session expects receive of ADD-PATH extended NLRI */
|
u8 add_path_rx; /* Session expects receive of ADD-PATH extended NLRI */
|
||||||
u8 add_path_tx; /* Session expects transmit of ADD-PATH extended NLRI */
|
u8 add_path_tx; /* Session expects transmit of ADD-PATH extended NLRI */
|
||||||
|
u8 ext_messages; /* Session allows to use extended messages (both sides support it) */
|
||||||
u32 local_id; /* BGP identifier of this router */
|
u32 local_id; /* BGP identifier of this router */
|
||||||
u32 remote_id; /* BGP identifier of the neighbor */
|
u32 remote_id; /* BGP identifier of the neighbor */
|
||||||
u32 rr_cluster_id; /* Route reflector cluster ID */
|
u32 rr_cluster_id; /* Route reflector cluster ID */
|
||||||
|
@ -180,9 +183,15 @@ struct bgp_bucket {
|
||||||
#define BGP_PORT 179
|
#define BGP_PORT 179
|
||||||
#define BGP_VERSION 4
|
#define BGP_VERSION 4
|
||||||
#define BGP_HEADER_LENGTH 19
|
#define BGP_HEADER_LENGTH 19
|
||||||
#define BGP_MAX_PACKET_LENGTH 4096
|
#define BGP_MAX_MESSAGE_LENGTH 4096
|
||||||
|
#define BGP_MAX_EXT_MSG_LENGTH 65535
|
||||||
#define BGP_RX_BUFFER_SIZE 4096
|
#define BGP_RX_BUFFER_SIZE 4096
|
||||||
#define BGP_TX_BUFFER_SIZE BGP_MAX_PACKET_LENGTH
|
#define BGP_TX_BUFFER_SIZE 4096
|
||||||
|
#define BGP_RX_BUFFER_EXT_SIZE 65535
|
||||||
|
#define BGP_TX_BUFFER_EXT_SIZE 65535
|
||||||
|
|
||||||
|
static inline int bgp_max_packet_length(struct bgp_proto *p)
|
||||||
|
{ return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; }
|
||||||
|
|
||||||
extern struct linpool *bgp_linpool;
|
extern struct linpool *bgp_linpool;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
|
||||||
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
|
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
|
||||||
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
|
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
|
||||||
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
|
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
|
||||||
CHECK, LINK, PORT)
|
CHECK, LINK, PORT, EXTENDED, MESSAGES)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ bgp_proto:
|
||||||
| bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; }
|
| bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; }
|
||||||
| bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
|
| bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
|
||||||
| bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
|
| bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
|
||||||
|
| bgp_proto ENABLE EXTENDED MESSAGES bool ';' { BGP_CFG->enable_extended_messages = $5; }
|
||||||
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
|
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
|
||||||
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
|
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
|
||||||
| bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
|
| bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
|
||||||
|
|
|
@ -84,7 +84,7 @@ mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
|
||||||
static void
|
static void
|
||||||
mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
|
mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
|
||||||
{
|
{
|
||||||
byte buf[BGP_MAX_PACKET_LENGTH + 128];
|
byte *buf = alloca(128+len); /* 128 is enough for MRT headers */
|
||||||
byte *bp = buf + MRTDUMP_HDR_LENGTH;
|
byte *bp = buf + MRTDUMP_HDR_LENGTH;
|
||||||
int as4 = conn->bgp->as4_session;
|
int as4 = conn->bgp->as4_session;
|
||||||
|
|
||||||
|
@ -223,6 +223,14 @@ bgp_put_cap_err(struct bgp_proto *p UNUSED, byte *buf)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte *
|
||||||
|
bgp_put_cap_ext_msg(struct bgp_proto *p UNUSED, byte *buf)
|
||||||
|
{
|
||||||
|
*buf++ = 230; /* Capability TBD: Support for extended messages */
|
||||||
|
*buf++ = 0; /* Capability data length */
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static byte *
|
static byte *
|
||||||
bgp_create_open(struct bgp_conn *conn, byte *buf)
|
bgp_create_open(struct bgp_conn *conn, byte *buf)
|
||||||
|
@ -274,6 +282,9 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
|
||||||
if (p->cf->enable_refresh)
|
if (p->cf->enable_refresh)
|
||||||
cap = bgp_put_cap_err(p, cap);
|
cap = bgp_put_cap_err(p, cap);
|
||||||
|
|
||||||
|
if (p->cf->enable_extended_messages)
|
||||||
|
cap = bgp_put_cap_ext_msg(p, cap);
|
||||||
|
|
||||||
cap_len = cap - buf - 12;
|
cap_len = cap - buf - 12;
|
||||||
if (cap_len > 0)
|
if (cap_len > 0)
|
||||||
{
|
{
|
||||||
|
@ -342,7 +353,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
|
||||||
{
|
{
|
||||||
struct bgp_proto *p = conn->bgp;
|
struct bgp_proto *p = conn->bgp;
|
||||||
struct bgp_bucket *buck;
|
struct bgp_bucket *buck;
|
||||||
int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
|
int remains = bgp_max_packet_length(p) - BGP_HEADER_LENGTH - 4;
|
||||||
byte *w;
|
byte *w;
|
||||||
int wd_size = 0;
|
int wd_size = 0;
|
||||||
int r_size = 0;
|
int r_size = 0;
|
||||||
|
@ -428,7 +439,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
|
||||||
struct bgp_proto *p = conn->bgp;
|
struct bgp_proto *p = conn->bgp;
|
||||||
struct bgp_bucket *buck;
|
struct bgp_bucket *buck;
|
||||||
int size, second, rem_stored;
|
int size, second, rem_stored;
|
||||||
int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
|
int remains = bgp_max_packet_length(p) - BGP_HEADER_LENGTH - 4;
|
||||||
byte *w, *w_stored, *tmp, *tstart;
|
byte *w, *w_stored, *tmp, *tstart;
|
||||||
ip_addr *ipp, ip, ip_ll;
|
ip_addr *ipp, ip, ip_ll;
|
||||||
ea_list *ea;
|
ea_list *ea;
|
||||||
|
@ -856,6 +867,12 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
|
||||||
conn->peer_enhanced_refresh_support = 1;
|
conn->peer_enhanced_refresh_support = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 230: /* Extended message length capability, draft, cap number TBD */
|
||||||
|
if (cl != 0)
|
||||||
|
goto err;
|
||||||
|
conn->peer_ext_messages_support = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
/* We can safely ignore all other capabilities */
|
/* We can safely ignore all other capabilities */
|
||||||
}
|
}
|
||||||
len -= 2 + cl;
|
len -= 2 + cl;
|
||||||
|
@ -1019,6 +1036,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
||||||
p->add_path_rx = (p->cf->add_path & ADD_PATH_RX) && (conn->peer_add_path & ADD_PATH_TX);
|
p->add_path_rx = (p->cf->add_path & ADD_PATH_RX) && (conn->peer_add_path & ADD_PATH_TX);
|
||||||
p->add_path_tx = (p->cf->add_path & ADD_PATH_TX) && (conn->peer_add_path & ADD_PATH_RX);
|
p->add_path_tx = (p->cf->add_path & ADD_PATH_TX) && (conn->peer_add_path & ADD_PATH_RX);
|
||||||
p->gr_ready = p->cf->gr_mode && conn->peer_gr_able;
|
p->gr_ready = p->cf->gr_mode && conn->peer_gr_able;
|
||||||
|
p->ext_messages = p->cf->enable_extended_messages && conn->peer_ext_messages_support;
|
||||||
|
|
||||||
if (p->add_path_tx)
|
if (p->add_path_tx)
|
||||||
p->p.accept_ra_types = RA_ANY;
|
p->p.accept_ra_types = RA_ANY;
|
||||||
|
@ -1418,7 +1436,7 @@ static struct {
|
||||||
{ 2, 4, "Unsupported optional parameter" },
|
{ 2, 4, "Unsupported optional parameter" },
|
||||||
{ 2, 5, "Authentication failure" },
|
{ 2, 5, "Authentication failure" },
|
||||||
{ 2, 6, "Unacceptable hold time" },
|
{ 2, 6, "Unacceptable hold time" },
|
||||||
{ 2, 7, "Required capability missing" }, /* [RFC3392] */
|
{ 2, 7, "Required capability missing" }, /* [RFC5492] */
|
||||||
{ 2, 8, "No supported AFI/SAFI" }, /* This error msg is nonstandard */
|
{ 2, 8, "No supported AFI/SAFI" }, /* This error msg is nonstandard */
|
||||||
{ 3, 0, "Invalid UPDATE message" },
|
{ 3, 0, "Invalid UPDATE message" },
|
||||||
{ 3, 1, "Malformed attribute list" },
|
{ 3, 1, "Malformed attribute list" },
|
||||||
|
@ -1666,6 +1684,7 @@ int
|
||||||
bgp_rx(sock *sk, int size)
|
bgp_rx(sock *sk, int size)
|
||||||
{
|
{
|
||||||
struct bgp_conn *conn = sk->data;
|
struct bgp_conn *conn = sk->data;
|
||||||
|
struct bgp_proto *p = conn->bgp;
|
||||||
byte *pkt_start = sk->rbuf;
|
byte *pkt_start = sk->rbuf;
|
||||||
byte *end = pkt_start + size;
|
byte *end = pkt_start + size;
|
||||||
unsigned i, len;
|
unsigned i, len;
|
||||||
|
@ -1682,7 +1701,7 @@ bgp_rx(sock *sk, int size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = get_u16(pkt_start+16);
|
len = get_u16(pkt_start+16);
|
||||||
if (len < BGP_HEADER_LENGTH || len > BGP_MAX_PACKET_LENGTH)
|
if (len < BGP_HEADER_LENGTH || len > bgp_max_packet_length(p))
|
||||||
{
|
{
|
||||||
bgp_error(conn, 1, 2, pkt_start+16, 2);
|
bgp_error(conn, 1, 2, pkt_start+16, 2);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue