1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Implements BGP route refresh.

This commit is contained in:
Ondrej Zajicek
2009-11-26 20:47:59 +01:00
parent 5e6f568115
commit bf47fe4b2e
9 changed files with 187 additions and 10 deletions

View File

@@ -676,6 +676,17 @@ bgp_neigh_notify(neighbor *n)
}
}
static int
bgp_reload_routes(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
if (!p->conn || !p->conn->peer_refresh_support)
return 0;
bgp_schedule_packet(p->conn, PKT_ROUTE_REFRESH);
return 1;
}
static void
bgp_start_locked(struct object_lock *lock)
{
@@ -792,6 +803,7 @@ bgp_init(struct proto_config *C)
P->rte_better = bgp_rte_better;
P->import_control = bgp_import_control;
P->neigh_notify = bgp_neigh_notify;
P->reload_routes = bgp_reload_routes;
p->cf = c;
p->local_as = c->local_as;
p->remote_as = c->remote_as;

View File

@@ -29,6 +29,7 @@ struct bgp_config {
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
u32 default_med; /* Default value for MULTI_EXIT_DISC attribute */
int capabilities; /* Enable capability handshake [RFC3392] */
int enable_refresh; /* Enable local support for route refresh [RFC2918] */
int enable_as4; /* Enable local support for 4B AS numbers [RFC4893] */
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
int rr_client; /* Whether neighbor is RR client of me */
@@ -66,6 +67,7 @@ struct bgp_conn {
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] */
int peer_refresh_support; /* Peer supports route refresh [RFC2918] */
unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */
};
@@ -202,6 +204,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define PKT_UPDATE 0x02
#define PKT_NOTIFICATION 0x03
#define PKT_KEEPALIVE 0x04
#define PKT_ROUTE_REFRESH 0x05
#define PKT_SCHEDULE_CLOSE 0x1f /* Used internally to schedule socket close */
/* Attributes */

View File

@@ -23,7 +23,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
DROP, IGNORE)
DROP, IGNORE, ROUTE, REFRESH)
CF_GRAMMAR
@@ -40,6 +40,7 @@ bgp_proto_start: proto_start BGP {
BGP_CFG->error_amnesia_time = 300;
BGP_CFG->error_delay_time_min = 60;
BGP_CFG->error_delay_time_max = 300;
BGP_CFG->enable_refresh = 1;
BGP_CFG->enable_as4 = bgp_as4_support;
BGP_CFG->capabilities = 2;
BGP_CFG->advertise_ipv4 = 1;
@@ -77,6 +78,7 @@ bgp_proto:
| bgp_proto ERROR FORGET TIME expr ';' { BGP_CFG->error_amnesia_time = $5; }
| bgp_proto ERROR WAIT TIME expr ',' expr ';' { BGP_CFG->error_delay_time_min = $5; BGP_CFG->error_delay_time_max = $7; }
| 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 AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }

View File

@@ -63,6 +63,14 @@ bgp_put_cap_ipv4(struct bgp_conn *conn UNUSED, byte *buf)
}
#endif
static byte *
bgp_put_cap_rr(struct bgp_conn *conn UNUSED, byte *buf)
{
*buf++ = 2; /* Capability 2: Support for route refresh */
*buf++ = 0; /* Capability data length */
return buf;
}
static byte *
bgp_put_cap_as4(struct bgp_conn *conn, byte *buf)
{
@@ -105,6 +113,9 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
cap = bgp_put_cap_ipv6(conn, cap);
#endif
if (p->cf->enable_refresh)
cap = bgp_put_cap_rr(conn, cap);
if (conn->want_as4_support)
cap = bgp_put_cap_as4(conn, cap);
@@ -386,6 +397,24 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
#endif
static byte *
bgp_create_route_refresh(struct bgp_conn *conn, byte *buf)
{
struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH");
#ifdef IPV6
*buf++ = 0; /* AFI IPv6 */
*buf++ = BGP_AF_IPV6;
#else
*buf++ = 0; /* AFI IPv4 */
*buf++ = BGP_AF_IPV4;
#endif
*buf++ = 0; /* RFU */
*buf++ = 1; /* and SAFI 1 */
return buf;
}
static void
bgp_create_header(byte *buf, unsigned int len, unsigned int type)
{
@@ -447,6 +476,12 @@ bgp_fire_tx(struct bgp_conn *conn)
type = PKT_OPEN;
end = bgp_create_open(conn, pkt);
}
else if (s & (1 << PKT_ROUTE_REFRESH))
{
s &= ~(1 << PKT_ROUTE_REFRESH);
type = PKT_ROUTE_REFRESH;
end = bgp_create_route_refresh(conn, pkt);
}
else if (s & (1 << PKT_UPDATE))
{
end = bgp_create_update(conn, pkt);
@@ -517,6 +552,11 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
switch (opt[0])
{
case 2:
if (cl != 0)
goto err;
conn->peer_refresh_support = 1;
break;
case 65:
if (cl != 4)
goto err;
@@ -1084,6 +1124,30 @@ bgp_rx_keepalive(struct bgp_conn *conn)
}
}
static void
bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
{
struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_PACKETS, "Got ROUTE-REFRESH");
if (conn->state != BS_ESTABLISHED)
{ bgp_error(conn, 5, 0, NULL, 0); return; }
if (!p->cf->enable_refresh)
{ bgp_error(conn, 1, 3, pkt+18, 1); return; }
if (len != (BGP_HEADER_LENGTH + 4))
{ bgp_error(conn, 1, 2, pkt+16, 2); return; }
/* FIXME - we ignore AFI/SAFI values, as we support
just one value and even an error code for an invalid
request is not defined */
proto_request_feeding(&p->p);
}
/**
* bgp_rx_packet - handle a received packet
* @conn: BGP connection
@@ -1103,6 +1167,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);
case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
case PKT_ROUTE_REFRESH: return bgp_rx_route_refresh(conn, pkt, len);
default: bgp_error(conn, 1, 3, pkt+18, 1);
}
}