mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-06 22:38:08 +00:00
Merge pull request #1668 from qlyoung/fix-bgp-corrupt-header-assert
bgpd: fix race condition causing occasional assert
This commit is contained in:
commit
c6301d7eab
@ -545,19 +545,26 @@ void bgp_open_send(struct peer *peer)
|
|||||||
bgp_writes_on(peer);
|
bgp_writes_on(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is only for sending NOTIFICATION message to neighbor. */
|
/*
|
||||||
|
* 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.
|
||||||
|
* Transmission is best-effort.
|
||||||
|
*
|
||||||
|
* @requires peer->io_mtx
|
||||||
|
* @param peer
|
||||||
|
* @return 0
|
||||||
|
*/
|
||||||
static int bgp_write_notify(struct peer *peer)
|
static int bgp_write_notify(struct peer *peer)
|
||||||
{
|
{
|
||||||
int ret, val;
|
int ret, val;
|
||||||
u_char type;
|
u_char type;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
|
|
||||||
pthread_mutex_lock(&peer->io_mtx);
|
/* There should be at least one packet. */
|
||||||
{
|
s = stream_fifo_pop(peer->obuf);
|
||||||
/* There should be at least one packet. */
|
|
||||||
s = stream_fifo_pop(peer->obuf);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&peer->io_mtx);
|
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return 0;
|
return 0;
|
||||||
@ -622,6 +629,14 @@ static int bgp_write_notify(struct peer *peer)
|
|||||||
* This function attempts to write the packet from the thread it is called
|
* This function attempts to write the packet from the thread it is called
|
||||||
* from, to ensure the packet gets out ASAP.
|
* from, to ensure the packet gets out ASAP.
|
||||||
*
|
*
|
||||||
|
* This function may be called from multiple threads. Since the function
|
||||||
|
* modifies I/O buffer(s) in the peer, these are locked for the duration of the
|
||||||
|
* call to prevent tampering from other threads.
|
||||||
|
*
|
||||||
|
* Delivery of the NOTIFICATION is attempted once and is best-effort. After
|
||||||
|
* return, the peer structure *must* be reset; no assumptions about session
|
||||||
|
* state are valid.
|
||||||
|
*
|
||||||
* @param peer
|
* @param peer
|
||||||
* @param code BGP error code
|
* @param code BGP error code
|
||||||
* @param sub_code BGP error subcode
|
* @param sub_code BGP error subcode
|
||||||
@ -634,6 +649,10 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
|
|||||||
struct stream *s;
|
struct stream *s;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
|
/* Lock I/O mutex to prevent other threads from pushing packets */
|
||||||
|
pthread_mutex_lock(&peer->io_mtx);
|
||||||
|
/* ============================================== */
|
||||||
|
|
||||||
/* Allocate new stream. */
|
/* Allocate new stream. */
|
||||||
s = stream_new(BGP_MAX_PACKET_SIZE);
|
s = stream_new(BGP_MAX_PACKET_SIZE);
|
||||||
|
|
||||||
@ -651,20 +670,8 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
|
|||||||
/* Set BGP packet length. */
|
/* Set BGP packet length. */
|
||||||
length = bgp_packet_set_size(s);
|
length = bgp_packet_set_size(s);
|
||||||
|
|
||||||
/*
|
|
||||||
* Turn off keepalive generation for peer. This is necessary because
|
|
||||||
* otherwise between the time we wipe the output buffer and the time we
|
|
||||||
* push the NOTIFY onto it, the KA generation thread could have pushed
|
|
||||||
* a KEEPALIVE in the middle.
|
|
||||||
*/
|
|
||||||
bgp_keepalives_off(peer);
|
|
||||||
|
|
||||||
/* wipe output buffer */
|
/* wipe output buffer */
|
||||||
pthread_mutex_lock(&peer->io_mtx);
|
stream_fifo_clean(peer->obuf);
|
||||||
{
|
|
||||||
stream_fifo_clean(peer->obuf);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&peer->io_mtx);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If possible, store last packet for debugging purposes. This check is
|
* If possible, store last packet for debugging purposes. This check is
|
||||||
@ -728,9 +735,12 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
|
|||||||
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
|
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
|
||||||
|
|
||||||
/* Add packet to peer's output queue */
|
/* Add packet to peer's output queue */
|
||||||
bgp_packet_add(peer, s);
|
stream_fifo_push(peer->obuf, s);
|
||||||
|
|
||||||
bgp_write_notify(peer);
|
bgp_write_notify(peer);
|
||||||
|
|
||||||
|
/* ============================================== */
|
||||||
|
pthread_mutex_unlock(&peer->io_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user