summaryrefslogtreecommitdiff
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c884
1 files changed, 679 insertions, 205 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 9469a0778f..5d7441ed6d 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -48,6 +48,7 @@
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_keepalives.h"
#include "bgpd/bgp_flowspec.h"
+#include "bgpd/bgp_linkstate_tlv.h"
#include "bgpd/bgp_trace.h"
DEFINE_HOOK(bgp_packet_dump,
@@ -105,21 +106,22 @@ void bgp_packet_set_size(struct stream *s)
* Push a packet onto the beginning of the peer's output queue.
* This function acquires the peer's write mutex before proceeding.
*/
-static void bgp_packet_add(struct peer *peer, struct stream *s)
+static void bgp_packet_add(struct peer_connection *connection,
+ struct peer *peer, struct stream *s)
{
intmax_t delta;
uint32_t holdtime;
intmax_t sendholdtime;
- frr_with_mutex (&peer->io_mtx) {
+ frr_with_mutex (&connection->io_mtx) {
/* if the queue is empty, reset the "last OK" timestamp to
* now, otherwise if we write another packet immediately
* after it'll get confused
*/
- if (!stream_fifo_count_safe(peer->obuf))
+ if (!stream_fifo_count_safe(connection->obuf))
peer->last_sendq_ok = monotime(NULL);
- stream_fifo_push(peer->obuf, s);
+ stream_fifo_push(connection->obuf, s);
delta = monotime(NULL) - peer->last_sendq_ok;
@@ -146,7 +148,7 @@ static void bgp_packet_add(struct peer *peer, struct stream *s)
EC_BGP_SENDQ_STUCK_PROPER,
"%pBP has not made any SendQ progress for 2 holdtimes (%jds), terminating session",
peer, sendholdtime);
- BGP_EVENT_ADD(peer, TCP_fatal_error);
+ BGP_EVENT_ADD(connection, TCP_fatal_error);
} else if (delta > (intmax_t)holdtime &&
monotime(NULL) - peer->last_sendq_warn > 5) {
flog_warn(
@@ -260,7 +262,7 @@ void bgp_update_restarted_peers(struct peer *peer)
if (bgp_debug_neighbor_events(peer))
zlog_debug("Peer %s: Checking restarted", peer->host);
- if (peer_established(peer)) {
+ if (peer_established(peer->connection)) {
peer->update_delay_over = 1;
peer->bgp->restarted_peers++;
bgp_check_update_delay(peer->bgp);
@@ -283,7 +285,7 @@ void bgp_update_implicit_eors(struct peer *peer)
if (bgp_debug_neighbor_events(peer))
zlog_debug("Peer %s: Checking implicit EORs", peer->host);
- if (peer_established(peer)) {
+ if (peer_established(peer->connection)) {
peer->update_delay_over = 1;
peer->bgp->implicit_eors++;
bgp_check_update_delay(peer->bgp);
@@ -348,7 +350,11 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw);
case SAFI_FLOWSPEC:
return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw);
+ case SAFI_LINKSTATE:
+ return bgp_nlri_parse_linkstate(peer, attr, packet,
+ mp_withdraw);
}
+
return BGP_NLRI_PARSE_ERROR;
}
@@ -391,6 +397,7 @@ static void bgp_write_proceed_actions(struct peer *peer)
struct bpacket *next_pkt;
struct update_subgroup *subgrp;
enum bgp_af_index index;
+ struct peer_connection *connection = peer->connection;
for (index = BGP_AF_START; index < BGP_AF_MAX; index++) {
paf = peer->peer_af_array[index];
@@ -403,7 +410,7 @@ static void bgp_write_proceed_actions(struct peer *peer)
next_pkt = paf->next_pkt_to_send;
if (next_pkt && next_pkt->buffer) {
- BGP_TIMER_ON(peer->t_generate_updgrp_packets,
+ BGP_TIMER_ON(connection->t_generate_updgrp_packets,
bgp_generate_updgrp_packets, 0);
return;
}
@@ -414,7 +421,7 @@ static void bgp_write_proceed_actions(struct peer *peer)
if (bpacket_queue_is_full(SUBGRP_INST(subgrp),
SUBGRP_PKTQ(subgrp))
|| subgroup_packets_to_build(subgrp)) {
- BGP_TIMER_ON(peer->t_generate_updgrp_packets,
+ BGP_TIMER_ON(connection->t_generate_updgrp_packets,
bgp_generate_updgrp_packets, 0);
return;
}
@@ -429,7 +436,7 @@ static void bgp_write_proceed_actions(struct peer *peer)
&& !CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND)
&& safi != SAFI_MPLS_VPN) {
- BGP_TIMER_ON(peer->t_generate_updgrp_packets,
+ BGP_TIMER_ON(connection->t_generate_updgrp_packets,
bgp_generate_updgrp_packets, 0);
return;
}
@@ -444,8 +451,8 @@ static void bgp_write_proceed_actions(struct peer *peer)
*/
void bgp_generate_updgrp_packets(struct event *thread)
{
- struct peer *peer = EVENT_ARG(thread);
-
+ struct peer_connection *connection = EVENT_ARG(thread);
+ struct peer *peer = connection->peer;
struct stream *s;
struct peer_af *paf;
struct bpacket *next_pkt;
@@ -462,14 +469,14 @@ void bgp_generate_updgrp_packets(struct event *thread)
* if peer is Established and updates are not on hold (as part of
* update-delay processing).
*/
- if (!peer_established(peer))
+ if (!peer_established(peer->connection))
return;
if ((peer->bgp->main_peers_update_hold)
|| bgp_update_delay_active(peer->bgp))
return;
- if (peer->t_routeadv)
+ if (peer->connection->t_routeadv)
return;
/*
@@ -477,7 +484,7 @@ void bgp_generate_updgrp_packets(struct event *thread)
* let's stop adding to the outq if we are
* already at the limit.
*/
- if (peer->obuf->count >= bm->outq_limit) {
+ if (connection->obuf->count >= bm->outq_limit) {
bgp_write_proceed_actions(peer);
return;
}
@@ -601,14 +608,14 @@ void bgp_generate_updgrp_packets(struct event *thread)
* packet with appropriate attributes from peer
* and advance peer */
s = bpacket_reformat_for_peer(next_pkt, paf);
- bgp_packet_add(peer, s);
+ bgp_packet_add(connection, peer, s);
bpacket_queue_advance_peer(paf);
}
} while (s && (++generated < wpq) &&
- (peer->obuf->count <= bm->outq_limit));
+ (connection->obuf->count <= bm->outq_limit));
if (generated)
- bgp_writes_on(peer);
+ bgp_writes_on(connection);
bgp_write_proceed_actions(peer);
}
@@ -635,20 +642,21 @@ void bgp_keepalive_send(struct peer *peer)
zlog_debug("%s sending KEEPALIVE", peer->host);
/* Add packet to the peer. */
- bgp_packet_add(peer, s);
+ bgp_packet_add(peer->connection, peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/*
* Creates a BGP Open packet and appends it to the peer's output queue.
* Sets capabilities as necessary.
*/
-void bgp_open_send(struct peer *peer)
+void bgp_open_send(struct peer_connection *connection)
{
struct stream *s;
uint16_t send_holdtime;
as_t local_as;
+ struct peer *peer = connection->peer;
if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
send_holdtime = peer->holdtime;
@@ -704,31 +712,32 @@ void bgp_open_send(struct peer *peer)
hook_call(bgp_packet_send, peer, BGP_MSG_OPEN, stream_get_endp(s), s);
/* Add packet to the peer. */
- bgp_packet_add(peer, s);
+ bgp_packet_add(connection, peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(connection);
}
/*
* Writes NOTIFICATION message directly to a peer socket without waiting for
* the I/O thread.
*
- * There must be exactly one stream on the peer->obuf FIFO, and the data within
- * this stream must match the format of a BGP NOTIFICATION message.
+ * There must be exactly one stream on the peer->connection->obuf FIFO, and the
+ * data within this stream must match the format of a BGP NOTIFICATION message.
* Transmission is best-effort.
*
- * @requires peer->io_mtx
+ * @requires peer->connection->io_mtx
* @param peer
* @return 0
*/
-static void bgp_write_notify(struct peer *peer)
+static void bgp_write_notify(struct peer_connection *connection,
+ struct peer *peer)
{
int ret, val;
uint8_t type;
struct stream *s;
/* There should be at least one packet. */
- s = stream_fifo_pop(peer->obuf);
+ s = stream_fifo_pop(connection->obuf);
if (!s)
return;
@@ -739,7 +748,7 @@ static void bgp_write_notify(struct peer *peer)
* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
* we only care about getting a clean shutdown at this point.
*/
- ret = write(peer->fd, STREAM_DATA(s), stream_get_endp(s));
+ ret = write(connection->fd, STREAM_DATA(s), stream_get_endp(s));
/*
* only connection reset/close gets counted as TCP_fatal_error, failure
@@ -747,13 +756,13 @@ static void bgp_write_notify(struct peer *peer)
*/
if (ret <= 0) {
stream_free(s);
- BGP_EVENT_ADD(peer, TCP_fatal_error);
+ BGP_EVENT_ADD(connection, TCP_fatal_error);
return;
}
/* Disable Nagle, make NOTIFY packet go out right away */
val = 1;
- (void)setsockopt(peer->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val,
+ (void)setsockopt(connection->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val,
sizeof(val));
/* Retrieve BGP packet type. */
@@ -776,7 +785,7 @@ static void bgp_write_notify(struct peer *peer)
* Handle Graceful Restart case where the state changes to
* Connect instead of Idle
*/
- BGP_EVENT_ADD(peer, BGP_Stop);
+ BGP_EVENT_ADD(connection, BGP_Stop);
stream_free(s);
}
@@ -902,15 +911,17 @@ bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,
* @param data Data portion
* @param datalen length of data portion
*/
-static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
- uint8_t sub_code, uint8_t *data,
- size_t datalen, bool use_curr)
+static void bgp_notify_send_internal(struct peer_connection *connection,
+ uint8_t code, uint8_t sub_code,
+ uint8_t *data, size_t datalen,
+ bool use_curr)
{
struct stream *s;
+ struct peer *peer = connection->peer;
bool hard_reset = bgp_notify_send_hard_reset(peer, code, sub_code);
/* Lock I/O mutex to prevent other threads from pushing packets */
- frr_mutex_lock_autounlock(&peer->io_mtx);
+ frr_mutex_lock_autounlock(&connection->io_mtx);
/* ============================================== */
/* Allocate new stream. */
@@ -943,7 +954,7 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
bgp_packet_set_size(s);
/* wipe output buffer */
- stream_fifo_clean(peer->obuf);
+ stream_fifo_clean(connection->obuf);
/*
* If possible, store last packet for debugging purposes. This check is
@@ -956,8 +967,9 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
if (use_curr && peer->curr) {
size_t packetsize = stream_get_endp(peer->curr);
assert(packetsize <= peer->max_packet_size);
- memcpy(peer->last_reset_cause, peer->curr->data, packetsize);
- peer->last_reset_cause_size = packetsize;
+ if (peer->last_reset_cause)
+ stream_free(peer->last_reset_cause);
+ peer->last_reset_cause = stream_dup(peer->curr);
}
/* For debug */
@@ -1027,13 +1039,13 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
/* Add packet to peer's output queue */
- stream_fifo_push(peer->obuf, s);
+ stream_fifo_push(connection->obuf, s);
bgp_peer_gr_flags_update(peer);
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
peer->bgp->peer);
- bgp_write_notify(peer);
+ bgp_write_notify(connection, peer);
}
/*
@@ -1046,18 +1058,20 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
* @param code BGP error code
* @param sub_code BGP error subcode
*/
-void bgp_notify_send(struct peer *peer, uint8_t code, uint8_t sub_code)
+void bgp_notify_send(struct peer_connection *connection, uint8_t code,
+ uint8_t sub_code)
{
- bgp_notify_send_internal(peer, code, sub_code, NULL, 0, true);
+ bgp_notify_send_internal(connection, code, sub_code, NULL, 0, true);
}
/*
* Enqueue notification; called from the main pthread, peer object access is ok.
*/
-void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
+void bgp_notify_send_with_data(struct peer_connection *connection, uint8_t code,
uint8_t sub_code, uint8_t *data, size_t datalen)
{
- bgp_notify_send_internal(peer, code, sub_code, data, datalen, true);
+ bgp_notify_send_internal(connection, code, sub_code, data, datalen,
+ true);
}
/*
@@ -1068,7 +1082,8 @@ void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code,
uint8_t *data, size_t datalen)
{
/* Avoid touching the peer object */
- bgp_notify_send_internal(peer, code, sub_code, data, datalen, false);
+ bgp_notify_send_internal(peer->connection, code, sub_code, data,
+ datalen, false);
}
/*
@@ -1080,6 +1095,7 @@ void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code,
* @param orf_type Outbound Route Filtering type
* @param when_to_refresh Whether to refresh immediately or defer
* @param remove Whether to remove ORF for specified AFI/SAFI
+ * @param subtype BGP enhanced route refresh optional subtypes
*/
void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
uint8_t orf_type, uint8_t when_to_refresh,
@@ -1102,7 +1118,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
- if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+ if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_RCV))
bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_NEW);
else
bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_OLD);
@@ -1115,7 +1131,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
stream_putc(s, 0);
stream_putc(s, pkt_safi);
- if (orf_type == ORF_TYPE_PREFIX || orf_type == ORF_TYPE_PREFIX_OLD)
+ if (orf_type == ORF_TYPE_PREFIX)
if (remove || filter->plist[FILTER_IN].plist) {
uint16_t orf_len;
unsigned long orfp;
@@ -1177,9 +1193,9 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
}
/* Add packet to the peer. */
- bgp_packet_add(peer, s);
+ bgp_packet_add(peer->connection, peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/*
@@ -1197,6 +1213,18 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
struct stream *s;
iana_afi_t pkt_afi = IANA_AFI_IPV4;
iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
+ unsigned long cap_len;
+ uint16_t len;
+ uint32_t gr_restart_time;
+ const char *capability = lookup_msg(capcode_str, capability_code,
+ "Unknown");
+
+ if (!peer_established(peer->connection))
+ return;
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
+ !CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
+ return;
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -1207,7 +1235,41 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
bgp_packet_set_marker(s, BGP_MSG_CAPABILITY);
/* Encode MP_EXT capability. */
- if (capability_code == CAPABILITY_CODE_MP) {
+ switch (capability_code) {
+ case CAPABILITY_CODE_SOFT_VERSION:
+ SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_SOFT_VERSION);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0); /* Capability Length */
+
+ /* The Capability Length SHOULD be no greater than 64.
+ * This is the limit to allow other capabilities as much
+ * space as they require.
+ */
+ const char *soft_version = cmd_software_version_get();
+
+ len = strlen(soft_version);
+ if (len > BGP_MAX_SOFT_VERSION)
+ len = BGP_MAX_SOFT_VERSION;
+
+ stream_putc(s, len);
+ stream_put(s, soft_version, len);
+
+ /* Software Version capability Len. */
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_MP:
stream_putc(s, action);
stream_putc(s, CAPABILITY_CODE_MP);
stream_putc(s, CAPABILITY_CODE_MP_LEN);
@@ -1216,27 +1278,145 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
stream_putc(s, pkt_safi);
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%pBP sending CAPABILITY has %s MP_EXT CAP for afi/safi: %s/%s",
- peer,
- action == CAPABILITY_ACTION_SET ? "Advertising"
- : "Removing",
- iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_RESTART:
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) &&
+ !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER))
+ return;
+
+ SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_RESTART);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0);
+ gr_restart_time = peer->bgp->restart_time;
+
+ if (peer->bgp->t_startup) {
+ SET_FLAG(gr_restart_time, GRACEFUL_RESTART_R_BIT);
+ SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
+ }
+
+ if (CHECK_FLAG(peer->bgp->flags,
+ BGP_FLAG_GRACEFUL_NOTIFICATION)) {
+ SET_FLAG(gr_restart_time, GRACEFUL_RESTART_N_BIT);
+ SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV);
+ }
+
+ stream_putw(s, gr_restart_time);
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)) {
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
+ &pkt_safi);
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+ if (CHECK_FLAG(peer->bgp->flags,
+ BGP_FLAG_GR_PRESERVE_FWD))
+ stream_putc(s, GRACEFUL_RESTART_F_BIT);
+ else
+ stream_putc(s, 0);
+ }
+ }
+
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+
+ break;
+ case CAPABILITY_CODE_LLGR:
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
+ return;
+
+ SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
+
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_LLGR);
+ cap_len = stream_get_endp(s);
+ stream_putc(s, 0);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
+ &pkt_safi);
+
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+ stream_putc(s, LLGR_F_BIT);
+ stream_put3(s, peer->bgp->llgr_stale_time);
+
+ SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_ADV);
+ }
+
+ len = stream_get_endp(s) - cap_len - 1;
+ stream_putc_at(s, cap_len, len);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ break;
+ case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ORF:
+ case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_DYNAMIC:
+ case CAPABILITY_CODE_ADDPATH:
+ case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_FQDN:
+ case CAPABILITY_CODE_ENHE:
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ break;
+ case CAPABILITY_CODE_ROLE:
+ if (peer->local_role != ROLE_UNDEFINED) {
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV);
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_ROLE);
+ stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
+ stream_putc(s, peer->local_role);
+ }
+ break;
+ default:
+ break;
}
/* Set packet size. */
bgp_packet_set_size(s);
/* Add packet to the peer. */
- bgp_packet_add(peer, s);
+ bgp_packet_add(peer->connection, peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/* RFC1771 6.8 Connection collision detection. */
-static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
+static int bgp_collision_detect(struct peer_connection *connection,
+ struct peer *new, struct in_addr remote_id)
{
struct peer *peer;
+ struct peer_connection *other;
/*
* Upon receipt of an OPEN message, the local system must examine
@@ -1252,18 +1432,22 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
if (peer == NULL)
return 0;
+ other = peer->connection;
+
/*
* Do not accept the new connection in Established or Clearing
* states. Note that a peer GR is handled by closing the existing
* connection upon receipt of new one.
*/
- if (peer_established(peer) || peer->status == Clearing) {
- bgp_notify_send(new, BGP_NOTIFY_CEASE,
+ if (peer_established(other) ||
+ other->status == Clearing) {
+ bgp_notify_send(connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return -1;
}
- if ((peer->status != OpenConfirm) && (peer->status != OpenSent))
+ if ((other->status != OpenConfirm) &&
+ (other->status != OpenSent))
return 0;
/*
@@ -1290,11 +1474,11 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
* and accepts BGP connection initiated by
* the remote system.
*/
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ bgp_notify_send(other, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return 1;
} else {
- bgp_notify_send(new, BGP_NOTIFY_CEASE,
+ bgp_notify_send(connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return -1;
}
@@ -1313,11 +1497,11 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
* OpenConfirm state).
*/
if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ bgp_notify_send(other, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return 1;
} else {
- bgp_notify_send(new, BGP_NOTIFY_CEASE,
+ bgp_notify_send(connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return -1;
}
@@ -1344,7 +1528,7 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
* Side effects
* ------------
* - May send NOTIFY messages
- * - May not modify peer->status
+ * - May not modify peer->connection->status
* - May not call bgp_event_update()
*/
@@ -1360,7 +1544,8 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
* @param size size of the packet
* @return as in summary
*/
-static int bgp_open_receive(struct peer *peer, bgp_size_t size)
+static int bgp_open_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
int ret;
uint8_t version;
@@ -1399,7 +1584,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
EC_BGP_PKT_OPEN,
"%s: stream does not have enough bytes for extended optional parameters",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return BGP_Stop;
}
@@ -1411,7 +1596,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
EC_BGP_PKT_OPEN,
"%s: stream does not have enough bytes to read the extended optional parameters optlen",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return BGP_Stop;
}
@@ -1438,7 +1623,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_PKT_OPEN,
"%s: stream has not enough bytes (%u)",
peer->host, optlen);
- bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return BGP_Stop;
}
@@ -1460,7 +1645,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_PKT_OPEN,
"%s bad OPEN, got AS4 capability, but AS4 set to 0",
peer->host);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as4, 4);
return BGP_Stop;
@@ -1470,7 +1655,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
if (remote_as == BGP_AS_ZERO) {
flog_err(EC_BGP_PKT_OPEN, "%s bad OPEN, got AS set to 0",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS);
return BGP_Stop;
}
@@ -1485,7 +1670,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
EC_BGP_PKT_OPEN,
"%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
peer->host);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as4, 4);
return BGP_Stop;
@@ -1513,7 +1699,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
EC_BGP_PKT_OPEN,
"%s bad OPEN, got AS4 capability, but remote_as %u mismatch with 16bit 'myasn' %u in open",
peer->host, as4, remote_as);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as4, 4);
return BGP_Stop;
@@ -1533,7 +1720,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s bad OPEN, wrong router identifier %pI4",
peer->host, &remote_id);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
notify_data_remote_id, 4);
return BGP_Stop;
@@ -1548,7 +1735,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
"%s bad protocol version, remote requested %d, local request %d",
peer->host, version, BGP_VERSION_4);
/* Data must be in network byte order here */
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_VERSION,
(uint8_t *)&maxver, 2);
return BGP_Stop;
@@ -1560,7 +1747,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
zlog_debug(
"%s bad OPEN, remote AS is unspecified currently",
peer->host);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return BGP_Stop;
@@ -1570,7 +1757,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
zlog_debug(
"%s bad OPEN, remote AS is %u, internal specified",
peer->host, remote_as);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return BGP_Stop;
@@ -1582,7 +1770,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
zlog_debug(
"%s bad OPEN, remote AS is %u, external specified",
peer->host, remote_as);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return BGP_Stop;
@@ -1592,7 +1781,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s bad OPEN, remote AS is %u, expected %u",
peer->host, remote_as, peer->as);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return BGP_Stop;
@@ -1602,7 +1791,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
* When collision is detected and this peer is closed.
* Return immediately.
*/
- ret = bgp_collision_detect(peer, remote_id);
+ ret = bgp_collision_detect(connection, peer, remote_id);
if (ret < 0)
return BGP_Stop;
@@ -1625,7 +1814,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
*/
if (holdtime < 3 && holdtime != 0) {
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
(uint8_t *)holdtime_ptr, 2);
return BGP_Stop;
@@ -1635,7 +1824,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
* is smaller than configured minimum Hold Time. */
if (holdtime < peer->bgp->default_min_holdtime
&& peer->bgp->default_min_holdtime != 0) {
- bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
(uint8_t *)holdtime_ptr, 2);
return BGP_Stop;
@@ -1712,6 +1901,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
peer->afc[AFI_L2VPN][SAFI_EVPN];
peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] =
peer->afc[AFI_IP6][SAFI_FLOWSPEC];
+ peer->afc_nego[AFI_LINKSTATE][SAFI_LINKSTATE] =
+ peer->afc[AFI_LINKSTATE][SAFI_LINKSTATE];
}
/* Verify valid local address present based on negotiated
@@ -1733,14 +1924,17 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
|| peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
|| peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
- if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) {
-#if defined(HAVE_CUMULUS)
- zlog_warn("%s: No local IPv6 address, BGP routing may not work",
- peer->host);
-#endif
+ if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global) &&
+ !bm->v6_with_v4_nexthops) {
+ flog_err(EC_BGP_SND_FAIL,
+"%s: No local IPv6 address, and zebra does not support V6 routing with v4 nexthops, BGP routing for V6 will not work",
+ peer->host);
+ bgp_notify_send(connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
}
}
- peer->rtt = sockopt_tcp_rtt(peer->fd);
+ peer->rtt = sockopt_tcp_rtt(connection->fd);
return Receive_OPEN_message;
}
@@ -1752,14 +1946,15 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
* @param size size of the packet
* @return as in summary
*/
-static int bgp_keepalive_receive(struct peer *peer, bgp_size_t size)
+static int bgp_keepalive_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
if (bgp_debug_keepalive(peer))
zlog_debug("%s KEEPALIVE rcvd", peer->host);
bgp_update_implicit_eors(peer);
- peer->rtt = sockopt_tcp_rtt(peer->fd);
+ peer->rtt = sockopt_tcp_rtt(connection->fd);
/* If the peer's RTT is higher than expected, shutdown
* the peer automatically.
@@ -1812,7 +2007,7 @@ static void bgp_refresh_stalepath_timer_expire(struct event *thread)
"%pBP route-refresh (BoRR) timer expired for afi/safi: %d/%d",
peer, afi, safi);
- bgp_timer_set(peer);
+ bgp_timer_set(peer->connection);
}
/**
@@ -1824,7 +2019,8 @@ static void bgp_refresh_stalepath_timer_expire(struct event *thread)
* @param size size of the packet
* @return as in summary
*/
-static int bgp_update_receive(struct peer *peer, bgp_size_t size)
+static int bgp_update_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
int ret, nlri_ret;
uint8_t *end;
@@ -1845,13 +2041,14 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
struct bgp_nlri nlris[NLRI_TYPE_MAX];
/* Status must be Established. */
- if (!peer_established(peer)) {
+ if (!peer_established(connection)) {
flog_err(EC_BGP_INVALID_STATUS,
"%s [FSM] Update packet received under status %s",
peer->host,
- lookup_msg(bgp_status_msg, peer->status, NULL));
- bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
+ bgp_notify_send(connection, BGP_NOTIFY_FSM_ERR,
+ bgp_fsm_error_subcode(peer->connection->status));
return BGP_Stop;
}
@@ -1874,7 +2071,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (packet length is short for unfeasible length)",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
return BGP_Stop;
}
@@ -1887,7 +2084,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] Update packet error (packet unfeasible length overflow %d)",
peer->host, withdraw_len);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
return BGP_Stop;
}
@@ -1907,7 +2104,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
EC_BGP_UPDATE_PACKET_SHORT,
"%s [Error] Packet Error (update packet is short for attribute length)",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ bgp_notify_send(peer->connection, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
return BGP_Stop;
}
@@ -1921,7 +2118,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
EC_BGP_UPDATE_PACKET_LONG,
"%s [Error] Packet Error (update packet attribute length overflow %d)",
peer->host, attribute_len);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_ATTR);
return BGP_Stop;
}
@@ -1975,7 +2172,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
/* Network Layer Reachability Information. */
update_len = end - stream_pnt(s);
- if (update_len) {
+ if (update_len && attribute_len) {
/* Set NLRI portion to structure. */
nlris[NLRI_UPDATE].afi = AFI_IP;
nlris[NLRI_UPDATE].safi = SAFI_UNICAST;
@@ -2036,12 +2233,12 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
&& nlri_ret != BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW) {
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] Error parsing NLRI", peer->host);
- if (peer_established(peer))
- bgp_notify_send(
- peer, BGP_NOTIFY_UPDATE_ERR,
- i <= NLRI_WITHDRAW
- ? BGP_NOTIFY_UPDATE_INVAL_NETWORK
- : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
+ if (peer_established(connection))
+ bgp_notify_send(connection,
+ BGP_NOTIFY_UPDATE_ERR,
+ i <= NLRI_WITHDRAW
+ ? BGP_NOTIFY_UPDATE_INVAL_NETWORK
+ : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
bgp_attr_unintern_sub(&attr);
return BGP_Stop;
}
@@ -2149,7 +2346,8 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
* @param size size of the packet
* @return as in summary
*/
-static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
+static int bgp_notify_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
struct bgp_notify outer = {};
struct bgp_notify inner = {};
@@ -2270,7 +2468,8 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
* @param size size of the packet
* @return as in summary
*/
-static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
+static int bgp_route_refresh_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
iana_afi_t pkt_afi;
afi_t afi;
@@ -2290,20 +2489,20 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_NO_CAP,
"%s [Error] BGP route refresh is not enabled",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESTYPE);
return BGP_Stop;
}
/* Status must be Established. */
- if (!peer_established(peer)) {
- flog_err(
- EC_BGP_INVALID_STATUS,
- "%s [Error] Route refresh packet received under status %s",
- peer->host,
- lookup_msg(bgp_status_msg, peer->status, NULL));
- bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ if (!peer_established(connection)) {
+ flog_err(EC_BGP_INVALID_STATUS,
+ "%s [Error] Route refresh packet received under status %s",
+ peer->host,
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
+ bgp_notify_send(connection, BGP_NOTIFY_FSM_ERR,
+ bgp_fsm_error_subcode(peer->connection->status));
return BGP_Stop;
}
@@ -2341,9 +2540,9 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
zlog_err(
"%s Enhanced Route Refresh message length error",
peer->host);
- bgp_notify_send(
- peer, BGP_NOTIFY_ROUTE_REFRESH_ERR,
- BGP_NOTIFY_ROUTE_REFRESH_INVALID_MSG_LEN);
+ bgp_notify_send(connection,
+ BGP_NOTIFY_ROUTE_REFRESH_ERR,
+ BGP_NOTIFY_ROUTE_REFRESH_INVALID_MSG_LEN);
}
/* When the BGP speaker receives a ROUTE-REFRESH message
@@ -2359,7 +2558,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
if (msg_length < 5) {
zlog_info("%s ORF route refresh length error",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ bgp_notify_send(connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return BGP_Stop;
}
@@ -2374,8 +2573,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
/* orf_len in bounds? */
if ((stream_pnt(s) + orf_len) > end)
break; /* XXX: Notify instead?? */
- if (orf_type == ORF_TYPE_PREFIX
- || orf_type == ORF_TYPE_PREFIX_OLD) {
+ if (orf_type == ORF_TYPE_PREFIX) {
uint8_t *p_pnt = stream_pnt(s);
uint8_t *p_end = stream_pnt(s) + orf_len;
struct orf_prefix orfp;
@@ -2400,7 +2598,8 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
* and 7 bytes of ORF Address-filter entry from
* the stream
*/
- if (*p_pnt & ORF_COMMON_PART_REMOVE_ALL) {
+ if (p_pnt < p_end &&
+ *p_pnt & ORF_COMMON_PART_REMOVE_ALL) {
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%pBP rcvd Remove-All pfxlist ORF request",
@@ -2594,7 +2793,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
bgp_set_stale_route(peer, afi, safi);
}
- if (peer_established(peer))
+ if (peer_established(peer->connection))
event_add_timer(bm->master,
bgp_refresh_stalepath_timer_expire, paf,
peer->bgp->stalepath_time,
@@ -2679,6 +2878,226 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
return BGP_PACKET_NOOP;
}
+static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ size_t len = end - data;
+ afi_t afi;
+ safi_t safi;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ if (len < BGP_CAP_LLGR_MIN_PACKET_LEN) {
+ zlog_err("%pBP: Received invalid Long-Lived Graceful-Restart capability length %zu",
+ peer, len);
+ return;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
+
+ while (data + BGP_CAP_LLGR_MIN_PACKET_LEN <= end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi;
+ iana_safi_t pkt_safi;
+ struct graceful_restart_af graf;
+
+ memcpy(&graf, data, sizeof(graf));
+ pkt_afi = ntohs(graf.afi);
+ pkt_safi = safi_int2iana(graf.safi);
+
+ /* Stale time is after AFI/SAFI/flags.
+ * It's encoded as 24 bits (= 3 bytes), so we need to
+ * put it into 32 bits.
+ */
+ uint32_t stale_time;
+ uint8_t *stale_time_ptr = data + 4;
+
+ stale_time = stale_time_ptr[0] << 16;
+ stale_time |= stale_time_ptr[1] << 8;
+ stale_time |= stale_time_ptr[2];
+
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
+ &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Long-lived Graceful Restart capability for this AFI/SAFI",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else if (!peer->afc[afi][safi] ||
+ !CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_RCV)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Long-lived Graceful Restart capability",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) Long-lived Graceful Restart capability stale time %u sec",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi),
+ stale_time);
+
+ peer->llgr[afi][safi].flags = graf.flag;
+ peer->llgr[afi][safi].stale_time =
+ MIN(stale_time,
+ peer->bgp->llgr_stale_time);
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_LLGR_AF_RCV);
+ }
+
+ data += BGP_CAP_LLGR_MIN_PACKET_LEN;
+ }
+ } else {
+ FOREACH_AFI_SAFI (afi, safi) {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_LLGR_AF_RCV);
+
+ peer->llgr[afi][safi].flags = 0;
+ peer->llgr[afi][safi].stale_time =
+ BGP_DEFAULT_LLGR_STALE_TIME;
+ }
+
+ UNSET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
+ }
+}
+
+static void bgp_dynamic_capability_graceful_restart(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+#define GRACEFUL_RESTART_CAPABILITY_PER_AFI_SAFI_SIZE 4
+ uint16_t gr_restart_flag_time;
+ uint8_t *data = pnt + 3;
+ uint8_t *end = pnt + hdr->length;
+ size_t len = end - data;
+ afi_t afi;
+ safi_t safi;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ if (len < sizeof(gr_restart_flag_time)) {
+ zlog_err("%pBP: Received invalid Graceful-Restart capability length %d",
+ peer, hdr->length);
+ return;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
+ ptr_get_be16(data, &gr_restart_flag_time);
+ data += sizeof(gr_restart_flag_time);
+
+ if (CHECK_FLAG(gr_restart_flag_time, GRACEFUL_RESTART_R_BIT))
+ SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
+ else
+ UNSET_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
+
+ if (CHECK_FLAG(gr_restart_flag_time, GRACEFUL_RESTART_N_BIT))
+ SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+ else
+ UNSET_FLAG(peer->cap,
+ PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+
+ UNSET_FLAG(gr_restart_flag_time, 0xF000);
+ peer->v_gr_restart = gr_restart_flag_time;
+
+ while (data + GRACEFUL_RESTART_CAPABILITY_PER_AFI_SAFI_SIZE <=
+ end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi;
+ iana_safi_t pkt_safi;
+ struct graceful_restart_af graf;
+
+ memcpy(&graf, data, sizeof(graf));
+ pkt_afi = ntohs(graf.afi);
+ pkt_safi = safi_int2iana(graf.safi);
+
+ /* Convert AFI, SAFI to internal values, check. */
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
+ &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP: Addr-family %s/%s(afi/safi) not supported. Ignore the Graceful Restart capability for this AFI/SAFI",
+ peer, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else if (!peer->afc[afi][safi]) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP: Addr-family %s/%s(afi/safi) not enabled. Ignore the Graceful Restart capability",
+ peer, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP: Address family %s is%spreserved",
+ peer,
+ get_afi_safi_str(afi, safi,
+ false),
+ CHECK_FLAG(peer->af_cap[afi]
+ [safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV)
+ ? " "
+ : " not ");
+
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_RCV);
+ if (CHECK_FLAG(graf.flag,
+ GRACEFUL_RESTART_F_BIT))
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV);
+ }
+
+ data += GRACEFUL_RESTART_CAPABILITY_PER_AFI_SAFI_SIZE;
+ }
+ } else {
+ FOREACH_AFI_SAFI (afi, safi) {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_RCV);
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV);
+ }
+
+ UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
+ UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+ UNSET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
+ }
+}
+
+static void bgp_dynamic_capability_software_version(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ uint8_t len = *data;
+ char soft_version[BGP_MAX_SOFT_VERSION + 1] = {};
+
+ if (action == CAPABILITY_ACTION_SET) {
+ if (data + len > end) {
+ zlog_err("%pBP: Received invalid Software Version capability length %d",
+ peer, len);
+ return;
+ }
+ data++;
+
+ if (len > BGP_MAX_SOFT_VERSION)
+ len = BGP_MAX_SOFT_VERSION;
+
+ memcpy(&soft_version, data, len);
+ soft_version[len] = '\0';
+
+ XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
+ peer->soft_version = XSTRDUP(MTYPE_BGP_SOFT_VERSION,
+ soft_version);
+
+ SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
+ } else {
+ UNSET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
+ XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
+ }
+}
+
/**
* Parse BGP CAPABILITY message for peer.
*
@@ -2697,6 +3116,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
afi_t afi;
iana_safi_t pkt_safi;
safi_t safi;
+ const char *capability;
end = pnt + length;
@@ -2704,8 +3124,8 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
/* We need at least action, capability code and capability
* length. */
if (pnt + 3 > end) {
- zlog_info("%s Capability length error", peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ zlog_err("%pBP: Capability length error", peer);
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return BGP_Stop;
}
@@ -2715,70 +3135,69 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
/* Action value check. */
if (action != CAPABILITY_ACTION_SET
&& action != CAPABILITY_ACTION_UNSET) {
- zlog_info("%s Capability Action Value error %d",
- peer->host, action);
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ zlog_err("%pBP: Capability Action Value error %d", peer,
+ action);
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return BGP_Stop;
}
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s CAPABILITY has action: %d, code: %u, length %u",
- peer->host, action, hdr->code, hdr->length);
-
- if (hdr->length < sizeof(struct capability_mp_data)) {
- zlog_info(
- "%pBP Capability structure is not properly filled out, expected at least %zu bytes but header length specified is %d",
- peer, sizeof(struct capability_mp_data),
- hdr->length);
- return BGP_Stop;
- }
+ zlog_debug("%pBP: CAPABILITY has action: %d, code: %u, length %u",
+ peer, action, hdr->code, hdr->length);
/* Capability length check. */
if ((pnt + hdr->length + 3) > end) {
- zlog_info("%s Capability length error", peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ zlog_err("%pBP: Capability length error", peer);
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return BGP_Stop;
}
- /* Fetch structure to the byte stream. */
- memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
- pnt += hdr->length + 3;
+ /* Ignore capability when override-capability is set. */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+ continue;
+
+ capability = lookup_msg(capcode_str, hdr->code, "Unknown");
+
+ switch (hdr->code) {
+ case CAPABILITY_CODE_SOFT_VERSION:
+ bgp_dynamic_capability_software_version(pnt, action,
+ hdr, peer);
+ break;
+ case CAPABILITY_CODE_MP:
+ if (hdr->length < sizeof(struct capability_mp_data)) {
+ zlog_err("%pBP: Capability (%s) structure is not properly filled out, expected at least %zu bytes but header length specified is %d",
+ peer, capability,
+ sizeof(struct capability_mp_data),
+ hdr->length);
+ return BGP_Stop;
+ }
- /* We know MP Capability Code. */
- if (hdr->code == CAPABILITY_CODE_MP) {
+ memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
pkt_afi = ntohs(mpc.afi);
pkt_safi = mpc.safi;
- /* Ignore capability when override-capability is set. */
- if (CHECK_FLAG(peer->flags,
- PEER_FLAG_OVERRIDE_CAPABILITY))
- continue;
-
/* Convert AFI, SAFI to internal values. */
if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
&safi)) {
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s Dynamic Capability MP_EXT afi/safi invalid (%s/%s)",
- peer->host,
- iana_afi2str(pkt_afi),
- iana_safi2str(pkt_safi));
+ zlog_debug("%pBP: Dynamic Capability %s afi/safi invalid (%s/%s)",
+ peer, capability,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
continue;
}
/* Address family check. */
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s CAPABILITY has %s MP_EXT CAP for afi/safi: %s/%s",
- peer->host,
- action == CAPABILITY_ACTION_SET
- ? "Advertising"
- : "Removing",
- iana_afi2str(pkt_afi),
- iana_safi2str(pkt_safi));
+ zlog_debug("%pBP: CAPABILITY has %s %s CAP for afi/safi: %s/%s",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
if (action == CAPABILITY_ACTION_SET) {
peer->afc_recv[afi][safi] = 1;
@@ -2796,12 +3215,63 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
else
return BGP_Stop;
}
- } else {
- flog_warn(
- EC_BGP_UNRECOGNIZED_CAPABILITY,
- "%s unrecognized capability code: %d - ignored",
- peer->host, hdr->code);
+ break;
+ case CAPABILITY_CODE_RESTART:
+ if ((hdr->length - 2) % 4) {
+ zlog_err("%pBP: Received invalid Graceful-Restart capability length %d",
+ peer, hdr->length);
+ bgp_notify_send(peer->connection,
+ BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
+ }
+
+ bgp_dynamic_capability_graceful_restart(pnt, action,
+ hdr, peer);
+ break;
+ case CAPABILITY_CODE_LLGR:
+ bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
+ break;
+ case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ORF:
+ case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_DYNAMIC:
+ case CAPABILITY_CODE_ADDPATH:
+ case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_FQDN:
+ case CAPABILITY_CODE_ENHE:
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ break;
+ case CAPABILITY_CODE_ROLE:
+ if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
+ zlog_err("%pBP: Capability (%s) length error",
+ peer, capability);
+ bgp_notify_send(peer->connection,
+ BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
+ }
+
+ uint8_t role;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+ memcpy(&role, pnt + 3, sizeof(role));
+
+ peer->remote_role = role;
+ } else {
+ UNSET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+ peer->remote_role = ROLE_UNDEFINED;
+ }
+ break;
+ default:
+ flog_warn(EC_BGP_UNRECOGNIZED_CAPABILITY,
+ "%pBP: unrecognized capability code: %d - ignored",
+ peer, hdr->code);
+ break;
}
+
+ pnt += hdr->length + 3;
}
/* No FSM action necessary */
@@ -2817,7 +3287,8 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
* @param size size of the packet
* @return as in summary
*/
-int bgp_capability_receive(struct peer *peer, bgp_size_t size)
+int bgp_capability_receive(struct peer_connection *connection,
+ struct peer *peer, bgp_size_t size)
{
uint8_t *pnt;
@@ -2832,20 +3303,19 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_NO_CAP,
"%s [Error] BGP dynamic capability is not enabled",
peer->host);
- bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR,
+ bgp_notify_send(connection, BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESTYPE);
return BGP_Stop;
}
/* Status must be Established. */
- if (!peer_established(peer)) {
- flog_err(
- EC_BGP_NO_CAP,
- "%s [Error] Dynamic capability packet received under status %s",
- peer->host,
- lookup_msg(bgp_status_msg, peer->status, NULL));
- bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ if (!peer_established(connection)) {
+ flog_err(EC_BGP_NO_CAP,
+ "%s [Error] Dynamic capability packet received under status %s",
+ peer->host,
+ lookup_msg(bgp_status_msg, connection->status, NULL));
+ bgp_notify_send(connection, BGP_NOTIFY_FSM_ERR,
+ bgp_fsm_error_subcode(connection->status));
return BGP_Stop;
}
@@ -2871,17 +3341,19 @@ void bgp_process_packet(struct event *thread)
{
/* Yes first of all get peer pointer. */
struct peer *peer; // peer
+ struct peer_connection *connection;
uint32_t rpkt_quanta_old; // how many packets to read
int fsm_update_result; // return code of bgp_event_update()
int mprc; // message processing return code
- peer = EVENT_ARG(thread);
+ connection = EVENT_ARG(thread);
+ peer = connection->peer;
rpkt_quanta_old = atomic_load_explicit(&peer->bgp->rpkt_quanta,
memory_order_relaxed);
fsm_update_result = 0;
/* Guard against scheduled events that occur after peer deletion. */
- if (peer->status == Deleted || peer->status == Clearing)
+ if (connection->status == Deleted || connection->status == Clearing)
return;
unsigned int processed = 0;
@@ -2891,8 +3363,8 @@ void bgp_process_packet(struct event *thread)
bgp_size_t size;
char notify_data_length[2];
- frr_with_mutex (&peer->io_mtx) {
- peer->curr = stream_fifo_pop(peer->ibuf);
+ frr_with_mutex (&connection->io_mtx) {
+ peer->curr = stream_fifo_pop(connection->ibuf);
}
if (peer->curr == NULL) // no packets to process, hmm...
@@ -2918,7 +3390,7 @@ void bgp_process_packet(struct event *thread)
frrtrace(2, frr_bgp, open_process, peer, size);
atomic_fetch_add_explicit(&peer->open_in, 1,
memory_order_relaxed);
- mprc = bgp_open_receive(peer, size);
+ mprc = bgp_open_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_PKT_OPEN,
@@ -2930,7 +3402,7 @@ void bgp_process_packet(struct event *thread)
atomic_fetch_add_explicit(&peer->update_in, 1,
memory_order_relaxed);
peer->readtime = monotime(NULL);
- mprc = bgp_update_receive(peer, size);
+ mprc = bgp_update_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_UPDATE_RCV,
@@ -2941,7 +3413,7 @@ void bgp_process_packet(struct event *thread)
frrtrace(2, frr_bgp, notification_process, peer, size);
atomic_fetch_add_explicit(&peer->notify_in, 1,
memory_order_relaxed);
- mprc = bgp_notify_receive(peer, size);
+ mprc = bgp_notify_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_NOTIFY_RCV,
@@ -2953,7 +3425,7 @@ void bgp_process_packet(struct event *thread)
peer->readtime = monotime(NULL);
atomic_fetch_add_explicit(&peer->keepalive_in, 1,
memory_order_relaxed);
- mprc = bgp_keepalive_receive(peer, size);
+ mprc = bgp_keepalive_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_KEEP_RCV,
@@ -2965,7 +3437,7 @@ void bgp_process_packet(struct event *thread)
frrtrace(2, frr_bgp, refresh_process, peer, size);
atomic_fetch_add_explicit(&peer->refresh_in, 1,
memory_order_relaxed);
- mprc = bgp_route_refresh_receive(peer, size);
+ mprc = bgp_route_refresh_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_RFSH_RCV,
@@ -2976,7 +3448,7 @@ void bgp_process_packet(struct event *thread)
frrtrace(2, frr_bgp, capability_process, peer, size);
atomic_fetch_add_explicit(&peer->dynamic_cap_in, 1,
memory_order_relaxed);
- mprc = bgp_capability_receive(peer, size);
+ mprc = bgp_capability_receive(connection, peer, size);
if (mprc == BGP_Stop)
flog_err(
EC_BGP_CAP_RCV,
@@ -3003,7 +3475,7 @@ void bgp_process_packet(struct event *thread)
/* Update FSM */
if (mprc != BGP_PACKET_NOOP)
- fsm_update_result = bgp_event_update(peer, mprc);
+ fsm_update_result = bgp_event_update(connection, mprc);
else
continue;
@@ -3018,12 +3490,12 @@ void bgp_process_packet(struct event *thread)
if (fsm_update_result != FSM_PEER_TRANSFERRED
&& fsm_update_result != FSM_PEER_STOPPED) {
- frr_with_mutex (&peer->io_mtx) {
+ frr_with_mutex (&connection->io_mtx) {
// more work to do, come back later
- if (peer->ibuf->count > 0)
+ if (connection->ibuf->count > 0)
event_add_event(bm->master, bgp_process_packet,
- peer, 0,
- &peer->t_process_packet);
+ connection, 0,
+ &connection->t_process_packet);
}
}
}
@@ -3046,18 +3518,20 @@ void bgp_send_delayed_eor(struct bgp *bgp)
*/
void bgp_packet_process_error(struct event *thread)
{
+ struct peer_connection *connection;
struct peer *peer;
int code;
- peer = EVENT_ARG(thread);
+ connection = EVENT_ARG(thread);
+ peer = connection->peer;
code = EVENT_VAL(thread);
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [Event] BGP error %d on fd %d",
- peer->host, code, peer->fd);
+ zlog_debug("%s [Event] BGP error %d on fd %d", peer->host, code,
+ connection->fd);
/* Closed connection or error on the socket */
- if (peer_established(peer)) {
+ if (peer_established(connection)) {
if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
|| CHECK_FLAG(peer->flags,
PEER_FLAG_GRACEFUL_RESTART_HELPER))
@@ -3068,5 +3542,5 @@ void bgp_packet_process_error(struct event *thread)
peer->last_reset = PEER_DOWN_CLOSE_SESSION;
}
- bgp_event_update(peer, code);
+ bgp_event_update(connection, code);
}