summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c57
-rw-r--r--bgpd/bgp_bfd.c2
-rw-r--r--bgpd/bgp_bmp.c8
-rw-r--r--bgpd/bgp_dump.c4
-rw-r--r--bgpd/bgp_evpn.c2
-rw-r--r--bgpd/bgp_fsm.c440
-rw-r--r--bgpd/bgp_fsm.h13
-rw-r--r--bgpd/bgp_io.c170
-rw-r--r--bgpd/bgp_io.h42
-rw-r--r--bgpd/bgp_network.c72
-rw-r--r--bgpd/bgp_open.c12
-rw-r--r--bgpd/bgp_packet.c111
-rw-r--r--bgpd/bgp_route.c17
-rw-r--r--bgpd/bgp_script.c3
-rw-r--r--bgpd/bgp_snmp_bgp4.c5
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c2
-rw-r--r--bgpd/bgp_trace.h4
-rw-r--r--bgpd/bgp_vty.c96
-rw-r--r--bgpd/bgpd.c312
-rw-r--r--bgpd/bgpd.h64
-rw-r--r--bgpd/rfapi/rfapi.c21
-rw-r--r--bgpd/rfapi/vnc_zebra.c23
-rw-r--r--configure.ac4
-rw-r--r--debian/not-installed1
-rw-r--r--doc/manpages/frr-zebra.rst5
-rw-r--r--doc/user/zebra.rst6
-rw-r--r--lib/cspf.c5
-rw-r--r--lib/link_state.c12
-rw-r--r--lib/pbr.h1
-rw-r--r--ospf6d/ospf6_auth_trailer.c2
-rw-r--r--ospf6d/ospf6_auth_trailer.h2
-rw-r--r--pbrd/pbr_vty.c5
-rw-r--r--tests/bgpd/test_aspath.c5
-rw-r--r--tests/bgpd/test_capability.c3
-rw-r--r--tests/bgpd/test_mp_attr.c3
-rw-r--r--tests/bgpd/test_packet.c7
-rw-r--r--tests/topotests/static_simple/test_static_simple.py2
-rw-r--r--zebra/interface.c6
-rw-r--r--zebra/kernel_socket.c4
-rw-r--r--zebra/main.c9
-rw-r--r--zebra/redistribute.c2
-rw-r--r--zebra/rib.h6
-rw-r--r--zebra/rt_netlink.c4
-rw-r--r--zebra/zebra_rib.c24
-rw-r--r--zebra/zebra_vrf.c2
45 files changed, 926 insertions, 674 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e07af4ab03..dcf0f4d47c 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -502,6 +502,7 @@ static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
uint8_t *data = pnt;
uint8_t tlv_type;
uint16_t tlv_length;
+ uint8_t *end = data + length;
if (length < 3) {
zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
@@ -510,7 +511,13 @@ static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
}
while (length) {
+ size_t data_len = end - data;
+
tlv_type = *data;
+
+ if (data_len - 1 < 2)
+ return false;
+
ptr_get_be16(data + 1, &tlv_length);
(void)data;
@@ -3461,8 +3468,24 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
/* Get attributes to the end of attribute length. */
while (BGP_INPUT_PNT(peer) < endp) {
+ startp = BGP_INPUT_PNT(peer);
+
+ /* Fewer than three octets remain (or fewer than four
+ * octets, if the Attribute Flags field has the Extended
+ * Length bit set) when beginning to parse the attribute.
+ * That is, this case exists if there remains unconsumed
+ * data in the path attributes but yet insufficient data
+ * to encode a single minimum-sized path attribute.
+ *
+ * An error condition exists and the "treat-as-withdraw"
+ * approach MUST be used (unless some other, more severe
+ * error is encountered dictating a stronger approach),
+ * and the Total Attribute Length MUST be relied upon to
+ * enable the beginning of the NLRI field to be located.
+ */
+
/* Check remaining length check.*/
- if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
+ if ((endp - startp) < BGP_ATTR_MIN_LEN) {
/* XXX warning: long int format, int arg (arg 5) */
flog_warn(
EC_BGP_ATTRIBUTE_TOO_SMALL,
@@ -3471,17 +3494,22 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
(unsigned long)(endp
- stream_pnt(BGP_INPUT(peer))));
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- ret = BGP_ATTR_PARSE_ERROR;
+ if (peer->sort != BGP_PEER_EBGP) {
+ bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ ret = BGP_ATTR_PARSE_ERROR;
+ } else {
+ ret = BGP_ATTR_PARSE_WITHDRAW;
+ }
+
goto done;
}
- /* Fetch attribute flag and type. */
- startp = BGP_INPUT_PNT(peer);
- /* "The lower-order four bits of the Attribute Flags octet are
- unused. They MUST be zero when sent and MUST be ignored when
- received." */
+ /* Fetch attribute flag and type.
+ * The lower-order four bits of the Attribute Flags octet are
+ * unused. They MUST be zero when sent and MUST be ignored when
+ * received.
+ */
flag = 0xF0 & stream_getc(BGP_INPUT(peer));
type = stream_getc(BGP_INPUT(peer));
@@ -3495,9 +3523,14 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
(unsigned long)(endp
- stream_pnt(BGP_INPUT(peer))));
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
- ret = BGP_ATTR_PARSE_ERROR;
+ if (peer->sort != BGP_PEER_EBGP) {
+ bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ ret = BGP_ATTR_PARSE_ERROR;
+ } else {
+ ret = BGP_ATTR_PARSE_WITHDRAW;
+ }
+
goto done;
}
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index d1ddfd0460..7f83e97107 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -56,7 +56,7 @@ static void bfd_session_status_update(struct bfd_session_params *bsp,
peer->last_reset = PEER_DOWN_BFD_DOWN;
/* rfc9384 */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_BFD_DOWN);
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index baf164679c..04a70aa59f 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -703,7 +703,7 @@ static int bmp_peer_status_changed(struct peer *peer)
if (!bmpbgp)
return 0;
- if (peer->status == Deleted) {
+ if (peer->connection->status == Deleted) {
bbpeer = bmp_bgp_peer_find(peer->qobj_node.nid);
if (bbpeer) {
XFREE(MTYPE_BMP_OPEN, bbpeer->open_rx);
@@ -715,10 +715,12 @@ static int bmp_peer_status_changed(struct peer *peer)
}
/* Check if this peer just went to Established */
- if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
+ if ((peer->connection->ostatus != OpenConfirm) ||
+ !(peer_established(peer)))
return 0;
- if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
+ if (peer->doppelganger &&
+ (peer->doppelganger->connection->status != Deleted)) {
bbpeer = bmp_bgp_peer_get(peer);
bbdopp = bmp_bgp_peer_find(peer->doppelganger->qobj_node.nid);
if (bbdopp) {
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index fe77e7e250..3b5fbf368b 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -512,8 +512,8 @@ int bgp_dump_state(struct peer *peer)
bgp_dump_all.type);
bgp_dump_common(obuf, peer, 1); /* force this in as4speak*/
- stream_putw(obuf, peer->ostatus);
- stream_putw(obuf, peer->status);
+ stream_putw(obuf, peer->connection->ostatus);
+ stream_putw(obuf, peer->connection->status);
/* Set length. */
bgp_dump_set_size(obuf, MSG_PROTOCOL_BGP4MP);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 3442eee1e1..7457326c1b 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -6462,7 +6462,7 @@ void bgp_reimport_evpn_routes_upon_martian_change(
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
continue;
- if (peer->status != Established)
+ if (peer->connection->status != Established)
continue;
if (CHECK_FLAG(peer->af_flags[afi][safi],
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 269f5c2948..92038a73e4 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -83,9 +83,6 @@ static void bgp_connect_timer(struct event *event);
static void bgp_holdtime_timer(struct event *event);
static void bgp_delayopen_timer(struct event *event);
-/* BGP FSM functions. */
-static enum bgp_fsm_state_progress bgp_start(struct peer *);
-
/* Register peer with NHT */
int bgp_peer_reg_with_nht(struct peer *peer)
{
@@ -146,13 +143,13 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
- from_peer->host, from_peer, from_peer->fd, peer,
- peer->fd);
+ from_peer->host, from_peer, from_peer->connection->fd,
+ peer, peer->connection->fd);
- bgp_writes_off(peer);
- bgp_reads_off(peer);
- bgp_writes_off(from_peer);
- bgp_reads_off(from_peer);
+ bgp_writes_off(peer->connection);
+ bgp_reads_off(peer->connection);
+ bgp_writes_off(from_peer->connection);
+ bgp_reads_off(from_peer->connection);
/*
* Before exchanging FD remove doppelganger from
@@ -172,20 +169,21 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
EVENT_OFF(from_peer->t_delayopen);
EVENT_OFF(from_peer->t_connect_check_r);
EVENT_OFF(from_peer->t_connect_check_w);
- EVENT_OFF(from_peer->t_process_packet);
+ EVENT_OFF(from_peer->connection->t_process_packet);
/*
* At this point in time, it is possible that there are packets pending
* on various buffers. Those need to be transferred or dropped,
* otherwise we'll get spurious failures during session establishment.
*/
- frr_with_mutex (&peer->io_mtx, &from_peer->io_mtx) {
- fd = peer->fd;
- peer->fd = from_peer->fd;
- from_peer->fd = fd;
+ frr_with_mutex (&peer->connection->io_mtx,
+ &from_peer->connection->io_mtx) {
+ fd = peer->connection->fd;
+ peer->connection->fd = from_peer->connection->fd;
+ from_peer->connection->fd = fd;
- stream_fifo_clean(peer->ibuf);
- stream_fifo_clean(peer->obuf);
+ stream_fifo_clean(peer->connection->ibuf);
+ stream_fifo_clean(peer->connection->obuf);
/*
* this should never happen, since bgp_process_packet() is the
@@ -207,18 +205,21 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
}
// copy each packet from old peer's output queue to new peer
- while (from_peer->obuf->head)
- stream_fifo_push(peer->obuf,
- stream_fifo_pop(from_peer->obuf));
+ while (from_peer->connection->obuf->head)
+ stream_fifo_push(peer->connection->obuf,
+ stream_fifo_pop(
+ from_peer->connection->obuf));
// copy each packet from old peer's input queue to new peer
- while (from_peer->ibuf->head)
- stream_fifo_push(peer->ibuf,
- stream_fifo_pop(from_peer->ibuf));
+ while (from_peer->connection->ibuf->head)
+ stream_fifo_push(peer->connection->ibuf,
+ stream_fifo_pop(
+ from_peer->connection->ibuf));
- ringbuf_wipe(peer->ibuf_work);
- ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work,
- ringbuf_remain(from_peer->ibuf_work));
+ ringbuf_wipe(peer->connection->ibuf_work);
+ ringbuf_copy(peer->connection->ibuf_work,
+ from_peer->connection->ibuf_work,
+ ringbuf_remain(from_peer->connection->ibuf_work));
}
peer->as = from_peer->as;
@@ -229,16 +230,16 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
peer->v_gr_restart = from_peer->v_gr_restart;
peer->cap = from_peer->cap;
peer->remote_role = from_peer->remote_role;
- status = peer->status;
- pstatus = peer->ostatus;
+ status = peer->connection->status;
+ pstatus = peer->connection->ostatus;
last_evt = peer->last_event;
last_maj_evt = peer->last_major_event;
- peer->status = from_peer->status;
- peer->ostatus = from_peer->ostatus;
+ peer->connection->status = from_peer->connection->status;
+ peer->connection->ostatus = from_peer->connection->ostatus;
peer->last_event = from_peer->last_event;
peer->last_major_event = from_peer->last_major_event;
- from_peer->status = status;
- from_peer->ostatus = pstatus;
+ from_peer->connection->status = status;
+ from_peer->connection->ostatus = pstatus;
from_peer->last_event = last_evt;
from_peer->last_major_event = last_maj_evt;
peer->remote_id = from_peer->remote_id;
@@ -295,29 +296,29 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
}
if (bgp_getsockname(peer) < 0) {
- flog_err(
- EC_LIB_SOCKET,
- "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
- (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
- ? "accept"
- : ""),
- peer->host, peer->fd, from_peer->fd);
+ flog_err(EC_LIB_SOCKET,
+ "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
+ (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
+ ? "accept"
+ : ""),
+ peer->host, peer->connection->fd,
+ from_peer->connection->fd);
BGP_EVENT_ADD(peer, BGP_Stop);
BGP_EVENT_ADD(from_peer, BGP_Stop);
return NULL;
}
- if (from_peer->status > Active) {
+ if (from_peer->connection->status > Active) {
if (bgp_getsockname(from_peer) < 0) {
- flog_err(
- EC_LIB_SOCKET,
- "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
-
- (CHECK_FLAG(from_peer->sflags,
- PEER_STATUS_ACCEPT_PEER)
- ? "accept"
- : ""),
- from_peer->host, from_peer->fd, peer->fd);
- bgp_stop(from_peer);
+ flog_err(EC_LIB_SOCKET,
+ "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
+
+ (CHECK_FLAG(from_peer->sflags,
+ PEER_STATUS_ACCEPT_PEER)
+ ? "accept"
+ : ""),
+ from_peer->host, from_peer->connection->fd,
+ peer->connection->fd);
+ bgp_stop(from_peer->connection);
from_peer = NULL;
}
}
@@ -334,10 +335,10 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
if (from_peer)
bgp_replace_nexthop_by_peer(from_peer, peer);
- bgp_reads_on(peer);
- bgp_writes_on(peer);
- event_add_event(bm->master, bgp_process_packet, peer, 0,
- &peer->t_process_packet);
+ bgp_reads_on(peer->connection);
+ bgp_writes_on(peer->connection);
+ event_add_event(bm->master, bgp_process_packet, peer->connection, 0,
+ &peer->connection->t_process_packet);
return (peer);
}
@@ -350,7 +351,7 @@ void bgp_timer_set(struct peer *peer)
afi_t afi;
safi_t safi;
- switch (peer->status) {
+ switch (peer->connection->status) {
case Idle:
/* First entry point of peer's finite state machine. In Idle
status start timer is on unless peer is shutdown or peer is
@@ -518,14 +519,14 @@ static void bgp_connect_timer(struct event *thread)
/* stop the DelayOpenTimer if it is running */
EVENT_OFF(peer->t_delayopen);
- assert(!peer->t_write);
- assert(!peer->t_read);
+ assert(!peer->connection->t_write);
+ assert(!peer->connection->t_read);
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
- bgp_stop(peer);
+ bgp_stop(peer->connection);
else {
EVENT_VAL(thread) = ConnectRetry_timer_expired;
bgp_event(thread); /* bgp_event unlocks peer */
@@ -554,7 +555,7 @@ static void bgp_holdtime_timer(struct event *thread)
* for systems where we are heavily loaded for one
* reason or another.
*/
- inq_count = atomic_load_explicit(&peer->ibuf->count,
+ inq_count = atomic_load_explicit(&peer->connection->ibuf->count,
memory_order_relaxed);
if (inq_count)
BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
@@ -1221,8 +1222,8 @@ static void bgp_update_delay_process_status_change(struct peer *peer)
if (CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV))
bgp_update_restarted_peers(peer);
}
- if (peer->ostatus == Established
- && bgp_update_delay_active(peer->bgp)) {
+ if (peer->connection->ostatus == Established &&
+ bgp_update_delay_active(peer->bgp)) {
/* Adjust the update-delay state to account for this flap.
NOTE: Intentionally skipping adjusting implicit_eors or
explicit_eors
@@ -1298,14 +1299,15 @@ void bgp_fsm_change_status(struct peer *peer, enum bgp_fsm_status status)
}
/* Preserve old status and change into new status. */
- peer->ostatus = peer->status;
- peer->status = status;
+ peer->connection->ostatus = peer->connection->status;
+ peer->connection->status = status;
/* Reset received keepalives counter on every FSM change */
peer->rtt_keepalive_rcv = 0;
/* Fire backward transition hook if that's the case */
- if (peer->ostatus == Established && peer->status != Established)
+ if (peer->connection->ostatus == Established &&
+ peer->connection->status != Established)
hook_call(peer_backward_transition, peer);
/* Save event that caused status change. */
@@ -1332,15 +1334,21 @@ void bgp_fsm_change_status(struct peer *peer, enum bgp_fsm_status status)
bgp_update_delay_process_status_change(peer);
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s fd %d went from %s to %s", peer->host, peer->fd,
- lookup_msg(bgp_status_msg, peer->ostatus, NULL),
- lookup_msg(bgp_status_msg, peer->status, NULL));
+ zlog_debug("%s fd %d went from %s to %s", peer->host,
+ peer->connection->fd,
+ lookup_msg(bgp_status_msg, peer->connection->ostatus,
+ NULL),
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
}
/* Flush the event queue and ensure the peer is shut down */
-static enum bgp_fsm_state_progress bgp_clearing_completed(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_clearing_completed(struct peer_connection *connection)
{
- enum bgp_fsm_state_progress rc = bgp_stop(peer);
+ struct peer *peer = connection->peer;
+
+ enum bgp_fsm_state_progress rc = bgp_stop(connection);
if (rc >= BGP_FSM_SUCCESS)
BGP_EVENT_FLUSH(peer);
@@ -1350,12 +1358,13 @@ static enum bgp_fsm_state_progress bgp_clearing_completed(struct peer *peer)
/* Administrative BGP peer stop event. */
/* May be called multiple times for the same peer */
-enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
+enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection)
{
afi_t afi;
safi_t safi;
char orf_name[BUFSIZ];
enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
+ struct peer *peer = connection->peer;
struct bgp *bgp = peer->bgp;
struct graceful_restart_info *gr_info = NULL;
@@ -1376,7 +1385,7 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
}
/* Can't do this in Clearing; events are used for state transitions */
- if (peer->status != Clearing) {
+ if (connection->status != Clearing) {
/* Delete all existing events of the peer */
BGP_EVENT_FLUSH(peer);
}
@@ -1495,8 +1504,8 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
bgp_keepalives_off(peer);
/* Stop read and write threads. */
- bgp_writes_off(peer);
- bgp_reads_off(peer);
+ bgp_writes_off(connection);
+ bgp_reads_off(connection);
EVENT_OFF(peer->t_connect_check_r);
EVENT_OFF(peer->t_connect_check_w);
@@ -1509,14 +1518,14 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
EVENT_OFF(peer->t_delayopen);
/* Clear input and output buffer. */
- frr_with_mutex (&peer->io_mtx) {
- if (peer->ibuf)
- stream_fifo_clean(peer->ibuf);
- if (peer->obuf)
- stream_fifo_clean(peer->obuf);
+ frr_with_mutex (&connection->io_mtx) {
+ if (connection->ibuf)
+ stream_fifo_clean(connection->ibuf);
+ if (connection->obuf)
+ stream_fifo_clean(connection->obuf);
- if (peer->ibuf_work)
- ringbuf_wipe(peer->ibuf_work);
+ if (connection->ibuf_work)
+ ringbuf_wipe(connection->ibuf_work);
if (peer->curr) {
stream_free(peer->curr);
@@ -1525,9 +1534,9 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
}
/* Close of file descriptor. */
- if (peer->fd >= 0) {
- close(peer->fd);
- peer->fd = -1;
+ if (connection->fd >= 0) {
+ close(connection->fd);
+ connection->fd = -1;
}
/* Reset capabilities. */
@@ -1551,7 +1560,8 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
/* Received ORF prefix-filter */
peer->orf_plist[afi][safi] = NULL;
- if ((peer->status == OpenConfirm) || (peer_established(peer))) {
+ if ((connection->status == OpenConfirm) ||
+ peer_established(peer)) {
/* ORF received prefix-filter pnt */
snprintf(orf_name, sizeof(orf_name), "%s.%d.%d",
peer->host, afi, safi);
@@ -1587,8 +1597,11 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
}
/* BGP peer is stoped by the error. */
-static enum bgp_fsm_state_progress bgp_stop_with_error(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_stop_with_error(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
+
/* Double start timer. */
peer->v_start *= 2;
@@ -1604,7 +1617,7 @@ static enum bgp_fsm_state_progress bgp_stop_with_error(struct peer *peer)
return BGP_FSM_FAILURE;
}
- return bgp_stop(peer);
+ return bgp_stop(connection);
}
@@ -1626,7 +1639,7 @@ bgp_stop_with_notify(struct peer *peer, uint8_t code, uint8_t sub_code)
/* Clear start timer value to default. */
peer->v_start = BGP_INIT_START_TIMER;
- return bgp_stop(peer);
+ return bgp_stop(peer->connection);
}
/**
@@ -1652,18 +1665,20 @@ static void bgp_connect_check(struct event *thread)
struct peer *peer;
peer = EVENT_ARG(thread);
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
- assert(!peer->t_read);
- assert(!peer->t_write);
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_READS_ON));
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_WRITES_ON));
+ assert(!peer->connection->t_read);
+ assert(!peer->connection->t_write);
EVENT_OFF(peer->t_connect_check_r);
EVENT_OFF(peer->t_connect_check_w);
/* Check file descriptor. */
slen = sizeof(status);
- ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status,
- &slen);
+ ret = getsockopt(peer->connection->fd, SOL_SOCKET, SO_ERROR,
+ (void *)&status, &slen);
/* If getsockopt is fail, this is fatal error. */
if (ret < 0) {
@@ -1691,21 +1706,24 @@ static void bgp_connect_check(struct event *thread)
/* TCP connection open. Next we send open message to remote peer. And
add read thread for reading open message. */
-static enum bgp_fsm_state_progress bgp_connect_success(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_connect_success(struct peer_connection *connection)
{
- if (peer->fd < 0) {
+ struct peer *peer = connection->peer;
+
+ if (connection->fd < 0) {
flog_err(EC_BGP_CONNECT, "%s peer's fd is negative value %d",
- __func__, peer->fd);
- return bgp_stop(peer);
+ __func__, connection->fd);
+ return bgp_stop(connection);
}
if (bgp_getsockname(peer) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"%s: bgp_getsockname(): failed for peer %s, fd %d",
- __func__, peer->host, peer->fd);
+ __func__, peer->host, connection->fd);
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
- bgp_writes_on(peer);
+ bgp_fsm_error_subcode(connection->status));
+ bgp_writes_on(connection);
return BGP_FSM_FAILURE;
}
@@ -1715,7 +1733,7 @@ static enum bgp_fsm_state_progress bgp_connect_success(struct peer *peer)
*/
bgp_nht_interface_events(peer);
- bgp_reads_on(peer);
+ bgp_reads_on(connection);
if (bgp_debug_neighbor_events(peer)) {
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
@@ -1735,21 +1753,23 @@ static enum bgp_fsm_state_progress bgp_connect_success(struct peer *peer)
* set.
*/
static enum bgp_fsm_state_progress
-bgp_connect_success_w_delayopen(struct peer *peer)
+bgp_connect_success_w_delayopen(struct peer_connection *connection)
{
- if (peer->fd < 0) {
+ struct peer *peer = connection->peer;
+
+ if (connection->fd < 0) {
flog_err(EC_BGP_CONNECT, "%s: peer's fd is negative value %d",
- __func__, peer->fd);
- return bgp_stop(peer);
+ __func__, connection->fd);
+ return bgp_stop(connection);
}
if (bgp_getsockname(peer) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"%s: bgp_getsockname(): failed for peer %s, fd %d",
- __func__, peer->host, peer->fd);
+ __func__, peer->host, connection->fd);
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
- bgp_writes_on(peer);
+ bgp_fsm_error_subcode(connection->status));
+ bgp_writes_on(connection);
return BGP_FSM_FAILURE;
}
@@ -1759,7 +1779,7 @@ bgp_connect_success_w_delayopen(struct peer *peer)
*/
bgp_nht_interface_events(peer);
- bgp_reads_on(peer);
+ bgp_reads_on(connection);
if (bgp_debug_neighbor_events(peer)) {
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
@@ -1785,9 +1805,12 @@ bgp_connect_success_w_delayopen(struct peer *peer)
}
/* TCP connect fail */
-static enum bgp_fsm_state_progress bgp_connect_fail(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_connect_fail(struct peer_connection *connection)
{
- if (peer_dynamic_neighbor_no_nsf(peer)) {
+ struct peer *peer = connection->peer;
+
+ if (peer_dynamic_neighbor(peer)) {
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s (dynamic neighbor) deleted (%s)",
peer->host, __func__);
@@ -1801,14 +1824,15 @@ static enum bgp_fsm_state_progress bgp_connect_fail(struct peer *peer)
*/
bgp_nht_interface_events(peer);
- return bgp_stop(peer);
+ return bgp_stop(connection);
}
/* This function is the first starting point of all BGP connection. It
* try to connect to remote peer with non-blocking IO.
*/
-enum bgp_fsm_state_progress bgp_start(struct peer *peer)
+static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
int status;
bgp_peer_conf_if_to_su_update(peer);
@@ -1889,10 +1913,10 @@ enum bgp_fsm_state_progress bgp_start(struct peer *peer)
}
}
- assert(!peer->t_write);
- assert(!peer->t_read);
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
+ assert(!connection->t_write);
+ assert(!connection->t_read);
+ assert(!CHECK_FLAG(connection->thread_flags, PEER_THREAD_WRITES_ON));
+ assert(!CHECK_FLAG(connection->thread_flags, PEER_THREAD_READS_ON));
status = bgp_connect(peer);
switch (status) {
@@ -1903,9 +1927,8 @@ enum bgp_fsm_state_progress bgp_start(struct peer *peer)
break;
case connect_success:
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s [FSM] Connect immediately success, fd %d",
- peer->host, peer->fd);
+ zlog_debug("%s [FSM] Connect immediately success, fd %d",
+ peer->host, connection->fd);
BGP_EVENT_ADD(peer, TCP_connection_open);
break;
@@ -1913,13 +1936,11 @@ enum bgp_fsm_state_progress bgp_start(struct peer *peer)
/* To check nonblocking connect, we wait until socket is
readable or writable. */
if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s [FSM] Non blocking connect waiting result, fd %d",
- peer->host, peer->fd);
- if (peer->fd < 0) {
- flog_err(EC_BGP_FSM,
- "%s peer's fd is negative value %d", __func__,
- peer->fd);
+ zlog_debug("%s [FSM] Non blocking connect waiting result, fd %d",
+ peer->host, connection->fd);
+ if (connection->fd < 0) {
+ flog_err(EC_BGP_FSM, "%s peer's fd is negative value %d",
+ __func__, peer->connection->fd);
return BGP_FSM_FAILURE;
}
/*
@@ -1931,21 +1952,23 @@ enum bgp_fsm_state_progress bgp_start(struct peer *peer)
* bgp_connect_check() as the handler for each and cancel the
* unused event in that function.
*/
- event_add_read(bm->master, bgp_connect_check, peer, peer->fd,
- &peer->t_connect_check_r);
- event_add_write(bm->master, bgp_connect_check, peer, peer->fd,
- &peer->t_connect_check_w);
+ event_add_read(bm->master, bgp_connect_check, peer,
+ peer->connection->fd, &peer->t_connect_check_r);
+ event_add_write(bm->master, bgp_connect_check, peer,
+ peer->connection->fd, &peer->t_connect_check_w);
break;
}
return BGP_FSM_SUCCESS;
}
/* Connect retry timer is expired when the peer status is Connect. */
-static enum bgp_fsm_state_progress bgp_reconnect(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_reconnect(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
enum bgp_fsm_state_progress ret;
- ret = bgp_stop(peer);
+ ret = bgp_stop(connection);
if (ret < BGP_FSM_SUCCESS)
return ret;
@@ -1953,13 +1976,16 @@ static enum bgp_fsm_state_progress bgp_reconnect(struct peer *peer)
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
peer->bgp->peer);
- return bgp_start(peer);
+ return bgp_start(connection);
}
-static enum bgp_fsm_state_progress bgp_fsm_open(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_open(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
+
/* If DelayOpen is active, we may still need to send an open message */
- if ((peer->status == Connect) || (peer->status == Active))
+ if ((connection->status == Connect) || (connection->status == Active))
bgp_open_send(peer);
/* Send keepalive and make keepalive timer */
@@ -1970,19 +1996,26 @@ static enum bgp_fsm_state_progress bgp_fsm_open(struct peer *peer)
/* FSM error, unexpected event. This is error of BGP connection. So cut the
peer and change to Idle status. */
-static enum bgp_fsm_state_progress bgp_fsm_event_error(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_event_error(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
+
flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
- peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
+ peer->host,
+ lookup_msg(bgp_status_msg, connection->status, NULL));
return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ bgp_fsm_error_subcode(connection->status));
}
/* Hold timer expire. This is error of BGP connection. So cut the
peer and change to Idle status. */
-static enum bgp_fsm_state_progress bgp_fsm_holdtime_expire(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_holdtime_expire(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
+
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [FSM] Hold timer expire", peer->host);
@@ -2000,8 +2033,10 @@ static enum bgp_fsm_state_progress bgp_fsm_holdtime_expire(struct peer *peer)
/* RFC 4271 DelayOpenTimer_Expires event */
static enum bgp_fsm_state_progress
-bgp_fsm_delayopen_timer_expire(struct peer *peer)
+bgp_fsm_delayopen_timer_expire(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
+
/* Stop the DelayOpenTimer */
EVENT_OFF(peer->t_delayopen);
@@ -2092,7 +2127,8 @@ static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
* Convert peer from stub to full fledged peer, set some timers, and generate
* initial updates.
*/
-static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_establish(struct peer_connection *connection)
{
afi_t afi;
safi_t safi;
@@ -2100,6 +2136,7 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
struct peer *other;
int status;
+ struct peer *peer = connection->peer;
other = peer->doppelganger;
hash_release(peer->bgp->peerhash, peer);
@@ -2282,13 +2319,14 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
}
- if (peer->doppelganger && (peer->doppelganger->status != Deleted)) {
+ if (peer->doppelganger &&
+ (peer->doppelganger->connection->status != Deleted)) {
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"[Event] Deleting stub connection for peer %s",
peer->host);
- if (peer->doppelganger->status > Active)
+ if (peer->doppelganger->connection->status > Active)
bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
else
@@ -2311,43 +2349,48 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
}
/* Keepalive packet is received. */
-static enum bgp_fsm_state_progress bgp_fsm_keepalive(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_keepalive(struct peer_connection *connection)
{
- EVENT_OFF(peer->t_holdtime);
+ EVENT_OFF(connection->peer->t_holdtime);
return BGP_FSM_SUCCESS;
}
/* Update packet is received. */
-static enum bgp_fsm_state_progress bgp_fsm_update(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_update(struct peer_connection *connection)
{
- EVENT_OFF(peer->t_holdtime);
+ EVENT_OFF(connection->peer->t_holdtime);
return BGP_FSM_SUCCESS;
}
/* This is empty event. */
-static enum bgp_fsm_state_progress bgp_ignore(struct peer *peer)
-{
- flog_err(
- EC_BGP_FSM,
- "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd);
+static enum bgp_fsm_state_progress bgp_ignore(struct peer_connection *connection)
+{
+ struct peer *peer = connection->peer;
+
+ flog_err(EC_BGP_FSM,
+ "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, connection->status, NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event], connection->fd);
return BGP_FSM_SUCCESS;
}
/* This is to handle unexpected events.. */
-static enum bgp_fsm_state_progress bgp_fsm_exception(struct peer *peer)
+static enum bgp_fsm_state_progress
+bgp_fsm_exception(struct peer_connection *connection)
{
- flog_err(
- EC_BGP_FSM,
- "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd);
- return bgp_stop(peer);
+ struct peer *peer = connection->peer;
+
+ flog_err(EC_BGP_FSM,
+ "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, connection->status, NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event], connection->fd);
+ return bgp_stop(connection);
}
void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
@@ -2355,7 +2398,7 @@ void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
if (!peer)
return;
- switch (peer->status) {
+ switch (peer->connection->status) {
case Idle:
if (has_valid_nexthops)
BGP_EVENT_ADD(peer, BGP_Start);
@@ -2388,7 +2431,7 @@ void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops)
/* Finite State Machine structure */
static const struct {
- enum bgp_fsm_state_progress (*func)(struct peer *);
+ enum bgp_fsm_state_progress (*func)(struct peer_connection *);
enum bgp_fsm_status next_state;
} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = {
{
@@ -2571,12 +2614,11 @@ int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
{
enum bgp_fsm_status next;
enum bgp_fsm_state_progress ret = 0;
+ int fsm_result = FSM_PEER_NOOP;
struct peer *other;
int passive_conn = 0;
int dyn_nbr;
-
- /* default return code */
- ret = FSM_PEER_NOOP;
+ struct peer_connection *connection = peer->connection;
other = peer->doppelganger;
passive_conn =
@@ -2584,33 +2626,38 @@ int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
dyn_nbr = peer_dynamic_neighbor(peer);
/* Logging this event. */
- next = FSM[peer->status - 1][event - 1].next_state;
+ next = FSM[peer->connection->status - 1][event - 1].next_state;
- if (bgp_debug_neighbor_events(peer) && peer->status != next)
+ if (bgp_debug_neighbor_events(peer) && peer->connection->status != next)
zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host,
bgp_event_str[event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- lookup_msg(bgp_status_msg, next, NULL), peer->fd);
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL),
+ lookup_msg(bgp_status_msg, next, NULL),
+ peer->connection->fd);
peer->last_event = peer->cur_event;
peer->cur_event = event;
/* Call function. */
- if (FSM[peer->status - 1][event - 1].func)
- ret = (*(FSM[peer->status - 1][event - 1].func))(peer);
+ if (FSM[peer->connection->status - 1][event - 1].func)
+ ret = (*(FSM[peer->connection->status - 1][event - 1].func))(
+ peer->connection);
- if (ret >= BGP_FSM_SUCCESS) {
+ switch (ret) {
+ case BGP_FSM_SUCCESS:
+ case BGP_FSM_SUCCESS_STATE_TRANSFER:
if (ret == BGP_FSM_SUCCESS_STATE_TRANSFER &&
next == Established) {
/* The case when doppelganger swap accurred in
bgp_establish.
Update the peer pointer accordingly */
- ret = FSM_PEER_TRANSFERRED;
+ fsm_result = FSM_PEER_TRANSFERRED;
peer = other;
}
/* If status is changed. */
- if (next != peer->status) {
+ if (next != peer->connection->status) {
bgp_fsm_change_status(peer, next);
/*
@@ -2620,14 +2667,14 @@ int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
* Opting for TRANSFERRED since transfer implies
* session establishment.
*/
- if (ret != FSM_PEER_TRANSFERRED)
- ret = FSM_PEER_TRANSITIONED;
+ if (fsm_result != FSM_PEER_TRANSFERRED)
+ fsm_result = FSM_PEER_TRANSITIONED;
}
/* Make sure timer is set. */
bgp_timer_set(peer);
-
- } else {
+ break;
+ case BGP_FSM_FAILURE:
/*
* If we got a return value of -1, that means there was an
* error, restart the FSM. Since bgp_stop() was called on the
@@ -2637,22 +2684,27 @@ int bgp_event_update(struct peer *peer, enum bgp_fsm_events event)
*/
if (!dyn_nbr && !passive_conn && peer->bgp &&
ret != BGP_FSM_FAILURE_AND_DELETE) {
- flog_err(
- EC_BGP_FSM,
- "%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d, last reset: %s",
- peer->host, bgp_event_str[peer->cur_event],
- lookup_msg(bgp_status_msg, peer->status, NULL),
- bgp_event_str[peer->last_event],
- bgp_event_str[peer->last_major_event], peer->fd,
- peer_down_str[peer->last_reset]);
- bgp_stop(peer);
+ flog_err(EC_BGP_FSM,
+ "%s [FSM] Failure handling event %s in state %s, prior events %s, %s, fd %d, last reset: %s",
+ peer->host, bgp_event_str[peer->cur_event],
+ lookup_msg(bgp_status_msg, connection->status,
+ NULL),
+ bgp_event_str[peer->last_event],
+ bgp_event_str[peer->last_major_event],
+ connection->fd,
+ peer_down_str[peer->last_reset]);
+ bgp_stop(connection);
bgp_fsm_change_status(peer, Idle);
bgp_timer_set(peer);
}
- ret = FSM_PEER_STOPPED;
+ fsm_result = FSM_PEER_STOPPED;
+ break;
+ case BGP_FSM_FAILURE_AND_DELETE:
+ fsm_result = FSM_PEER_STOPPED;
+ break;
}
- return ret;
+ return fsm_result;
}
/* BGP GR Code */
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index daf31b266e..1f53ac6118 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -17,15 +17,14 @@ enum bgp_fsm_state_progress {
/* Macro for BGP read, write and timer thread. */
#define BGP_TIMER_ON(T, F, V) \
do { \
- if ((peer->status != Deleted)) \
+ if ((peer->connection->status != Deleted)) \
event_add_timer(bm->master, (F), peer, (V), &(T)); \
} while (0)
-#define BGP_EVENT_ADD(P, E) \
- do { \
- if ((P)->status != Deleted) \
- event_add_event(bm->master, bgp_event, (P), (E), \
- NULL); \
+#define BGP_EVENT_ADD(P, E) \
+ do { \
+ if ((P)->connection->status != Deleted) \
+ event_add_event(bm->master, bgp_event, (P), (E), NULL); \
} while (0)
#define BGP_EVENT_FLUSH(P) \
@@ -115,7 +114,7 @@ enum bgp_fsm_state_progress {
extern void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops);
extern void bgp_event(struct event *event);
extern int bgp_event_update(struct peer *, enum bgp_fsm_events event);
-extern enum bgp_fsm_state_progress bgp_stop(struct peer *peer);
+extern enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection);
extern void bgp_timer_set(struct peer *);
extern void bgp_routeadv_timer(struct event *event);
extern void bgp_fsm_change_status(struct peer *peer,
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index a375bd6005..84e428cbc4 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -29,11 +29,11 @@
/* clang-format on */
/* forward declarations */
-static uint16_t bgp_write(struct peer *);
-static uint16_t bgp_read(struct peer *peer, int *code_p);
+static uint16_t bgp_write(struct peer_connection *connection);
+static uint16_t bgp_read(struct peer_connection *connection, int *code_p);
static void bgp_process_writes(struct event *event);
static void bgp_process_reads(struct event *event);
-static bool validate_header(struct peer *);
+static bool validate_header(struct peer_connection *connection);
/* generic i/o status codes */
#define BGP_IO_TRANS_ERR (1 << 0) /* EAGAIN or similar occurred */
@@ -42,65 +42,69 @@ static bool validate_header(struct peer *);
/* Thread external API ----------------------------------------------------- */
-void bgp_writes_on(struct peer *peer)
+void bgp_writes_on(struct peer_connection *connection)
{
struct frr_pthread *fpt = bgp_pth_io;
+ struct peer *peer = connection->peer;
+
assert(fpt->running);
- assert(peer->status != Deleted);
- assert(peer->obuf);
- assert(peer->ibuf);
- assert(peer->ibuf_work);
+ assert(connection->status != Deleted);
+ assert(connection->obuf);
+ assert(connection->ibuf);
+ assert(connection->ibuf_work);
assert(!peer->t_connect_check_r);
assert(!peer->t_connect_check_w);
- assert(peer->fd);
+ assert(connection->fd);
- event_add_write(fpt->master, bgp_process_writes, peer, peer->fd,
- &peer->t_write);
- SET_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON);
+ event_add_write(fpt->master, bgp_process_writes, connection,
+ connection->fd, &connection->t_write);
+ SET_FLAG(connection->thread_flags, PEER_THREAD_WRITES_ON);
}
-void bgp_writes_off(struct peer *peer)
+void bgp_writes_off(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
struct frr_pthread *fpt = bgp_pth_io;
assert(fpt->running);
- event_cancel_async(fpt->master, &peer->t_write, NULL);
+ event_cancel_async(fpt->master, &connection->t_write, NULL);
EVENT_OFF(peer->t_generate_updgrp_packets);
- UNSET_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON);
+ UNSET_FLAG(peer->connection->thread_flags, PEER_THREAD_WRITES_ON);
}
-void bgp_reads_on(struct peer *peer)
+void bgp_reads_on(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
struct frr_pthread *fpt = bgp_pth_io;
assert(fpt->running);
- assert(peer->status != Deleted);
- assert(peer->ibuf);
- assert(peer->fd);
- assert(peer->ibuf_work);
- assert(peer->obuf);
+ assert(connection->status != Deleted);
+ assert(connection->ibuf);
+ assert(connection->fd);
+ assert(connection->ibuf_work);
+ assert(connection->obuf);
assert(!peer->t_connect_check_r);
assert(!peer->t_connect_check_w);
- assert(peer->fd);
+ assert(connection->fd);
- event_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
- &peer->t_read);
+ event_add_read(fpt->master, bgp_process_reads, connection,
+ connection->fd, &connection->t_read);
- SET_FLAG(peer->thread_flags, PEER_THREAD_READS_ON);
+ SET_FLAG(connection->thread_flags, PEER_THREAD_READS_ON);
}
-void bgp_reads_off(struct peer *peer)
+void bgp_reads_off(struct peer_connection *connection)
{
struct frr_pthread *fpt = bgp_pth_io;
assert(fpt->running);
- event_cancel_async(fpt->master, &peer->t_read, NULL);
- EVENT_OFF(peer->t_process_packet);
- EVENT_OFF(peer->t_process_packet_error);
+ event_cancel_async(fpt->master, &connection->t_read, NULL);
+ EVENT_OFF(connection->t_process_packet);
+ EVENT_OFF(connection->t_process_packet_error);
- UNSET_FLAG(peer->thread_flags, PEER_THREAD_READS_ON);
+ UNSET_FLAG(connection->thread_flags, PEER_THREAD_READS_ON);
}
/* Thread internal functions ----------------------------------------------- */
@@ -111,19 +115,21 @@ void bgp_reads_off(struct peer *peer)
static void bgp_process_writes(struct event *thread)
{
static struct peer *peer;
- peer = EVENT_ARG(thread);
+ struct peer_connection *connection = EVENT_ARG(thread);
uint16_t status;
bool reschedule;
bool fatal = false;
- if (peer->fd < 0)
+ peer = connection->peer;
+
+ if (connection->fd < 0)
return;
struct frr_pthread *fpt = bgp_pth_io;
- frr_with_mutex (&peer->io_mtx) {
- status = bgp_write(peer);
- reschedule = (stream_fifo_head(peer->obuf) != NULL);
+ frr_with_mutex (&connection->io_mtx) {
+ status = bgp_write(connection);
+ reschedule = (stream_fifo_head(connection->obuf) != NULL);
}
/* no problem */
@@ -142,26 +148,26 @@ static void bgp_process_writes(struct event *thread)
* sent in the update message
*/
if (reschedule) {
- event_add_write(fpt->master, bgp_process_writes, peer, peer->fd,
- &peer->t_write);
+ event_add_write(fpt->master, bgp_process_writes, connection,
+ connection->fd, &connection->t_write);
} else if (!fatal) {
BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
bgp_generate_updgrp_packets);
}
}
-static int read_ibuf_work(struct peer *peer)
+static int read_ibuf_work(struct peer_connection *connection)
{
/* static buffer for transferring packets */
/* shorter alias to peer's input buffer */
- struct ringbuf *ibw = peer->ibuf_work;
+ struct ringbuf *ibw = connection->ibuf_work;
/* packet size as given by header */
uint16_t pktsize = 0;
struct stream *pkt;
/* ============================================== */
- frr_with_mutex (&peer->io_mtx) {
- if (peer->ibuf->count >= bm->inq_limit)
+ frr_with_mutex (&connection->io_mtx) {
+ if (connection->ibuf->count >= bm->inq_limit)
return -ENOMEM;
}
@@ -170,7 +176,7 @@ static int read_ibuf_work(struct peer *peer)
return 0;
/* check that header is valid */
- if (!validate_header(peer))
+ if (!validate_header(connection))
return -EBADMSG;
/* header is valid; retrieve packet size */
@@ -179,7 +185,7 @@ static int read_ibuf_work(struct peer *peer)
pktsize = ntohs(pktsize);
/* if this fails we are seriously screwed */
- assert(pktsize <= peer->max_packet_size);
+ assert(pktsize <= connection->peer->max_packet_size);
/*
* If we have that much data, chuck it into its own
@@ -195,9 +201,9 @@ static int read_ibuf_work(struct peer *peer)
assert(ringbuf_get(ibw, pkt->data, pktsize) == pktsize);
stream_set_endp(pkt, pktsize);
- frrtrace(2, frr_bgp, packet_read, peer, pkt);
- frr_with_mutex (&peer->io_mtx) {
- stream_fifo_push(peer->ibuf, pkt);
+ frrtrace(2, frr_bgp, packet_read, connection->peer, pkt);
+ frr_with_mutex (&connection->io_mtx) {
+ stream_fifo_push(connection->ibuf, pkt);
}
return pktsize;
@@ -208,29 +214,31 @@ static int read_ibuf_work(struct peer *peer)
* or has hung up.
*
* We read as much data as possible, process as many packets as we can and
- * place them on peer->ibuf for secondary processing by the main thread.
+ * place them on peer->connection.ibuf for secondary processing by the main
+ * thread.
*/
static void bgp_process_reads(struct event *thread)
{
/* clang-format off */
+ struct peer_connection *connection = EVENT_ARG(thread);
static struct peer *peer; /* peer to read from */
uint16_t status; /* bgp_read status code */
bool fatal = false; /* whether fatal error occurred */
- bool added_pkt = false; /* whether we pushed onto ->ibuf */
+ bool added_pkt = false; /* whether we pushed onto ->connection.ibuf */
int code = 0; /* FSM code if error occurred */
static bool ibuf_full_logged; /* Have we logged full already */
int ret = 1;
/* clang-format on */
- peer = EVENT_ARG(thread);
+ peer = connection->peer;
- if (bm->terminating || peer->fd < 0)
+ if (bm->terminating || connection->fd < 0)
return;
struct frr_pthread *fpt = bgp_pth_io;
- frr_with_mutex (&peer->io_mtx) {
- status = bgp_read(peer, &code);
+ frr_with_mutex (&connection->io_mtx) {
+ status = bgp_read(connection, &code);
}
/* error checking phase */
@@ -246,13 +254,13 @@ static void bgp_process_reads(struct event *thread)
/* Handle the error in the main pthread, include the
* specific state change from 'bgp_read'.
*/
- event_add_event(bm->master, bgp_packet_process_error, peer,
- code, &peer->t_process_packet_error);
+ event_add_event(bm->master, bgp_packet_process_error, connection,
+ code, &connection->t_process_packet_error);
goto done;
}
while (true) {
- ret = read_ibuf_work(peer);
+ ret = read_ibuf_work(connection);
if (ret <= 0)
break;
@@ -282,31 +290,33 @@ done:
/* handle invalid header */
if (fatal) {
/* wipe buffer just in case someone screwed up */
- ringbuf_wipe(peer->ibuf_work);
+ ringbuf_wipe(connection->ibuf_work);
return;
}
- event_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
- &peer->t_read);
+ event_add_read(fpt->master, bgp_process_reads, connection,
+ connection->fd, &connection->t_read);
if (added_pkt)
- event_add_event(bm->master, bgp_process_packet, peer, 0,
- &peer->t_process_packet);
+ event_add_event(bm->master, bgp_process_packet, connection, 0,
+ &connection->t_process_packet);
}
/*
* Flush peer output buffer.
*
- * This function pops packets off of peer->obuf and writes them to peer->fd.
- * The amount of packets written is equal to the minimum of peer->wpkt_quanta
- * and the number of packets on the output buffer, unless an error occurs.
+ * This function pops packets off of peer->connection.obuf and writes them to
+ * peer->connection.fd. The amount of packets written is equal to the minimum of
+ * peer->wpkt_quanta and the number of packets on the output buffer, unless an
+ * error occurs.
*
* If write() returns an error, the appropriate FSM event is generated.
*
* The return value is equal to the number of packets written
* (which may be zero).
*/
-static uint16_t bgp_write(struct peer *peer)
+static uint16_t bgp_write(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
uint8_t type;
struct stream *s;
int update_last_write = 0;
@@ -328,7 +338,7 @@ static uint16_t bgp_write(struct peer *peer)
struct stream **streams = ostreams;
struct iovec iov[wpkt_quanta_old];
- s = stream_fifo_head(peer->obuf);
+ s = stream_fifo_head(connection->obuf);
if (!s)
goto done;
@@ -348,7 +358,7 @@ static uint16_t bgp_write(struct peer *peer)
total_written = 0;
do {
- num = writev(peer->fd, iov, iovsz);
+ num = writev(connection->fd, iov, iovsz);
if (num < 0) {
if (!ERRNO_IO_RETRY(errno)) {
@@ -397,7 +407,7 @@ static uint16_t bgp_write(struct peer *peer)
/* Handle statistics */
for (unsigned int i = 0; i < total_written; i++) {
- s = stream_fifo_pop(peer->obuf);
+ s = stream_fifo_pop(connection->obuf);
assert(s == ostreams[i]);
@@ -476,7 +486,8 @@ done : {
uint8_t ibuf_scratch[BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX];
/*
- * Reads a chunk of data from peer->fd into peer->ibuf_work.
+ * Reads a chunk of data from peer->connection.fd into
+ * peer->connection.ibuf_work.
*
* code_p
* Pointer to location to store FSM event code in case of fatal error.
@@ -487,14 +498,14 @@ uint8_t ibuf_scratch[BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX]
* per peer then we need to rethink the global ibuf_scratch
* data structure above.
*/
-static uint16_t bgp_read(struct peer *peer, int *code_p)
+static uint16_t bgp_read(struct peer_connection *connection, int *code_p)
{
size_t readsize; /* how many bytes we want to read */
ssize_t nbytes; /* how many bytes we actually read */
size_t ibuf_work_space; /* space we can read into the work buf */
uint16_t status = 0;
- ibuf_work_space = ringbuf_space(peer->ibuf_work);
+ ibuf_work_space = ringbuf_space(connection->ibuf_work);
if (ibuf_work_space == 0) {
SET_FLAG(status, BGP_IO_WORK_FULL_ERR);
@@ -503,7 +514,7 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
readsize = MIN(ibuf_work_space, sizeof(ibuf_scratch));
- nbytes = read(peer->fd, ibuf_scratch, readsize);
+ nbytes = read(connection->fd, ibuf_scratch, readsize);
/* EAGAIN or EWOULDBLOCK; come back later */
if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
@@ -511,8 +522,8 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
} else if (nbytes < 0) {
/* Fatal error; tear down session */
flog_err(EC_BGP_UPDATE_RCV,
- "%s [Error] bgp_read_packet error: %s", peer->host,
- safe_strerror(errno));
+ "%s [Error] bgp_read_packet error: %s",
+ connection->peer->host, safe_strerror(errno));
/* Handle the error in the main pthread. */
if (code_p)
@@ -522,9 +533,9 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
} else if (nbytes == 0) {
/* Received EOF / TCP session closed */
- if (bgp_debug_neighbor_events(peer))
+ if (bgp_debug_neighbor_events(connection->peer))
zlog_debug("%s [Event] BGP connection closed fd %d",
- peer->host, peer->fd);
+ connection->peer->host, connection->fd);
/* Handle the error in the main pthread. */
if (code_p)
@@ -532,8 +543,8 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
SET_FLAG(status, BGP_IO_FATAL_ERR);
} else {
- assert(ringbuf_put(peer->ibuf_work, ibuf_scratch, nbytes) ==
- (size_t)nbytes);
+ assert(ringbuf_put(connection->ibuf_work, ibuf_scratch,
+ nbytes) == (size_t)nbytes);
}
return status;
@@ -546,11 +557,12 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
* Assumes that there are at least BGP_HEADER_SIZE readable bytes in the input
* buffer.
*/
-static bool validate_header(struct peer *peer)
+static bool validate_header(struct peer_connection *connection)
{
+ struct peer *peer = connection->peer;
uint16_t size;
uint8_t type;
- struct ringbuf *pkt = peer->ibuf_work;
+ struct ringbuf *pkt = connection->ibuf_work;
static const uint8_t m_correct[BGP_MARKER_SIZE] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
diff --git a/bgpd/bgp_io.h b/bgpd/bgp_io.h
index 4c92373c2d..8d481129e5 100644
--- a/bgpd/bgp_io.h
+++ b/bgpd/bgp_io.h
@@ -14,6 +14,8 @@
#include "bgpd/bgpd.h"
#include "frr_pthread.h"
+struct peer_connection;
+
/**
* Start function for write thread.
*
@@ -33,57 +35,57 @@ extern int bgp_io_stop(void **result, struct frr_pthread *fpt);
/**
* Turns on packet writing for a peer.
*
- * After this function is called, any packets placed on peer->obuf will be
- * written to peer->fd until no more packets remain.
+ * After this function is called, any packets placed on connection->obuf will be
+ * written to connection->fd until no more packets remain.
*
- * Additionally, it becomes unsafe to perform socket actions on peer->fd.
+ * Additionally, it becomes unsafe to perform socket actions on connection->fd.
*
* @param peer - peer to register
*/
-extern void bgp_writes_on(struct peer *peer);
+extern void bgp_writes_on(struct peer_connection *peer);
/**
* Turns off packet writing for a peer.
*
- * After this function returns, packets placed on peer->obuf will not be
- * written to peer->fd by the I/O thread.
+ * After this function returns, packets placed on connection->obuf will not be
+ * written to connection->fd by the I/O thread.
*
* After this function returns it becomes safe to perform socket actions on
- * peer->fd.
+ * connection->fd.
*
- * @param peer - peer to deregister
+ * @param connection - connection to deregister
* @param flush - as described
*/
-extern void bgp_writes_off(struct peer *peer);
+extern void bgp_writes_off(struct peer_connection *connection);
/**
* Turns on packet reading for a peer.
*
- * After this function is called, any packets received on peer->fd will be read
- * and copied into the FIFO queue peer->ibuf.
+ * After this function is called, any packets received on connection->fd
+ * will be read and copied into the FIFO queue connection->ibuf.
*
- * Additionally, it becomes unsafe to perform socket actions on peer->fd.
+ * Additionally, it becomes unsafe to perform socket actions on connection->fd.
*
- * Whenever one or more packets are placed onto peer->ibuf, a task of type
+ * Whenever one or more packets are placed onto connection->ibuf, a task of type
* THREAD_EVENT will be placed on the main thread whose handler is
*
* bgp_packet.c:bgp_process_packet()
*
- * @param peer - peer to register
+ * @param connection - The connection to register
*/
-extern void bgp_reads_on(struct peer *peer);
+extern void bgp_reads_on(struct peer_connection *connection);
/**
* Turns off packet reading for a peer.
*
- * After this function is called, any packets received on peer->fd will not be
- * read by the I/O thread.
+ * After this function is called, any packets received on connection->fd
+ * will not be read by the I/O thread.
*
* After this function returns it becomes safe to perform socket actions on
- * peer->fd.
+ * connection->fd.
*
- * @param peer - peer to deregister
+ * @param connection - The connection to register for
*/
-extern void bgp_reads_off(struct peer *peer);
+extern void bgp_reads_off(struct peer_connection *connection);
#endif /* _FRR_BGP_IO_H */
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 73fe00c7ab..c5e7f7be63 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -429,7 +429,7 @@ static void bgp_accept(struct event *thread)
peer1 = peer_lookup_dynamic_neighbor(bgp, &su);
if (peer1) {
/* Dynamic neighbor has been created, let it proceed */
- peer1->fd = bgp_sock;
+ peer1->connection->fd = bgp_sock;
/* Set the user configured MSS to TCP socket */
if (CHECK_FLAG(peer1->flags, PEER_FLAG_TCP_MSS))
@@ -482,11 +482,12 @@ static void bgp_accept(struct event *thread)
* Established and then the Clearing_Completed event is generated. Also,
* block incoming connection in Deleted state.
*/
- if (peer1->status == Clearing || peer1->status == Deleted) {
+ if (peer1->connection->status == Clearing ||
+ peer1->connection->status == Deleted) {
if (bgp_debug_neighbor_events(peer1))
- zlog_debug(
- "[Event] Closing incoming conn for %s (%p) state %d",
- peer1->host, peer1, peer1->status);
+ zlog_debug("[Event] Closing incoming conn for %s (%p) state %d",
+ peer1->host, peer1,
+ peer1->connection->status);
close(bgp_sock);
return;
}
@@ -521,10 +522,9 @@ static void bgp_accept(struct event *thread)
}
if (bgp_debug_neighbor_events(peer1))
- zlog_debug(
- "[Event] connection from %s fd %d, active peer status %d fd %d",
- inet_sutop(&su, buf), bgp_sock, peer1->status,
- peer1->fd);
+ zlog_debug("[Event] connection from %s fd %d, active peer status %d fd %d",
+ inet_sutop(&su, buf), bgp_sock,
+ peer1->connection->status, peer1->connection->fd);
if (peer1->doppelganger) {
/* We have an existing connection. Kill the existing one and run
@@ -563,7 +563,7 @@ static void bgp_accept(struct event *thread)
peer->doppelganger = peer1;
peer1->doppelganger = peer;
- peer->fd = bgp_sock;
+ peer->connection->fd = bgp_sock;
frr_with_privs(&bgpd_privs) {
vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
}
@@ -684,13 +684,13 @@ static int bgp_update_source(struct peer *peer)
if (bgp_update_address(ifp, &peer->su, &addr))
return -1;
- ret = sockunion_bind(peer->fd, &addr, 0, &addr);
+ ret = sockunion_bind(peer->connection->fd, &addr, 0, &addr);
}
/* Source is specified with IP address. */
if (peer->update_source)
- ret = sockunion_bind(peer->fd, peer->update_source, 0,
- peer->update_source);
+ ret = sockunion_bind(peer->connection->fd, peer->update_source,
+ 0, peer->update_source);
return ret;
}
@@ -698,8 +698,10 @@ static int bgp_update_source(struct peer *peer)
/* BGP try to connect to the peer. */
int bgp_connect(struct peer *peer)
{
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_WRITES_ON));
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_READS_ON));
ifindex_t ifindex = 0;
if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) {
@@ -708,11 +710,12 @@ int bgp_connect(struct peer *peer)
return 0;
}
frr_with_privs(&bgpd_privs) {
- /* Make socket for the peer. */
- peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
- bgp_get_bound_name(peer));
+ /* Make socket for the peer. */
+ peer->connection->fd =
+ vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
+ bgp_get_bound_name(peer));
}
- if (peer->fd < 0) {
+ if (peer->connection->fd < 0) {
peer->last_reset = PEER_DOWN_SOCKET_ERROR;
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: Failure to create socket for connection to %s, error received: %s(%d)",
@@ -721,18 +724,18 @@ int bgp_connect(struct peer *peer)
return -1;
}
- set_nonblocking(peer->fd);
+ set_nonblocking(peer->connection->fd);
/* Set the user configured MSS to TCP socket */
if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
- sockopt_tcp_mss_set(peer->fd, peer->tcp_mss);
+ sockopt_tcp_mss_set(peer->connection->fd, peer->tcp_mss);
- bgp_socket_set_buffer_size(peer->fd);
+ bgp_socket_set_buffer_size(peer->connection->fd);
/* Set TCP keepalive when TCP keepalive is enabled */
- bgp_update_setsockopt_tcp_keepalive(peer->bgp, peer->fd);
+ bgp_update_setsockopt_tcp_keepalive(peer->bgp, peer->connection->fd);
- if (bgp_set_socket_ttl(peer, peer->fd) < 0) {
+ if (bgp_set_socket_ttl(peer, peer->connection->fd) < 0) {
peer->last_reset = PEER_DOWN_SOCKET_ERROR;
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: Failure to set socket ttl for connection to %s, error received: %s(%d)",
@@ -742,15 +745,16 @@ int bgp_connect(struct peer *peer)
return -1;
}
- sockopt_reuseaddr(peer->fd);
- sockopt_reuseport(peer->fd);
+ sockopt_reuseaddr(peer->connection->fd);
+ sockopt_reuseport(peer->connection->fd);
#ifdef IPTOS_PREC_INTERNETCONTROL
frr_with_privs(&bgpd_privs) {
if (sockunion_family(&peer->su) == AF_INET)
- setsockopt_ipv4_tos(peer->fd, bm->tcp_dscp);
+ setsockopt_ipv4_tos(peer->connection->fd, bm->tcp_dscp);
else if (sockunion_family(&peer->su) == AF_INET6)
- setsockopt_ipv6_tclass(peer->fd, bm->tcp_dscp);
+ setsockopt_ipv6_tclass(peer->connection->fd,
+ bm->tcp_dscp);
}
#endif
@@ -762,7 +766,7 @@ int bgp_connect(struct peer *peer)
if (!BGP_PEER_SU_UNSPEC(peer))
bgp_md5_set(peer);
- bgp_md5_set_connect(peer->fd, &peer->su, prefixlen,
+ bgp_md5_set_connect(peer->connection->fd, &peer->su, prefixlen,
peer->password);
}
@@ -779,11 +783,11 @@ int bgp_connect(struct peer *peer)
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
- peer->host, peer->fd);
+ peer->host, peer->connection->fd);
/* Connect to the remote peer. */
- return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
- ifindex);
+ return sockunion_connect(peer->connection->fd, &peer->su,
+ htons(peer->port), ifindex);
}
/* After TCP connection is established. Get local address and port. */
@@ -799,10 +803,10 @@ int bgp_getsockname(struct peer *peer)
peer->su_remote = NULL;
}
- peer->su_local = sockunion_getsockname(peer->fd);
+ peer->su_local = sockunion_getsockname(peer->connection->fd);
if (!peer->su_local)
return -1;
- peer->su_remote = sockunion_getpeername(peer->fd);
+ peer->su_remote = sockunion_getpeername(peer->connection->fd);
if (!peer->su_remote)
return -1;
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index e826548e69..9cb88a2d6d 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -911,8 +911,18 @@ static int bgp_capability_software_version(struct peer *peer,
return -1;
}
- if (len) {
+ if (len > BGP_MAX_SOFT_VERSION) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "%s: Received Software Version, but the length is too big, truncating, from peer %s",
+ __func__, peer->host);
+ stream_get(str, s, BGP_MAX_SOFT_VERSION);
+ stream_forward_getp(s, len - BGP_MAX_SOFT_VERSION);
+ len = BGP_MAX_SOFT_VERSION;
+ } else if (len) {
stream_get(str, s, len);
+ }
+
+ if (len) {
str[len] = '\0';
XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 327c6b79fd..a9e772e243 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -111,15 +111,15 @@ static void bgp_packet_add(struct peer *peer, struct stream *s)
uint32_t holdtime;
intmax_t sendholdtime;
- frr_with_mutex (&peer->io_mtx) {
+ frr_with_mutex (&peer->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(peer->connection->obuf))
peer->last_sendq_ok = monotime(NULL);
- stream_fifo_push(peer->obuf, s);
+ stream_fifo_push(peer->connection->obuf, s);
delta = monotime(NULL) - peer->last_sendq_ok;
@@ -477,7 +477,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 (peer->connection->obuf->count >= bm->outq_limit) {
bgp_write_proceed_actions(peer);
return;
}
@@ -605,10 +605,10 @@ void bgp_generate_updgrp_packets(struct event *thread)
bpacket_queue_advance_peer(paf);
}
} while (s && (++generated < wpq) &&
- (peer->obuf->count <= bm->outq_limit));
+ (peer->connection->obuf->count <= bm->outq_limit));
if (generated)
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
bgp_write_proceed_actions(peer);
}
@@ -637,7 +637,7 @@ void bgp_keepalive_send(struct peer *peer)
/* Add packet to the peer. */
bgp_packet_add(peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/*
@@ -706,18 +706,18 @@ void bgp_open_send(struct peer *peer)
/* Add packet to the peer. */
bgp_packet_add(peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->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
*/
@@ -728,7 +728,7 @@ static void bgp_write_notify(struct peer *peer)
struct stream *s;
/* There should be at least one packet. */
- s = stream_fifo_pop(peer->obuf);
+ s = stream_fifo_pop(peer->connection->obuf);
if (!s)
return;
@@ -739,7 +739,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(peer->connection->fd, STREAM_DATA(s), stream_get_endp(s));
/*
* only connection reset/close gets counted as TCP_fatal_error, failure
@@ -753,8 +753,8 @@ static void bgp_write_notify(struct peer *peer)
/* Disable Nagle, make NOTIFY packet go out right away */
val = 1;
- (void)setsockopt(peer->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val,
- sizeof(val));
+ (void)setsockopt(peer->connection->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&val, sizeof(val));
/* Retrieve BGP packet type. */
stream_set_getp(s, BGP_MARKER_SIZE + 2);
@@ -910,7 +910,7 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
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(&peer->connection->io_mtx);
/* ============================================== */
/* Allocate new stream. */
@@ -943,7 +943,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(peer->connection->obuf);
/*
* If possible, store last packet for debugging purposes. This check is
@@ -1028,7 +1028,7 @@ 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(peer->connection->obuf, s);
bgp_peer_gr_flags_update(peer);
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,
@@ -1181,7 +1181,7 @@ 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_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/*
@@ -1299,7 +1299,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
/* Add packet to the peer. */
bgp_packet_add(peer, s);
- bgp_writes_on(peer);
+ bgp_writes_on(peer->connection);
}
/* RFC1771 6.8 Connection collision detection. */
@@ -1326,13 +1326,14 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
* 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) {
+ if (peer_established(peer) || peer->connection->status == Clearing) {
bgp_notify_send(new, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return -1;
}
- if ((peer->status != OpenConfirm) && (peer->status != OpenSent))
+ if ((peer->connection->status != OpenConfirm) &&
+ (peer->connection->status != OpenSent))
return 0;
/*
@@ -1413,7 +1414,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()
*/
@@ -1812,7 +1813,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
return BGP_Stop;
}
}
- peer->rtt = sockopt_tcp_rtt(peer->fd);
+ peer->rtt = sockopt_tcp_rtt(peer->connection->fd);
return Receive_OPEN_message;
}
@@ -1831,7 +1832,7 @@ static int bgp_keepalive_receive(struct peer *peer, bgp_size_t size)
bgp_update_implicit_eors(peer);
- peer->rtt = sockopt_tcp_rtt(peer->fd);
+ peer->rtt = sockopt_tcp_rtt(peer->connection->fd);
/* If the peer's RTT is higher than expected, shutdown
* the peer automatically.
@@ -1921,9 +1922,10 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
flog_err(EC_BGP_INVALID_STATUS,
"%s [FSM] Update packet received under status %s",
peer->host,
- lookup_msg(bgp_status_msg, peer->status, NULL));
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ bgp_fsm_error_subcode(peer->connection->status));
return BGP_Stop;
}
@@ -2047,7 +2049,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;
@@ -2369,13 +2371,13 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
/* 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));
+ 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(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ bgp_fsm_error_subcode(peer->connection->status));
return BGP_Stop;
}
@@ -2471,7 +2473,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",
@@ -2957,13 +2960,13 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size)
/* 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));
+ flog_err(EC_BGP_NO_CAP,
+ "%s [Error] Dynamic capability packet received under status %s",
+ peer->host,
+ lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
- bgp_fsm_error_subcode(peer->status));
+ bgp_fsm_error_subcode(peer->connection->status));
return BGP_Stop;
}
@@ -2989,17 +2992,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;
@@ -3009,8 +3014,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...
@@ -3136,12 +3141,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);
}
}
}
@@ -3164,15 +3169,17 @@ 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)) {
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 3b3cbb28a9..dce8859bc8 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2754,13 +2754,11 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
continue;
if (BGP_PATH_HOLDDOWN(pi2))
continue;
- if (pi2->peer != bgp->peer_self
- && !CHECK_FLAG(
- pi2->peer->sflags,
- PEER_STATUS_NSF_WAIT))
- if (pi2->peer->status
- != Established)
- continue;
+ if (pi2->peer != bgp->peer_self &&
+ !CHECK_FLAG(pi2->peer->sflags,
+ PEER_STATUS_NSF_WAIT) &&
+ !peer_established(pi2->peer))
+ continue;
if (!aspath_cmp_left(pi1->attr->aspath,
pi2->attr->aspath)
@@ -9674,9 +9672,8 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
}
}
- label = decode_label(&path->extra->label[0]);
-
- if (bgp_is_valid_label(&label)) {
+ if (bgp_is_valid_label(&path->extra->label[0])) {
+ label = decode_label(&path->extra->label[0]);
if (json) {
json_object_int_add(json_out, "notag", label);
json_object_array_add(json, json_out);
diff --git a/bgpd/bgp_script.c b/bgpd/bgp_script.c
index 68df175c18..b37385812e 100644
--- a/bgpd/bgp_script.c
+++ b/bgpd/bgp_script.c
@@ -26,7 +26,8 @@ void lua_pushpeer(lua_State *L, const struct peer *peer)
lua_setfield(L, -2, "remote_id");
lua_pushinaddr(L, &peer->local_id);
lua_setfield(L, -2, "local_id");
- lua_pushstring(L, lookup_msg(bgp_status_msg, peer->status, NULL));
+ lua_pushstring(L, lookup_msg(bgp_status_msg, peer->connection->status,
+ NULL));
lua_setfield(L, -2, "state");
lua_pushstring(L, peer->desc ? peer->desc : "");
lua_setfield(L, -2, "description");
diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c
index 123d33bd14..8af87ae4b2 100644
--- a/bgpd/bgp_snmp_bgp4.c
+++ b/bgpd/bgp_snmp_bgp4.c
@@ -251,7 +251,7 @@ static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length,
case BGPPEERIDENTIFIER:
return SNMP_IPADDRESS(peer->remote_id);
case BGPPEERSTATE:
- return SNMP_INTEGER(peer->status);
+ return SNMP_INTEGER(peer->connection->status);
case BGPPEERADMINSTATUS:
*write_method = write_bgpPeerTable;
#define BGP_PeerAdmin_stop 1
@@ -756,7 +756,8 @@ int bgpTrapEstablished(struct peer *peer)
oid index[sizeof(oid) * IN_ADDR_SIZE];
/* Check if this peer just went to Established */
- if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
+ if ((peer->connection->ostatus != OpenConfirm) ||
+ !(peer_established(peer)))
return 0;
ret = inet_aton(peer->host, &addr);
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index 712b5d4af8..5e77a9297b 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -265,7 +265,7 @@ static uint8_t *bgpv2PeerTable(struct variable *v, oid name[], size_t *length,
else
return SNMP_INTEGER(BGP_PEER_ADMIN_STATUS_RUNNING);
case BGP4V2_PEER_STATE:
- return SNMP_INTEGER(peer->status);
+ return SNMP_INTEGER(peer->connection->status);
case BGP4V2_PEER_DESCRIPTION:
if (peer->desc)
return SNMP_STRING(peer->desc);
diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h
index 3213b29d99..964393a9f5 100644
--- a/bgpd/bgp_trace.h
+++ b/bgpd/bgp_trace.h
@@ -54,9 +54,9 @@ PKT_PROCESS_TRACEPOINT_INSTANCE(refresh_process)
TRACEPOINT_EVENT(
frr_bgp,
packet_read,
- TP_ARGS(struct peer *, peer, struct stream *, pkt),
+ TP_ARGS(struct peer_connection *, connection, struct stream *, pkt),
TP_FIELDS(
- ctf_string(peer, PEER_HOSTNAME(peer))
+ ctf_string(peer, PEER_HOSTNAME(connection->peer))
ctf_sequence_hex(uint8_t, packet, pkt->data, size_t,
STREAM_READABLE(pkt))
)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index be0fe42837..445dea92d5 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -2888,7 +2888,7 @@ DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd,
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -2914,7 +2914,7 @@ DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd,
* with aspath containing AS_SET or AS_CONFED_SET.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -4851,7 +4851,7 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
peer_flag_unset(peer, PEER_FLAG_IFPEER_V6ONLY);
/* v6only flag changed. Reset bgp seesion */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5040,7 +5040,7 @@ DEFUN (no_neighbor,
peer_notify_unconfig(peer);
peer_delete(peer);
- if (other && other->status != Deleted) {
+ if (other && other->connection->status != Deleted) {
peer_notify_unconfig(other);
peer_delete(other);
}
@@ -11748,12 +11748,16 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
PEER_TOTAL_TX(peer));
atomic_size_t outq_count, inq_count;
- outq_count = atomic_load_explicit(
- &peer->obuf->count,
- memory_order_relaxed);
- inq_count = atomic_load_explicit(
- &peer->ibuf->count,
- memory_order_relaxed);
+ outq_count =
+ atomic_load_explicit(&peer->connection
+ ->obuf
+ ->count,
+ memory_order_relaxed);
+ inq_count =
+ atomic_load_explicit(&peer->connection
+ ->ibuf
+ ->count,
+ memory_order_relaxed);
json_object_int_add(
json_peer, "tableVersion",
@@ -11789,7 +11793,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json_object_string_add(
json_peer, "state",
lookup_msg(bgp_status_msg,
- peer->status, NULL));
+ peer->connection->status,
+ NULL));
else if (CHECK_FLAG(
peer->sflags,
PEER_STATUS_PREFIX_OVERFLOW))
@@ -11800,7 +11805,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json_object_string_add(
json_peer, "state",
lookup_msg(bgp_status_msg,
- peer->status, NULL));
+ peer->connection->status,
+ NULL));
/* BGP peer state */
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
@@ -11916,12 +11922,16 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
" ");
atomic_size_t outq_count, inq_count;
- outq_count = atomic_load_explicit(
- &peer->obuf->count,
- memory_order_relaxed);
- inq_count = atomic_load_explicit(
- &peer->ibuf->count,
- memory_order_relaxed);
+ outq_count =
+ atomic_load_explicit(&peer->connection
+ ->obuf
+ ->count,
+ memory_order_relaxed);
+ inq_count =
+ atomic_load_explicit(&peer->connection
+ ->ibuf
+ ->count,
+ memory_order_relaxed);
vty_out(vty, "4");
vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation),
@@ -11993,7 +12003,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
else
vty_out(vty, " %12s",
lookup_msg(bgp_status_msg,
- peer->status, NULL));
+ peer->connection
+ ->status,
+ NULL));
vty_out(vty, " %8u", 0);
}
@@ -13573,9 +13585,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
"nbrCommonAdmin");
/* Status. */
- json_object_string_add(
- json_neigh, "bgpState",
- lookup_msg(bgp_status_msg, p->status, NULL));
+ json_object_string_add(json_neigh, "bgpState",
+ lookup_msg(bgp_status_msg,
+ p->connection->status, NULL));
if (peer_established(p)) {
time_t uptime;
@@ -13593,9 +13605,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_object_int_add(json_neigh,
"bgpTimerUpEstablishedEpoch",
epoch_tbuf);
- }
-
- else if (p->status == Active) {
+ } else if (p->connection->status == Active) {
if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE))
json_object_string_add(json_neigh, "bgpStateIs",
"passive");
@@ -13656,7 +13666,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* Configured and Synced tcp-mss value for peer */
if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) {
- sync_tcp_mss = sockopt_tcp_mss_get(p->fd);
+ sync_tcp_mss = sockopt_tcp_mss_get(p->connection->fd);
json_object_int_add(json_neigh, "bgpTcpMssConfigured",
p->tcp_mss);
json_object_int_add(json_neigh, "bgpTcpMssSynced",
@@ -13701,14 +13711,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* Status. */
vty_out(vty, " BGP state = %s",
- lookup_msg(bgp_status_msg, p->status, NULL));
+ lookup_msg(bgp_status_msg, p->connection->status, NULL));
if (peer_established(p))
vty_out(vty, ", up for %8s",
peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN,
0, NULL));
-
- else if (p->status == Active) {
+ else if (p->connection->status == Active) {
if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE))
vty_out(vty, " (passive)");
else if (CHECK_FLAG(p->sflags, PEER_STATUS_NSF_WAIT))
@@ -13743,7 +13752,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* Configured and synced tcp-mss value for peer */
if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) {
- sync_tcp_mss = sockopt_tcp_mss_get(p->fd);
+ sync_tcp_mss = sockopt_tcp_mss_get(p->connection->fd);
vty_out(vty, " Configured tcp-mss is %d", p->tcp_mss);
vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss);
}
@@ -14717,9 +14726,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
/* Packet counts. */
atomic_size_t outq_count, inq_count;
- outq_count = atomic_load_explicit(&p->obuf->count,
+ outq_count = atomic_load_explicit(&p->connection->obuf->count,
memory_order_relaxed);
- inq_count = atomic_load_explicit(&p->ibuf->count,
+ inq_count = atomic_load_explicit(&p->connection->ibuf->count,
memory_order_relaxed);
json_object_int_add(json_stat, "depthInq",
@@ -14770,9 +14779,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
notify_out, notify_in, update_out, update_in,
keepalive_out, keepalive_in, refresh_out, refresh_in,
dynamic_cap_out, dynamic_cap_in;
- outq_count = atomic_load_explicit(&p->obuf->count,
+ outq_count = atomic_load_explicit(&p->connection->obuf->count,
memory_order_relaxed);
- inq_count = atomic_load_explicit(&p->ibuf->count,
+ inq_count = atomic_load_explicit(&p->connection->ibuf->count,
memory_order_relaxed);
open_out = atomic_load_explicit(&p->open_out,
memory_order_relaxed);
@@ -15116,12 +15125,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_object_int_add(json_neigh, "authenticationEnabled",
1);
- if (p->t_read)
+ if (p->connection->t_read)
json_object_string_add(json_neigh, "readThread", "on");
else
json_object_string_add(json_neigh, "readThread", "off");
- if (CHECK_FLAG(p->thread_flags, PEER_THREAD_WRITES_ON))
+ if (CHECK_FLAG(p->connection->thread_flags,
+ PEER_THREAD_WRITES_ON))
json_object_string_add(json_neigh, "writeThread", "on");
else
json_object_string_add(json_neigh, "writeThread",
@@ -15152,10 +15162,12 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
vty_out(vty, "Peer Authentication Enabled\n");
vty_out(vty, "Read thread: %s Write thread: %s FD used: %d\n",
- p->t_read ? "on" : "off",
- CHECK_FLAG(p->thread_flags, PEER_THREAD_WRITES_ON)
+ p->connection->t_read ? "on" : "off",
+ CHECK_FLAG(p->connection->thread_flags,
+ PEER_THREAD_WRITES_ON)
? "on"
- : "off", p->fd);
+ : "off",
+ p->connection->fd);
}
if (p->notify.code == BGP_NOTIFY_OPEN_ERR
@@ -16419,8 +16431,10 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
PEER_STATUS_PREFIX_OVERFLOW))
peer_status = "Idle (PfxCt)";
else
- peer_status = lookup_msg(bgp_status_msg,
- peer->status, NULL);
+ peer_status =
+ lookup_msg(bgp_status_msg,
+ peer->connection->status,
+ NULL);
dynamic = peer_dynamic_neighbor(peer);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index aaf1f41c4b..730c96cdda 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -80,6 +80,7 @@
#include "bgp_trace.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
+DEFINE_MTYPE_STATIC(BGPD, BGP_PEER_CONNECTION, "BGP Connection information");
DEFINE_QOBJ_TYPE(bgp_master);
DEFINE_QOBJ_TYPE(bgp);
DEFINE_QOBJ_TYPE(peer);
@@ -134,8 +135,9 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp)
void bgp_session_reset(struct peer *peer)
{
- if (peer->doppelganger && (peer->doppelganger->status != Deleted)
- && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
+ if (peer->doppelganger &&
+ (peer->doppelganger->connection->status != Deleted) &&
+ !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
peer_delete(peer->doppelganger);
BGP_EVENT_ADD(peer, BGP_Stop);
@@ -155,9 +157,9 @@ static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
n = (nnode) ? *nnode : NULL;
npeer = (n) ? listgetdata(n) : NULL;
- if (peer->doppelganger && (peer->doppelganger->status != Deleted)
- && !(CHECK_FLAG(peer->doppelganger->flags,
- PEER_FLAG_CONFIG_NODE))) {
+ if (peer->doppelganger &&
+ (peer->doppelganger->connection->status != Deleted) &&
+ !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) {
if (peer->doppelganger == npeer)
/* nnode and *nnode are confirmed to be non-NULL here */
*nnode = (*nnode)->next;
@@ -305,7 +307,7 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id,
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
IPV4_ADDR_COPY(&peer->local_id, id);
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_RID_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -484,7 +486,7 @@ void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
if (peer->sort != BGP_PEER_IBGP)
continue;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_CLID_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -508,7 +510,7 @@ void bgp_cluster_id_unset(struct bgp *bgp)
if (peer->sort != BGP_PEER_IBGP)
continue;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_CLID_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -581,7 +583,7 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str)
if (ptype == BGP_PEER_EBGP) {
peer->local_as = as;
if (BGP_IS_VALID_STATE_FOR_NOTIF(
- peer->status)) {
+ peer->connection->status)) {
peer->last_reset =
PEER_DOWN_CONFED_ID_CHANGE;
bgp_notify_send(
@@ -599,7 +601,7 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str)
if (ptype == BGP_PEER_EBGP)
peer->local_as = as;
if (BGP_IS_VALID_STATE_FOR_NOTIF(
- peer->status)) {
+ peer->connection->status)) {
peer->last_reset =
PEER_DOWN_CONFED_ID_CHANGE;
bgp_notify_send(
@@ -626,7 +628,8 @@ void bgp_confederation_id_unset(struct bgp *bgp)
/* We're looking for peers who's AS is not local */
if (peer_sort(peer) != BGP_PEER_IBGP) {
peer->local_as = bgp->as;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status)) {
peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -680,7 +683,7 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as, const char *as_str)
peer->local_as = bgp->as;
(void)peer_sort(peer);
if (BGP_IS_VALID_STATE_FOR_NOTIF(
- peer->status)) {
+ peer->connection->status)) {
peer->last_reset =
PEER_DOWN_CONFED_PEER_CHANGE;
bgp_notify_send(
@@ -737,7 +740,7 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
peer->local_as = bgp->confed_id;
(void)peer_sort(peer);
if (BGP_IS_VALID_STATE_FOR_NOTIF(
- peer->status)) {
+ peer->connection->status)) {
peer->last_reset =
PEER_DOWN_CONFED_PEER_CHANGE;
bgp_notify_send(
@@ -1110,12 +1113,80 @@ enum bgp_peer_sort peer_sort_lookup(struct peer *peer)
return peer->sort;
}
+/*
+ * Mutex will be freed in peer_connection_free
+ * this is a convenience function to reduce cut-n-paste
+ */
+void bgp_peer_connection_buffers_free(struct peer_connection *connection)
+{
+ frr_with_mutex (&connection->io_mtx) {
+ if (connection->ibuf) {
+ stream_fifo_free(connection->ibuf);
+ connection->ibuf = NULL;
+ }
+
+ if (connection->obuf) {
+ stream_fifo_free(connection->obuf);
+ connection->obuf = NULL;
+ }
+
+ if (connection->ibuf_work) {
+ ringbuf_del(connection->ibuf_work);
+ connection->ibuf_work = NULL;
+ }
+ }
+}
+
+static void bgp_peer_connection_free(struct peer_connection *connection)
+{
+ bgp_peer_connection_buffers_free(connection);
+ pthread_mutex_destroy(&connection->io_mtx);
+
+ memset(connection, 0, sizeof(struct peer_connection));
+ XFREE(MTYPE_BGP_PEER_CONNECTION, connection);
+}
+
+struct peer_connection *bgp_peer_connection_new(struct peer *peer)
+{
+ struct peer_connection *connection;
+
+ connection = XCALLOC(MTYPE_BGP_PEER_CONNECTION,
+ sizeof(struct peer_connection));
+
+ connection->peer = peer;
+ connection->fd = -1;
+
+ connection->ibuf = stream_fifo_new();
+ connection->obuf = stream_fifo_new();
+ pthread_mutex_init(&connection->io_mtx, NULL);
+
+ /* We use a larger buffer for peer->obuf_work in the event that:
+ * - We RX a BGP_UPDATE where the attributes alone are just
+ * under BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE.
+ * - The user configures an outbound route-map that does many as-path
+ * prepends or adds many communities. At most they can have
+ * CMD_ARGC_MAX args in a route-map so there is a finite limit on how
+ * large they can make the attributes.
+ *
+ * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid
+ * bounds checking for every single attribute as we construct an
+ * UPDATE.
+ */
+ connection->ibuf_work =
+ ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
+
+ connection->status = Idle;
+ connection->ostatus = Idle;
+
+ return connection;
+}
+
static void peer_free(struct peer *peer)
{
afi_t afi;
safi_t safi;
- assert(peer->status == Deleted);
+ assert(peer->connection->status == Deleted);
QOBJ_UNREG(peer);
@@ -1123,17 +1194,15 @@ static void peer_free(struct peer *peer)
* but just to be sure..
*/
bgp_timer_set(peer);
- bgp_reads_off(peer);
- bgp_writes_off(peer);
+ bgp_reads_off(peer->connection);
+ bgp_writes_off(peer->connection);
event_cancel_event_ready(bm->master, peer);
FOREACH_AFI_SAFI (afi, safi)
EVENT_OFF(peer->t_revalidate_all[afi][safi]);
- assert(!peer->t_write);
- assert(!peer->t_read);
+ assert(!peer->connection->t_write);
+ assert(!peer->connection->t_read);
BGP_EVENT_FLUSH(peer);
- pthread_mutex_destroy(&peer->io_mtx);
-
/* Free connected nexthop, if present */
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
&& !peer_dynamic_neighbor(peer))
@@ -1187,6 +1256,8 @@ static void peer_free(struct peer *peer)
if (peer->as_pretty)
XFREE(MTYPE_BGP, peer->as_pretty);
+ bgp_peer_connection_free(peer->connection);
+
bgp_unlock(peer->bgp);
stream_free(peer->last_reset_cause);
@@ -1368,12 +1439,12 @@ struct peer *peer_new(struct bgp *bgp)
/* Allocate new peer. */
peer = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer));
+ /* Create buffers. */
+ peer->connection = bgp_peer_connection_new(peer);
+
/* Set default value. */
- peer->fd = -1;
peer->v_start = BGP_INIT_START_TIMER;
peer->v_connect = bgp->default_connect_retry;
- peer->status = Idle;
- peer->ostatus = Idle;
peer->cur_event = peer->last_event = peer->last_major_event = 0;
peer->bgp = bgp_lock(bgp);
peer = peer_lock(peer); /* initial reference */
@@ -1410,14 +1481,6 @@ struct peer *peer_new(struct bgp *bgp)
/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);
- /* Create buffers. */
- peer->ibuf = stream_fifo_new();
- peer->obuf = stream_fifo_new();
- pthread_mutex_init(&peer->io_mtx, NULL);
-
- peer->ibuf_work =
- ringbuf_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE/2);
-
/* Get service port number. */
sp = getservbyname("bgp", "tcp");
peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port);
@@ -1894,7 +1957,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified,
/* Stop peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -2266,7 +2329,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
- if (peer->status == OpenSent || peer->status == OpenConfirm) {
+ if (peer->connection->status == OpenSent ||
+ peer->connection->status == OpenConfirm) {
peer->last_reset = PEER_DOWN_AF_ACTIVATE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -2281,9 +2345,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
* activation.
*/
other = peer->doppelganger;
- if (other
- && (other->status == OpenSent
- || other->status == OpenConfirm)) {
+ if (other && (other->connection->status == OpenSent ||
+ other->connection->status == OpenConfirm)) {
other->last_reset = PEER_DOWN_AF_ACTIVATE;
bgp_notify_send(other, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -2504,7 +2567,7 @@ int peer_delete(struct peer *peer)
struct listnode *pn;
int accept_peer;
- assert(peer->status != Deleted);
+ assert(peer->connection->status != Deleted);
bgp = peer->bgp;
accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
@@ -2512,13 +2575,15 @@ int peer_delete(struct peer *peer)
bgp_soft_reconfig_table_task_cancel(bgp, NULL, peer);
bgp_keepalives_off(peer);
- bgp_reads_off(peer);
- bgp_writes_off(peer);
+ bgp_reads_off(peer->connection);
+ bgp_writes_off(peer->connection);
event_cancel_event_ready(bm->master, peer);
FOREACH_AFI_SAFI (afi, safi)
EVENT_OFF(peer->t_revalidate_all[afi][safi]);
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
- assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_WRITES_ON));
+ assert(!CHECK_FLAG(peer->connection->thread_flags,
+ PEER_THREAD_READS_ON));
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON));
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
@@ -2549,7 +2614,7 @@ int peer_delete(struct peer *peer)
* executed after peer structure is deleted.
*/
peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
- bgp_stop(peer);
+ bgp_stop(peer->connection);
UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
if (peer->doppelganger) {
@@ -2590,22 +2655,6 @@ int peer_delete(struct peer *peer)
peer_unlock(peer); /* bgp peer list reference */
}
- /* Buffers. */
- if (peer->ibuf) {
- stream_fifo_free(peer->ibuf);
- peer->ibuf = NULL;
- }
-
- if (peer->obuf) {
- stream_fifo_free(peer->obuf);
- peer->obuf = NULL;
- }
-
- if (peer->ibuf_work) {
- ringbuf_del(peer->ibuf_work);
- peer->ibuf_work = NULL;
- }
-
/* Local and remote addresses. */
if (peer->su_local) {
sockunion_free(peer->su_local);
@@ -2856,7 +2905,7 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
void peer_notify_unconfig(struct peer *peer)
{
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
}
@@ -2871,7 +2920,7 @@ static void peer_notify_shutdown(struct peer *peer)
return;
}
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
}
@@ -2883,7 +2932,7 @@ void peer_group_notify_unconfig(struct peer_group *group)
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
other = peer->doppelganger;
- if (other && other->status != Deleted) {
+ if (other && other->connection->status != Deleted) {
other->group = NULL;
peer_notify_unconfig(other);
} else
@@ -2909,7 +2958,7 @@ int peer_group_delete(struct peer_group *group)
bgp_zebra_terminate_radv(bgp, peer);
peer_delete(peer);
- if (other && other->status != Deleted) {
+ if (other && other->connection->status != Deleted) {
other->group = NULL;
peer_delete(other);
}
@@ -2958,7 +3007,7 @@ int peer_group_remote_as_delete(struct peer_group *group)
peer_delete(peer);
- if (other && other->status != Deleted) {
+ if (other && other->connection->status != Deleted) {
other->group = NULL;
peer_delete(other);
}
@@ -3138,7 +3187,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_RMAP_BIND;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -3694,7 +3743,7 @@ void bgp_instance_down(struct bgp *bgp)
/* Bring down peers, so corresponding routes are purged. */
for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
else
@@ -4377,10 +4426,10 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
if (type == peer_change_reset) {
/* If we're resetting session, we've to delete both peer struct
*/
- if ((peer->doppelganger)
- && (peer->doppelganger->status != Deleted)
- && (!CHECK_FLAG(peer->doppelganger->flags,
- PEER_FLAG_CONFIG_NODE)))
+ if ((peer->doppelganger) &&
+ (peer->doppelganger->connection->status != Deleted) &&
+ (!CHECK_FLAG(peer->doppelganger->flags,
+ PEER_FLAG_CONFIG_NODE)))
peer_delete(peer->doppelganger);
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
@@ -4390,10 +4439,10 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
BGP_ROUTE_REFRESH_NORMAL);
else {
- if ((peer->doppelganger)
- && (peer->doppelganger->status != Deleted)
- && (!CHECK_FLAG(peer->doppelganger->flags,
- PEER_FLAG_CONFIG_NODE)))
+ if ((peer->doppelganger) &&
+ (peer->doppelganger->connection->status != Deleted) &&
+ (!CHECK_FLAG(peer->doppelganger->flags,
+ PEER_FLAG_CONFIG_NODE)))
peer_delete(peer->doppelganger);
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
@@ -4549,7 +4598,8 @@ static void peer_flag_modify_action(struct peer *peer, uint64_t flag)
peer);
}
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status)) {
char *msg = peer->tx_shutdown_message;
size_t msglen;
uint8_t msgbuf[BGP_ADMIN_SHUTDOWN_MSG_LEN + 1];
@@ -4579,7 +4629,7 @@ static void peer_flag_modify_action(struct peer *peer, uint64_t flag)
peer->v_start = BGP_INIT_START_TIMER;
BGP_EVENT_ADD(peer, BGP_Stop);
}
- } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
else if (flag == PEER_FLAG_PASSIVE)
@@ -4616,7 +4666,7 @@ void bgp_shutdown_enable(struct bgp *bgp, const char *msg)
continue;
/* send a RFC 4486 notification message if necessary */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
if (msg) {
size_t datalen = strlen(msg);
@@ -5038,7 +5088,8 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl)
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (peer->sort != BGP_PEER_IBGP) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -5056,7 +5107,8 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl)
peer->ttl = group->conf->ttl;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -5093,7 +5145,7 @@ int peer_ebgp_multihop_unset(struct peer *peer)
peer->ttl = ttl;
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -5110,8 +5162,9 @@ int peer_ebgp_multihop_unset(struct peer *peer)
peer->ttl = BGP_DEFAULT_TTL;
- if (peer->fd >= 0) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (peer->connection->fd >= 0) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status))
bgp_notify_send(
peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5266,7 +5319,7 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5304,7 +5357,7 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname)
member->update_source = NULL;
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5337,7 +5390,7 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5374,7 +5427,7 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5425,7 +5478,7 @@ void peer_update_source_unset(struct peer *peer)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -5461,7 +5514,7 @@ void peer_update_source_unset(struct peer *peer)
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -6426,7 +6479,7 @@ int peer_local_as_unset(struct peer *peer)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or stop peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -6454,7 +6507,7 @@ int peer_local_as_unset(struct peer *peer)
XFREE(MTYPE_BGP, member->change_local_as_pretty);
/* Send notification or stop peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) {
member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
@@ -6486,7 +6539,7 @@ int peer_password_set(struct peer *peer, const char *password)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -6522,7 +6575,7 @@ int peer_password_set(struct peer *peer, const char *password)
member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -6567,7 +6620,7 @@ int peer_password_unset(struct peer *peer)
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -6594,7 +6647,7 @@ int peer_password_unset(struct peer *peer)
XFREE(MTYPE_PEER_PASSWORD, member->password);
/* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
@@ -7795,13 +7848,15 @@ int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
peer->gtsm_hops = gtsm_hops;
- if (peer->fd >= 0)
- sockopt_minttl(peer->su.sa.sa_family, peer->fd,
+ if (peer->connection->fd >= 0)
+ sockopt_minttl(peer->su.sa.sa_family,
+ peer->connection->fd,
MAXTTL + 1 - gtsm_hops);
- if ((peer->status < Established) && peer->doppelganger
- && (peer->doppelganger->fd >= 0))
+ if ((peer->connection->status < Established) &&
+ peer->doppelganger &&
+ (peer->doppelganger->connection->fd >= 0))
sockopt_minttl(peer->su.sa.sa_family,
- peer->doppelganger->fd,
+ peer->doppelganger->connection->fd,
MAXTTL + 1 - gtsm_hops);
} else {
group = peer->group;
@@ -7818,18 +7873,18 @@ int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
* no session then do nothing (will get
* handled by next connection)
*/
- if (gpeer->fd >= 0
- && gpeer->gtsm_hops
- != BGP_GTSM_HOPS_DISABLED)
- sockopt_minttl(
- gpeer->su.sa.sa_family,
- gpeer->fd,
- MAXTTL + 1 - gpeer->gtsm_hops);
- if ((gpeer->status < Established)
- && gpeer->doppelganger
- && (gpeer->doppelganger->fd >= 0))
+ if (gpeer->connection->fd >= 0 &&
+ gpeer->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
+ sockopt_minttl(gpeer->su.sa.sa_family,
+ gpeer->connection->fd,
+ MAXTTL + 1 -
+ gpeer->gtsm_hops);
+ if ((gpeer->connection->status < Established) &&
+ gpeer->doppelganger &&
+ (gpeer->doppelganger->connection->fd >= 0))
sockopt_minttl(gpeer->su.sa.sa_family,
- gpeer->doppelganger->fd,
+ gpeer->doppelganger
+ ->connection->fd,
MAXTTL + 1 - gtsm_hops);
}
}
@@ -7862,14 +7917,16 @@ int peer_ttl_security_hops_unset(struct peer *peer)
if (peer->sort == BGP_PEER_EBGP)
ret = peer_ebgp_multihop_unset(peer);
else {
- if (peer->fd >= 0)
- sockopt_minttl(peer->su.sa.sa_family, peer->fd,
- 0);
+ if (peer->connection->fd >= 0)
+ sockopt_minttl(peer->su.sa.sa_family,
+ peer->connection->fd, 0);
- if ((peer->status < Established) && peer->doppelganger
- && (peer->doppelganger->fd >= 0))
+ if ((peer->connection->status < Established) &&
+ peer->doppelganger &&
+ (peer->doppelganger->connection->fd >= 0))
sockopt_minttl(peer->su.sa.sa_family,
- peer->doppelganger->fd, 0);
+ peer->doppelganger->connection->fd,
+ 0);
}
} else {
group = peer->group;
@@ -7878,15 +7935,16 @@ int peer_ttl_security_hops_unset(struct peer *peer)
if (peer->sort == BGP_PEER_EBGP)
ret = peer_ebgp_multihop_unset(peer);
else {
- if (peer->fd >= 0)
+ if (peer->connection->fd >= 0)
sockopt_minttl(peer->su.sa.sa_family,
- peer->fd, 0);
+ peer->connection->fd, 0);
- if ((peer->status < Established)
- && peer->doppelganger
- && (peer->doppelganger->fd >= 0))
+ if ((peer->connection->status < Established) &&
+ peer->doppelganger &&
+ (peer->doppelganger->connection->fd >= 0))
sockopt_minttl(peer->su.sa.sa_family,
- peer->doppelganger->fd,
+ peer->doppelganger
+ ->connection->fd,
0);
}
}
@@ -7938,7 +7996,7 @@ int peer_clear(struct peer *peer, struct listnode **nnode)
return 0;
peer->v_start = BGP_INIT_START_TIMER;
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_RESET);
else
@@ -7958,7 +8016,7 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
if (!peer->afc[afi][safi])
return BGP_ERR_AF_UNCONFIGURED;
- peer->rtt = sockopt_tcp_rtt(peer->fd);
+ peer->rtt = sockopt_tcp_rtt(peer->connection->fd);
if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
/* Clear the "neighbor x.x.x.x default-originate" flag */
@@ -8241,8 +8299,9 @@ static int peer_unshut_after_cfg(struct bgp *bgp)
peer->host);
peer->shut_during_cfg = false;
- if (peer_active(peer) && peer->status != Established) {
- if (peer->status != Idle)
+ if (peer_active(peer) &&
+ peer->connection->status != Established) {
+ if (peer->connection->status != Idle)
BGP_EVENT_ADD(peer, BGP_Stop);
BGP_EVENT_ADD(peer, BGP_Start);
}
@@ -8343,7 +8402,8 @@ void bgp_terminate(void)
peer);
continue;
}
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(
+ peer->connection->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 67ee8aa138..51e0cb3802 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1120,6 +1120,36 @@ struct llgr_info {
uint8_t flags;
};
+struct peer_connection {
+ struct peer *peer;
+
+ /* Status of the peer connection. */
+ enum bgp_fsm_status status;
+ enum bgp_fsm_status ostatus;
+
+ int fd;
+
+ /* Packet receive and send buffer. */
+ pthread_mutex_t io_mtx; // guards ibuf, obuf
+ struct stream_fifo *ibuf; // packets waiting to be processed
+ struct stream_fifo *obuf; // packets waiting to be written
+
+ struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only
+
+ struct event *t_read;
+ struct event *t_write;
+
+ struct event *t_process_packet;
+ struct event *t_process_packet_error;
+
+ /* Thread flags */
+ _Atomic uint32_t thread_flags;
+#define PEER_THREAD_WRITES_ON (1U << 0)
+#define PEER_THREAD_READS_ON (1U << 1)
+};
+extern struct peer_connection *bgp_peer_connection_new(struct peer *peer);
+extern void bgp_peer_connection_buffers_free(struct peer_connection *connection);
+
/* BGP neighbor structure. */
struct peer {
/* BGP structure. */
@@ -1160,22 +1190,11 @@ struct peer {
/* Local router ID. */
struct in_addr local_id;
- /* Packet receive and send buffer. */
- pthread_mutex_t io_mtx; // guards ibuf, obuf
- struct stream_fifo *ibuf; // packets waiting to be processed
- struct stream_fifo *obuf; // packets waiting to be written
-
- struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only
-
struct stream *curr; // the current packet being parsed
/* the doppelganger peer structure, due to dual TCP conn setup */
struct peer *doppelganger;
- /* Status of the peer. */
- enum bgp_fsm_status status;
- enum bgp_fsm_status ostatus;
-
/* FSM events, stored for debug purposes.
* Note: uchar used for reduced memory usage.
*/
@@ -1187,7 +1206,16 @@ struct peer {
uint16_t table_dump_index;
/* Peer information */
- int fd; /* File descriptor */
+
+ /*
+ * We will have 2 `struct peer_connection` data structures
+ * connection is our attempt to talk to our peer. incoming
+ * is the peer attempting to talk to us. When it is
+ * time to consolidate between the two, we'll solidify
+ * into the connection variable being used.
+ */
+ struct peer_connection *connection;
+
int ttl; /* TTL of TCP connection to the peer. */
int rtt; /* Estimated round-trip-time from TCP_INFO */
int rtt_expected; /* Expected round-trip-time for a peer */
@@ -1520,8 +1548,6 @@ struct peer {
_Atomic uint32_t v_gr_restart;
/* Threads. */
- struct event *t_read;
- struct event *t_write;
struct event *t_start;
struct event *t_connect_check_r;
struct event *t_connect_check_w;
@@ -1535,16 +1561,12 @@ struct peer {
struct event *t_llgr_stale[AFI_MAX][SAFI_MAX];
struct event *t_revalidate_all[AFI_MAX][SAFI_MAX];
struct event *t_generate_updgrp_packets;
- struct event *t_process_packet;
- struct event *t_process_packet_error;
struct event *t_refresh_stalepath;
/* Thread flags. */
_Atomic uint32_t thread_flags;
-#define PEER_THREAD_WRITES_ON (1U << 0)
-#define PEER_THREAD_READS_ON (1U << 1)
-#define PEER_THREAD_KEEPALIVES_ON (1U << 2)
-#define PEER_THREAD_SUBGRP_ADV_DELAY (1U << 3)
+#define PEER_THREAD_KEEPALIVES_ON (1U << 0)
+#define PEER_THREAD_SUBGRP_ADV_DELAY (1U << 1)
/* workqueues */
struct work_queue *clear_node_queue;
@@ -2574,7 +2596,7 @@ static inline char *timestamp_string(time_t ts)
static inline bool peer_established(struct peer *peer)
{
- return peer->status == Established;
+ return peer->connection->status == Established;
}
static inline bool peer_dynamic_neighbor(struct peer *peer)
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 985094d323..ff7137bdd9 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -1236,26 +1236,9 @@ static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp,
* Fill in BGP peer structure
*/
rfd->peer = peer_new(bgp);
- rfd->peer->status = Established; /* keep bgp core happy */
+ rfd->peer->connection->status = Established; /* keep bgp core happy */
- /*
- * since this peer is not on the I/O thread, this lock is not strictly
- * necessary, but serves as a reminder to those who may meddle...
- */
- frr_with_mutex (&rfd->peer->io_mtx) {
- // we don't need any I/O related facilities
- if (rfd->peer->ibuf)
- stream_fifo_free(rfd->peer->ibuf);
- if (rfd->peer->obuf)
- stream_fifo_free(rfd->peer->obuf);
-
- if (rfd->peer->ibuf_work)
- ringbuf_del(rfd->peer->ibuf_work);
-
- rfd->peer->ibuf = NULL;
- rfd->peer->obuf = NULL;
- rfd->peer->ibuf_work = NULL;
- }
+ bgp_peer_connection_buffers_free(rfd->peer->connection);
{ /* base code assumes have valid host pointer */
char buf[INET6_ADDRSTRLEN];
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index c17b17a335..c886beea91 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -171,28 +171,11 @@ static void vnc_redistribute_add(struct prefix *p, uint32_t metric,
* Same setup as in rfapi_open()
*/
vncHD1VR.peer = peer_new(bgp);
- vncHD1VR.peer->status =
+ vncHD1VR.peer->connection->status =
Established; /* keep bgp core happy */
- /*
- * since this peer is not on the I/O thread, this lock
- * is not strictly necessary, but serves as a reminder
- * to those who may meddle...
- */
- frr_with_mutex (&vncHD1VR.peer->io_mtx) {
- // we don't need any I/O related facilities
- if (vncHD1VR.peer->ibuf)
- stream_fifo_free(vncHD1VR.peer->ibuf);
- if (vncHD1VR.peer->obuf)
- stream_fifo_free(vncHD1VR.peer->obuf);
-
- if (vncHD1VR.peer->ibuf_work)
- ringbuf_del(vncHD1VR.peer->ibuf_work);
-
- vncHD1VR.peer->ibuf = NULL;
- vncHD1VR.peer->obuf = NULL;
- vncHD1VR.peer->ibuf_work = NULL;
- }
+ bgp_peer_connection_buffers_free(
+ vncHD1VR.peer->connection);
/* base code assumes have valid host pointer */
vncHD1VR.peer->host =
diff --git a/configure.ac b/configure.ac
index 6d0ffc7adf..cea7571fe0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1385,7 +1385,9 @@ if test "$enable_protobuf3" = "yes"; then
[PROTO3=false && AC_MSG_FAILURE([protobuf3 requested but protobuf-c.h not found. Install protobuf-c.])])
fi
-AC_DEFINE([HAVE_PROTOBUF], [1], [protobuf])
+if test "$enable_protobuf" != "no"; then
+ AC_DEFINE([HAVE_PROTOBUF], [1], [protobuf])
+fi
#
# End of logic for protobuf support.
#
diff --git a/debian/not-installed b/debian/not-installed
index 1a89f35853..8999dd948b 100644
--- a/debian/not-installed
+++ b/debian/not-installed
@@ -1,3 +1,4 @@
usr/include
usr/lib/frr/ospfclient
usr/lib/frr/rfptest
+usr/lib/*/frr/modules/dplane_sample_plugin.so
diff --git a/doc/manpages/frr-zebra.rst b/doc/manpages/frr-zebra.rst
index 722b011ecd..6cc46b806d 100644
--- a/doc/manpages/frr-zebra.rst
+++ b/doc/manpages/frr-zebra.rst
@@ -45,6 +45,11 @@ ROUTES
When the program terminates, do not flush routes installed by zebra from the kernel.
+.. option:: -R, --routing-table <tableno>
+
+ Specify which kernel routing table *Zebra* should communicate with.
+ If this option is not specified the default table (RT_TABLE_MAIN) is used.
+
FILES
=====
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 39add2235f..e3c9998354 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -68,6 +68,12 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
option and we will use Route Replace Semantics instead of delete
than add.
+.. option:: --routing-table <tableno>
+
+ Specify which kernel routing table *Zebra* should communicate with.
+ If this option is not specified the default table (RT_TABLE_MAIN) is
+ used.
+
.. option:: --asic-offload=[notify_on_offload|notify_on_ack]
The linux kernel has the ability to use asic-offload ( see switchdev
diff --git a/lib/cspf.c b/lib/cspf.c
index 6a0fb7f63c..c17d8e0929 100644
--- a/lib/cspf.c
+++ b/lib/cspf.c
@@ -331,6 +331,8 @@ void cspf_clean(struct cspf *algo)
if (processed_count(&algo->processed)) {
frr_each_safe (processed, &algo->processed, path) {
processed_del(&algo->processed, path);
+ if (path == algo->pdst)
+ algo->pdst = NULL;
cpath_del(path);
}
}
@@ -343,6 +345,9 @@ void cspf_clean(struct cspf *algo)
}
}
+ if (algo->pdst)
+ cpath_del(algo->pdst);
+
memset(&algo->csts, 0, sizeof(struct constraints));
algo->path = NULL;
algo->pdst = NULL;
diff --git a/lib/link_state.c b/lib/link_state.c
index 6537f881ce..105e3e28a9 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -523,7 +523,9 @@ struct ls_vertex *ls_vertex_update(struct ls_ted *ted, struct ls_node *node)
if (!ls_node_same(old->node, node)) {
ls_node_del(old->node);
old->node = node;
- }
+ } else
+ ls_node_del(node);
+
old->status = UPDATE;
return old;
}
@@ -805,7 +807,9 @@ struct ls_edge *ls_edge_update(struct ls_ted *ted,
if (!ls_attributes_same(old->attributes, attributes)) {
ls_attributes_del(old->attributes);
old->attributes = attributes;
- }
+ } else
+ ls_attributes_del(attributes);
+
old->status = UPDATE;
return old;
}
@@ -902,7 +906,9 @@ struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref)
if (!ls_prefix_same(old->ls_pref, pref)) {
ls_prefix_del(old->ls_pref);
old->ls_pref = pref;
- }
+ } else
+ ls_prefix_del(pref);
+
old->status = UPDATE;
return old;
}
diff --git a/lib/pbr.h b/lib/pbr.h
index c514cc2a65..d8c06e75bd 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -99,6 +99,7 @@ struct pbr_action {
#define PBR_ACTION_DST_PORT (1 << 8)
#define PBR_ACTION_DSCP (1 << 9)
#define PBR_ACTION_ECN (1 << 10)
+#define PBR_ACTION_DROP (1 << 11) /* nexthop == blackhole */
uint32_t table;
uint32_t queue_id;
diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c
index f98f092edb..10e00921f1 100644
--- a/ospf6d/ospf6_auth_trailer.c
+++ b/ospf6d/ospf6_auth_trailer.c
@@ -664,7 +664,7 @@ void ospf6_auth_update_digest(struct ospf6_interface *oi,
struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
uint32_t pkt_len, enum keychain_hash_algo algo)
{
- static const uint16_t cpid = 1;
+ const uint16_t cpid = htons(OSPFV3_CRYPTO_PROTO_ID);
uint32_t hash_len = keychain_get_hash_len(algo);
uint32_t block_s = keychain_get_block_size(algo);
uint32_t k_len = strlen(auth_str);
diff --git a/ospf6d/ospf6_auth_trailer.h b/ospf6d/ospf6_auth_trailer.h
index 924b89503f..3f82a7b197 100644
--- a/ospf6d/ospf6_auth_trailer.h
+++ b/ospf6d/ospf6_auth_trailer.h
@@ -15,6 +15,8 @@
#define OSPF6_AUTHENTICATION_NULL 0
#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC 1
+#define OSPFV3_CRYPTO_PROTO_ID 1
+
/* Auth debug options */
extern unsigned char conf_debug_ospf6_auth[2];
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index 4e1a0f7503..582ffac9b2 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -1120,6 +1120,9 @@ static void pbrms_clear_set_config(struct pbr_map_sequence *pbrms)
pbrms->nhs_installed = false;
pbrms->forwarding_type = PBR_FT_UNSPEC;
+
+ /* clear advisory flag indicating nexthop == blackhole */
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_DROP);
}
@@ -1278,6 +1281,8 @@ DEFPY (pbr_map_nexthop,
}
} else if (bh) {
nhop.type = NEXTHOP_TYPE_BLACKHOLE;
+ /* advisory flag for non-linux dataplanes */
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_DROP);
} else {
nhop.type = NEXTHOP_TYPE_IFINDEX;
}
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index 57aa2af9de..799733b7b5 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -1343,10 +1343,11 @@ static int handle_attr_test(struct aspath_tests *t)
bgp.asnotation = t->segment->asnotation;
peer.curr = stream_new(BGP_MAX_PACKET_SIZE);
- peer.obuf = stream_fifo_new();
+ peer.connection = bgp_peer_connection_new(&peer);
+ peer.connection->obuf = stream_fifo_new();
peer.bgp = &bgp;
peer.host = (char *)"none";
- peer.fd = -1;
+ peer.connection->fd = -1;
peer.cap = t->cap;
peer.max_packet_size = BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index da17471fd1..84c9f53066 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -972,7 +972,8 @@ int main(void)
parse_test(peer, &opt_params[i++], OPT_PARAM);
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
- peer->status = Established;
+ peer->connection = bgp_peer_connection_new(peer);
+ peer->connection->status = Established;
i = 0;
while (dynamic_cap_msgs[i].name)
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index ae7903e0cc..cebdda9e5c 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -1085,7 +1085,8 @@ int main(void)
peer = peer_create_accept(bgp);
peer->host = (char *)"foo";
- peer->status = Established;
+ peer->connection = bgp_peer_connection_new(peer);
+ peer->connection->status = Established;
peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
ifp.ifindex = 0;
diff --git a/tests/bgpd/test_packet.c b/tests/bgpd/test_packet.c
index 94c3feaa93..a83276be07 100644
--- a/tests/bgpd/test_packet.c
+++ b/tests/bgpd/test_packet.c
@@ -64,11 +64,12 @@ int main(int argc, char *argv[])
}
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
- peer->status = Established;
+ peer->connection = bgp_peer_connection_new(peer);
+ peer->connection->status = Established;
- peer->fd = open(argv[1], O_RDONLY|O_NONBLOCK);
+ peer->connection->fd = open(argv[1], O_RDONLY | O_NONBLOCK);
t.arg = peer;
- peer->t_read = &t;
+ peer->connection->t_read = &t;
// printf("bgp_read_packet returns: %d\n", bgp_read(&t));
}
diff --git a/tests/topotests/static_simple/test_static_simple.py b/tests/topotests/static_simple/test_static_simple.py
index 817336ac21..fd87224b57 100644
--- a/tests/topotests/static_simple/test_static_simple.py
+++ b/tests/topotests/static_simple/test_static_simple.py
@@ -68,7 +68,7 @@ def disable_debug(router):
router.vtysh_cmd("no debug northbound callbacks configuration")
-@retry(retry_timeout=3, initial_wait=0.1)
+@retry(retry_timeout=30, initial_wait=0.1)
def check_kernel(r1, super_prefix, count, add, is_blackhole, vrf, matchvia):
network = ipaddress.ip_network(super_prefix)
vrfstr = f" vrf {vrf}" if vrf else ""
diff --git a/zebra/interface.c b/zebra/interface.c
index 90787f3aa0..9ca330571f 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1195,6 +1195,12 @@ static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down,
zif = ifp->info;
+ /*
+ * FRR does not have enough data to make this request
+ */
+ if (ifp->ifindex == IFINDEX_INTERNAL)
+ return true;
+
/* Current state as we know it */
old_down = !!(ZEBRA_IF_IS_PROTODOWN(zif));
old_set_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index fff3e6416f..d897f4a1df 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1100,11 +1100,11 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
- &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, 0, distance, 0,
+ &p, NULL, &nh, 0, rt_table_main_id, 0, 0, distance, 0,
false);
else
rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0,
- zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
+ zebra_flags, &p, NULL, &nh, 0, rt_table_main_id, 0,
distance, true);
}
diff --git a/zebra/main.c b/zebra/main.c
index aeb9739c13..1e833ce7f1 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -69,6 +69,8 @@ uint32_t rcvbufsize = RCVBUFSIZE_MIN;
uint32_t rcvbufsize = 128 * 1024;
#endif
+uint32_t rt_table_main_id = RT_TABLE_MAIN;
+
#define OPTION_V6_RR_SEMANTICS 2000
#define OPTION_ASIC_OFFLOAD 2001
#define OPTION_V6_WITH_V4_NEXTHOP 2002
@@ -88,6 +90,7 @@ const struct option longopts[] = {
{ "nl-bufsize", required_argument, NULL, 's' },
{ "v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS },
#endif /* HAVE_NETLINK */
+ {"routing-table", optional_argument, NULL, 'R'},
{ 0 }
};
@@ -298,7 +301,7 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv);
- frr_opt_add("baz:e:rK:s:"
+ frr_opt_add("baz:e:rK:s:R:"
#ifdef HAVE_NETLINK
"n"
#endif
@@ -319,6 +322,7 @@ int main(int argc, char **argv)
#else
" -s, Set kernel socket receive buffer size\n"
#endif /* HAVE_NETLINK */
+ " -R, --routing-table Set kernel routing table\n"
);
while (1) {
@@ -373,6 +377,9 @@ int main(int argc, char **argv)
"Rcvbufsize is smaller than recommended value: %d\n",
RCVBUFSIZE_MIN);
break;
+ case 'R':
+ rt_table_main_id = atoi(optarg);
+ break;
#ifdef HAVE_NETLINK
case 'n':
vrf_configure_backend(VRF_BACKEND_NETNS);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 8c8cbfc8d1..7aa254b1cb 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -716,7 +716,7 @@ int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id,
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf_id);
if (!is_zebra_valid_kernel_table(table_id)
- || (table_id == RT_TABLE_MAIN))
+ || (table_id == rt_table_main_id))
return -1;
if (afi >= AFI_MAX)
diff --git a/zebra/rib.h b/zebra/rib.h
index 64bbaf3e76..e20084f8cf 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -185,6 +185,10 @@ struct route_entry {
* don't generate routes
*/
#define MQ_SIZE 11
+
+/* For checking that an object has already queued in some sub-queue */
+#define MQ_BIT_MASK ((1 << MQ_SIZE) - 1)
+
struct meta_queue {
struct list *subq[MQ_SIZE];
uint32_t size; /* sum of lengths of all subqueues */
@@ -625,6 +629,8 @@ extern pid_t pid;
extern bool v6_rr_semantics;
+extern uint32_t rt_table_main_id;
+
/* Name of hook calls */
#define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results"
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index a51d7b849b..2318cd6374 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2476,7 +2476,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
* are trying to give me. So now we have this little hack.
*/
if (mroute->family == AF_INET)
- actual_table = (zvrf->table_id == RT_TABLE_MAIN)
+ actual_table = (zvrf->table_id == rt_table_main_id)
? RT_TABLE_DEFAULT
: zvrf->table_id;
else
@@ -4759,7 +4759,7 @@ ssize_t netlink_mpls_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
req->n.nlmsg_pid = nl->snl.nl_pid;
req->r.rtm_family = AF_MPLS;
- req->r.rtm_table = RT_TABLE_MAIN;
+ req->r.rtm_table = rt_table_main_id;
req->r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
req->r.rtm_scope = RT_SCOPE_UNIVERSE;
req->r.rtm_type = RTN_UNICAST;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 780d3c8991..5a32cf6bb9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -365,7 +365,7 @@ int is_zebra_valid_kernel_table(uint32_t table_id)
int is_zebra_main_routing_table(uint32_t table_id)
{
- if (table_id == RT_TABLE_MAIN)
+ if (table_id == rt_table_main_id)
return 1;
return 0;
}
@@ -3255,12 +3255,26 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
return -1;
/* Invariant: at this point we always have rn->info set. */
- if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
- RIB_ROUTE_QUEUED(qindex))) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ /* A route node must only be in one sub-queue at a time. */
+ if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK)) {
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ /*
+ * curr_qindex_bitmask is power of 2, because a route node must only be in one sub-queue at a time,
+ * so for getting current sub-queue index from bitmask we may use part of classic msb function
+ * (find most significant set bit).
+ */
+ const uint32_t curr_qindex_bitmask = CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK);
+ static const uint8_t pos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,
+ 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
+
+ curr_qindex = pos[(uint32_t)(curr_qindex_bitmask * 0x077CB531UL) >> 27];
+
rnode_debug(rn, re->vrf_id,
"rn %p is already queued in sub-queue %s",
- (void *)rn, subqueue2str(qindex));
+ (void *)rn, subqueue2str(curr_qindex));
+ }
+
return -1;
}
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index b246d445da..0c063830d3 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -371,7 +371,7 @@ struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
zebra_vxlan_init_tables(zvrf);
zebra_mpls_init_tables(zvrf);
zebra_pw_init(zvrf);
- zvrf->table_id = RT_TABLE_MAIN;
+ zvrf->table_id = rt_table_main_id;
/* by default table ID is default one */
return zvrf;
}