0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 01:31:55 +00:00

bgp/bgp.c, bgp/packets.c, io-loop.c: solving slow shutdown when bird is busy

This commit is contained in:
Katerina Kubecova 2024-12-03 15:37:56 +01:00
parent 780c48a732
commit a01120fc9a
3 changed files with 43 additions and 13 deletions

View File

@ -862,7 +862,7 @@ bgp_conn_enter_close_state(struct bgp_conn *conn)
bgp_conn_set_state(conn, BS_CLOSE); bgp_conn_set_state(conn, BS_CLOSE);
tm_stop(conn->keepalive_timer); tm_stop(conn->keepalive_timer);
conn->sk->rx_hook = NULL; //conn->sk->rx_hook = NULL; // deleting rx_hook here may cause problems with pool listening
/* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */ /* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
bgp_start_timer(p, conn->hold_timer, 10); bgp_start_timer(p, conn->hold_timer, 10);

View File

@ -3094,6 +3094,8 @@ bgp_send(struct bgp_conn *conn, uint type, uint len)
int success = sk_send(sk, len); int success = sk_send(sk, len);
if (success && ((conn->state == BS_ESTABLISHED) || (conn->state == BS_OPENCONFIRM))) if (success && ((conn->state == BS_ESTABLISHED) || (conn->state == BS_OPENCONFIRM)))
bgp_start_timer(conn->bgp, conn->send_hold_timer, conn->send_hold_time); bgp_start_timer(conn->bgp, conn->send_hold_timer, conn->send_hold_time);
struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_PACKETS, "Scheduled packet type %d %s", type, success ? "succesfuly" : "unsuccesfully");
return success; return success;
} }
@ -3234,12 +3236,11 @@ bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type)
ASSERT(conn->sk); ASSERT(conn->sk);
struct bgp_proto *p = conn->bgp; struct bgp_proto *p = conn->bgp;
bool wont_ping = conn->channels_to_send || conn->packets_to_send || (conn->sk->tpos != conn->sk->tbuf);
if (c) if (c)
BGP_TRACE(D_PACKETS, "Scheduling packet type %d for channel %s", type, c->c.name); BGP_TRACE(D_PACKETS, "Scheduling packet type %d for channel %s%s", type, c->c.name, wont_ping ? " (TX already scheduled)" : "");
else else
BGP_TRACE(D_PACKETS, "Scheduling packet type %d", type); BGP_TRACE(D_PACKETS, "Scheduling packet type %d %s", type, wont_ping ? " (TX already scheduled)" : "");
bool was_active = conn->channels_to_send || conn->packets_to_send;
if (c) if (c)
{ {
@ -3255,7 +3256,7 @@ bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type)
else else
conn->packets_to_send |= 1 << type; conn->packets_to_send |= 1 << type;
if (was_active || (conn->sk->tpos != conn->sk->tbuf)) if (wont_ping && (type != PKT_SCHEDULE_CLOSE))
return; return;
else if ((type == PKT_KEEPALIVE) || (this_birdloop != p->p.loop)) else if ((type == PKT_KEEPALIVE) || (this_birdloop != p->p.loop))
while (bgp_fire_tx(conn) > 0) while (bgp_fire_tx(conn) > 0)
@ -3572,7 +3573,10 @@ bgp_rx(sock *sk, uint size)
while (end >= pkt_start + BGP_HEADER_LENGTH) while (end >= pkt_start + BGP_HEADER_LENGTH)
{ {
if ((conn->state == BS_CLOSE) || (conn->sk != sk)) if ((conn->state == BS_CLOSE) || (conn->sk != sk))
return 0; {
BGP_TRACE(D_PACKETS,"Packet arrived after closing");
return 0;
}
if ((conn->state == BS_ESTABLISHED) && rt_cork_check(&conn->bgp->uncork)) if ((conn->state == BS_ESTABLISHED) && rt_cork_check(&conn->bgp->uncork))
{ {
sk_pause_rx(p->p.loop, sk); sk_pause_rx(p->p.loop, sk);

View File

@ -535,8 +535,16 @@ sockets_fire(struct birdloop *loop, bool read, bool write)
if (write && (rev & POLLOUT)) if (write && (rev & POLLOUT))
{ {
/* Write until task limit is up */ /* Write until task limit is up */
while ((s == loop->sock_active) && (e = sk_write(s)) && task_still_in_limit()) while (s == loop->sock_active)
; {
int fd = s->fd; /* The socket may disappear after sk_write! */
e = sk_write(s);
bool allowed = task_still_in_limit();
LOOP_TRACE(loop, DL_SOCKETS, "Writing to fd %d: %s%s", fd, e ? "again" : "done", (e && !allowed) ? " (out of time)" : "");
if (!e || !allowed)
break;
}
if (s != loop->sock_active) if (s != loop->sock_active)
continue; continue;
@ -547,11 +555,21 @@ sockets_fire(struct birdloop *loop, bool read, bool write)
/* Read until task limit is up */ /* Read until task limit is up */
if (read && (rev & POLLIN)) if (read && (rev & POLLIN))
while ((s == loop->sock_active) && s->rx_hook && sk_read(s, rev) && (s->fast_rx || task_still_in_limit())) {
;
if (s != loop->sock_active) while (s == loop->sock_active && s->rx_hook )
continue; {
int fd = s->fd; /* The socket may disappear after sk_write! */
e = sk_read(s, rev);
bool allowed = task_still_in_limit();
LOOP_TRACE(loop, DL_SOCKETS, "Read from fd %d: %s%s", fd, e ? "again" : "done", (e && !allowed) ? " (out of time)" : "");
if (!e || !allowed)
break;
}
if (s != loop->sock_active)
continue;
}
if (!(rev & (POLLOUT | POLLIN)) && (rev & POLLERR)) if (!(rev & (POLLOUT | POLLIN)) && (rev & POLLERR))
sk_err(s, rev); sk_err(s, rev);
@ -914,7 +932,15 @@ bird_thread_main(void *arg)
account_to(&this_thread->idle); account_to(&this_thread->idle);
birdloop_leave(thr->meta); birdloop_leave(thr->meta);
poll_retry:; poll_retry:;
for (uint i=0; i<pfd.pfd.used; i++)
{
if (pfd.loop.data[i])
LOOP_TRACE(pfd.loop.data[i], DL_SOCKETS, "Polling fd %d with events 0x%x (timeout %i)",
pfd.pfd.data[i].fd, pfd.pfd.data[i].events, timeout);
}
int rv = poll(pfd.pfd.data, pfd.pfd.used, timeout); int rv = poll(pfd.pfd.data, pfd.pfd.used, timeout);
THREAD_TRACE(DL_SOCKETS, "Returned %d from poll", rv);
if (rv < 0) if (rv < 0)
{ {
if (errno == EINTR || errno == EAGAIN) if (errno == EINTR || errno == EAGAIN)