summaryrefslogtreecommitdiffstats
path: root/proto/bgp
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
commitbf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5 (patch)
tree59108f1bdc8f5192a27e9a40d72a7e950686dd8c /proto/bgp
parent5e6f568115511e2bcf43c60dfdcbd7a35cb04b93 (diff)
downloadbird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.tar
bird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.zip
Implements BGP route refresh.
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/bgp.c12
-rw-r--r--proto/bgp/bgp.h3
-rw-r--r--proto/bgp/config.Y4
-rw-r--r--proto/bgp/packets.c65
4 files changed, 83 insertions, 1 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index cde0276..24cd202 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -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;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c4d0335..59ec9c1 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -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 */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 3576946..3c73d60 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -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; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 4176c9f..91b4792 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -64,6 +64,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)
{
*buf++ = 65; /* Capability 65: Support for 4-octet AS number */
@@ -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);
}
}