]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Limit peer output queue length like input queue length
authorDonald Sharp <sharpd@nvidia.com>
Thu, 19 Jan 2023 16:43:12 +0000 (11:43 -0500)
committerDonald Sharp <sharpd@nvidia.com>
Thu, 19 Jan 2023 16:48:01 +0000 (11:48 -0500)
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 <sharpd@nvidia.com>
bgpd/bgp_packet.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h
doc/user/bgp.rst

index 5d4cf2a6aaadb7a64cc14eae7d289f60351a0a8b..9e7c75318e8a3384e504cbf2026fa4af1a278b57 100644 (file)
@@ -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);
index 4acf4f76aa55002bb52bfca8680477803121464b..878f2f796850a1b4d2f2d3eb432c2d3b247647f9 100644 (file)
@@ -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);
index 9b4aa38d7af89a5b2c7df306ec9d8ad985580347..e5bb2b73e4cb3e315412611a74167a652fec94d1 100644 (file)
@@ -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.
index 86979123146fa64519a300fb744bb6383c62345b..acf0dbfe9d5dd977f6beb1f12c8fc4ef8489606f 100644 (file)
@@ -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;
 };
index 7f97491630a15f278ab619be47ff66a1c6cde1db..c5130c3cfd2da944bb9eadbf2d555c23a0f25d9f 100644 (file)
@@ -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