From 45fb9742f07c0db4ffd81f428194de8185ba038f Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 27 Jun 2024 09:34:23 +0200 Subject: [PATCH] BGP runs TX as a deferred routine This should help flushing the tx buffers as soon as possible. --- proto/bgp/attrs.c | 40 ++++++++++++++++++++------------------- proto/bgp/bgp.c | 13 ++----------- proto/bgp/bgp.h | 2 -- proto/bgp/packets.c | 46 ++++++++++++++++++++++++++++++++------------- 4 files changed, 56 insertions(+), 45 deletions(-) diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 7cc3e514..6da6e1a8 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1841,32 +1841,34 @@ bgp_done_prefix(struct bgp_ptx_private *c, struct bgp_prefix *px, struct bgp_buc void bgp_tx_resend(struct bgp_proto *p, struct bgp_channel *bc) { - BGP_PTX_LOCK(bc->tx, c); - - ASSERT_DIE(bc->tx_keep); uint seen = 0; - - HASH_WALK(c->prefix_hash, next, px) { - if (!px->cur) + BGP_PTX_LOCK(bc->tx, c); + + ASSERT_DIE(bc->tx_keep); + + HASH_WALK(c->prefix_hash, next, px) { - ASSERT_DIE(px->last); - struct bgp_bucket *last = px->last; + if (!px->cur) + { + ASSERT_DIE(px->last); + struct bgp_bucket *last = px->last; - /* Remove the last reference, we wanna resend the route */ - px->last->px_uc--; - px->last = NULL; + /* Remove the last reference, we wanna resend the route */ + px->last->px_uc--; + px->last = NULL; - /* And send it once again */ - seen += bgp_update_prefix(c, px, last); + /* And send it once again */ + seen += bgp_update_prefix(c, px, last); + } } + HASH_WALK_END; + + if (bc->c.debug & D_EVENTS) + log(L_TRACE "%s.%s: TX resending %u routes", + bc->c.proto->name, bc->c.name, seen); + } - HASH_WALK_END; - - if (bc->c.debug & D_EVENTS) - log(L_TRACE "%s.%s: TX resending %u routes", - bc->c.proto->name, bc->c.name, seen); - if (seen) bgp_schedule_packet(p->conn, bc, PKT_UPDATE); } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b0ec980d..163fdf6a 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -475,8 +475,6 @@ bgp_close_conn(struct bgp_conn *conn) conn->hold_timer = NULL; rfree(conn->send_hold_timer); conn->send_hold_timer = NULL; - rfree(conn->tx_ev); - conn->tx_ev = NULL; sk_close(conn->sk); conn->sk = NULL; @@ -1168,10 +1166,6 @@ bgp_keepalive_timeout(timer *t) DBG("BGP: Keepalive timer\n"); bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE); - - /* Kick TX a bit faster */ - if (ev_active(conn->tx_ev)) - ev_run(conn->tx_ev); } void @@ -1211,8 +1205,6 @@ bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn) conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0); conn->keepalive_timer = tm_new_init(p->p.pool, bgp_keepalive_timeout, conn, 0, 0); conn->send_hold_timer = tm_new_init(p->p.pool, bgp_send_hold_timeout, conn, 0, 0); - - conn->tx_ev = ev_new_init(p->p.pool, bgp_kick_tx, conn); } static void @@ -2796,9 +2788,8 @@ bgp_show_proto_info(struct proto *P) tm_remains(p->conn->hold_timer), p->conn->hold_time); cli_msg(-1006, " Keepalive timer: %t/%u", tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time); - cli_msg(-1006, " TX pending: %d bytes%s", - p->conn->sk->tpos - p->conn->sk->ttx, - ev_active(p->conn->tx_ev) ? " (refill scheduled)" : ""); + cli_msg(-1006, " TX pending: %d bytes", + p->conn->sk->tpos - p->conn->sk->ttx); cli_msg(-1006, " Send hold timer: %t/%u", tm_remains(p->conn->send_hold_timer), p->conn->send_hold_time); } diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index a4fcc65b..7b7908f6 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -309,7 +309,6 @@ struct bgp_conn { timer *hold_timer; timer *keepalive_timer; timer *send_hold_timer; - event *tx_ev; u32 packets_to_send; /* Bitmap of packet types to be sent */ u32 channels_to_send; /* Bitmap of channels with packets to be sent */ u8 last_channel; /* Channel used last time for TX */ @@ -708,7 +707,6 @@ int bgp_check_capabilities(struct bgp_conn *conn); const struct bgp_af_desc *bgp_get_af_desc(u32 afi); const struct bgp_af_caps *bgp_find_af_caps(struct bgp_caps *caps, u32 afi); void bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type); -void bgp_kick_tx(void *vconn); void bgp_tx(struct birdsock *sk); int bgp_rx(struct birdsock *sk, uint size); void bgp_do_uncork(callback *); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 530b2d74..10ee4bc0 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1052,9 +1052,12 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session); bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE); - bgp_start_timer(p, conn->hold_timer, conn->hold_time); - bgp_start_timer(p, conn->send_hold_timer, conn->send_hold_time); - bgp_conn_enter_openconfirm_state(conn); + if (conn->sk) + { + bgp_start_timer(p, conn->hold_timer, conn->hold_time); + bgp_start_timer(p, conn->send_hold_timer, conn->send_hold_time); + bgp_conn_enter_openconfirm_state(conn); + } } @@ -3142,6 +3145,12 @@ bgp_fire_tx(struct bgp_conn *conn) return 0; } +static void bgp_tx_deferred(struct deferred_call *dc); +struct bgp_tx_deferred_call { + struct deferred_call dc; + struct bgp_conn *conn; +}; + /** * bgp_schedule_packet - schedule a packet for transmission * @conn: connection @@ -3161,6 +3170,8 @@ bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type) else BGP_TRACE(D_PACKETS, "Scheduling packet type %d", type); + bool was_active = conn->channels_to_send || conn->packets_to_send; + if (c) { if (! conn->channels_to_send) @@ -3175,18 +3186,28 @@ bgp_schedule_packet(struct bgp_conn *conn, struct bgp_channel *c, int type) else conn->packets_to_send |= 1 << type; - if ((conn->sk->tpos == conn->sk->tbuf) && !ev_active(conn->tx_ev)) - proto_send_event(&p->p, conn->tx_ev); + if (was_active || (conn->sk->tpos != conn->sk->tbuf)) + return; + else if ((type == PKT_KEEPALIVE) || (this_birdloop != p->p.loop)) + while (bgp_fire_tx(conn) > 0) + ; + else + { + struct bgp_tx_deferred_call btdc = { + .dc.hook = bgp_tx_deferred, + .conn = conn, + }; + defer_call(&btdc.dc, sizeof btdc); + } } -void -bgp_kick_tx(void *vconn) -{ - struct bgp_conn *conn = vconn; +static void +bgp_tx_deferred(struct deferred_call *dc) +{ + struct bgp_conn *conn = SKIP_BACK(struct bgp_tx_deferred_call, dc, dc)->conn; DBG("BGP: kicking TX\n"); while (bgp_fire_tx(conn) > 0) - MAYBE_DEFER_TASK(proto_event_list(&conn->bgp->p), conn->tx_ev, - "BGP TX for %s", conn->bgp->p.name); + ; } void @@ -3202,8 +3223,7 @@ bgp_tx(sock *sk) DBG("BGP: TX hook\n"); while (bgp_fire_tx(conn) > 0) - MAYBE_DEFER_TASK(proto_event_list(&conn->bgp->p), conn->tx_ev, - "BGP TX for %s", conn->bgp->p.name); + ; }