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:
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user