From: Donald Sharp Date: Thu, 19 Jan 2023 16:43:12 +0000 (-0500) Subject: bgpd: Limit peer output queue length like input queue length X-Git-Tag: base_8.5~46^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=963b7ee44845481197a1e04bf922a872041bec00;p=matthieu%2Ffrr.git bgpd: Limit peer output queue length like input queue length Consider this scenario: Lots of peers with a bunch of route information that is changing fast. One of the peers happens to be really slow for whatever reason. The way the output queue is filled is that bgpd puts 64 packets at a time and then reschedules itself to send more in the future. Now suppose that peer has hit it's input Queue limit and is slow. As such bgp will continue to add data to the output Queue, irrelevant if the other side is receiving this data. Let's limit the Output Queue to the same limit as the Input Queue. This should prevent bgp eating up large amounts of memory as stream data when under severe network trauma. Signed-off-by: Donald Sharp --- diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 5d4cf2a6aa..9e7c75318e 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -487,6 +487,16 @@ void bgp_generate_updgrp_packets(struct thread *thread) if (peer->t_routeadv) return; + /* + * Since the following is a do while loop + * let's stop adding to the outq if we are + * already at the limit. + */ + if (peer->obuf->count >= bm->outq_limit) { + bgp_write_proceed_actions(peer); + return; + } + do { enum bgp_af_index index; @@ -609,7 +619,8 @@ void bgp_generate_updgrp_packets(struct thread *thread) bgp_packet_add(peer, s); bpacket_queue_advance_peer(paf); } - } while (s && (++generated < wpq)); + } while (s && (++generated < wpq) && + (peer->obuf->count <= bm->outq_limit)); if (generated) bgp_writes_on(peer); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 4acf4f76aa..878f2f7968 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -17901,9 +17901,12 @@ int bgp_config_write(struct vty *vty) vty_out(vty, "bgp session-dscp %u\n", bm->tcp_dscp >> 2); /* BGP InQ limit */ - if (bm->inq_limit != BM_DEFAULT_INQ_LIMIT) + if (bm->inq_limit != BM_DEFAULT_Q_LIMIT) vty_out(vty, "bgp input-queue-limit %u\n", bm->inq_limit); + if (bm->outq_limit != BM_DEFAULT_Q_LIMIT) + vty_out(vty, "bgp output-queue-limit %u\n", bm->outq_limit); + /* BGP configuration. */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { @@ -18638,11 +18641,37 @@ DEFPY (no_bgp_inq_limit, "Set the BGP Input Queue limit for all peers when message parsing\n" "Input-Queue limit\n") { - bm->inq_limit = BM_DEFAULT_INQ_LIMIT; + bm->inq_limit = BM_DEFAULT_Q_LIMIT; + + return CMD_SUCCESS; +} + +DEFPY (bgp_outq_limit, + bgp_outq_limit_cmd, + "bgp output-queue-limit (1-4294967295)$limit", + BGP_STR + "Set the BGP Output Queue limit for all peers when message parsing\n" + "Output-Queue limit\n") +{ + bm->outq_limit = limit; return CMD_SUCCESS; } +DEFPY (no_bgp_outq_limit, + no_bgp_outq_limit_cmd, + "no bgp output-queue-limit [(1-4294967295)$limit]", + NO_STR + BGP_STR + "Set the BGP Output Queue limit for all peers when message parsing\n" + "Output-Queue limit\n") +{ + bm->outq_limit = BM_DEFAULT_Q_LIMIT; + + return CMD_SUCCESS; +} + + /* Initialization of BGP interface. */ static void bgp_vty_if_init(void) { @@ -18695,6 +18724,8 @@ void bgp_vty_init(void) /* "global bgp inq-limit command */ install_element(CONFIG_NODE, &bgp_inq_limit_cmd); install_element(CONFIG_NODE, &no_bgp_inq_limit_cmd); + install_element(CONFIG_NODE, &bgp_outq_limit_cmd); + install_element(CONFIG_NODE, &no_bgp_outq_limit_cmd); /* "bgp local-mac" hidden commands. */ install_element(CONFIG_NODE, &bgp_local_mac_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9b4aa38d7a..e5bb2b73e4 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7940,7 +7940,8 @@ void bgp_master_init(struct thread_master *master, const int buffer_size, bm->socket_buffer = buffer_size; bm->wait_for_fib = false; bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL; - bm->inq_limit = BM_DEFAULT_INQ_LIMIT; + bm->inq_limit = BM_DEFAULT_Q_LIMIT; + bm->outq_limit = BM_DEFAULT_Q_LIMIT; bgp_mac_init(); /* init the rd id space. diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 8697912314..acf0dbfe9d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -177,8 +177,9 @@ struct bgp_master { /* DSCP value for TCP sessions */ uint8_t tcp_dscp; -#define BM_DEFAULT_INQ_LIMIT 10000 +#define BM_DEFAULT_Q_LIMIT 10000 uint32_t inq_limit; + uint32_t outq_limit; QOBJ_FIELDS; }; diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 7f97491630..c5130c3cfd 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -4065,6 +4065,11 @@ The following command is available in ``config`` mode as well as in the Set the BGP Input Queue limit for all peers when messaging parsing. Increase this only if you have the memory to handle large queues of messages at once. +.. clicmd:: bgp output-queue-limit (1-4294967295) + + Set the BGP Output Queue limit for all peers when messaging parsing. Increase + this only if you have the memory to handle large queues of messages at once. + .. _bgp-displaying-bgp-information: Displaying BGP Information