]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: respecting table cork
authorMaria Matejka <mq@ucw.cz>
Tue, 2 Aug 2022 10:54:11 +0000 (12:54 +0200)
committerMaria Matejka <mq@ucw.cz>
Tue, 2 Aug 2022 15:34:38 +0000 (17:34 +0200)
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 3b624a49f8b2cfc0ea6edcbe747bf2ab8a54d7d0..33849b0bbe8214acf527091d5d72ee1386725617 100644 (file)
@@ -376,6 +376,7 @@ bgp_close_conn(struct bgp_conn *conn)
   conn->keepalive_timer = NULL;
   rfree(conn->hold_timer);
   conn->hold_timer = NULL;
+
   rfree(conn->tx_ev);
   conn->tx_ev = NULL;
   rfree(conn->sk);
@@ -514,6 +515,7 @@ void
 bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len)
 {
   proto_notify_state(&p->p, PS_STOP);
+  p->uncork_ev->data = NULL;
   bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
   bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
   ev_schedule(p->event);
@@ -1576,6 +1578,8 @@ bgp_start(struct proto *P)
   p->last_rx_update = 0;
 
   p->event = ev_new_init(p->p.pool, bgp_decision, p);
+  p->uncork_ev = ev_new_init(p->p.pool, bgp_uncork, p);
+
   p->startup_timer = tm_new_init(p->p.pool, bgp_startup_timeout, p, 0, 0);
   p->gr_timer = tm_new_init(p->p.pool, bgp_graceful_restart_timeout, p, 0, 0);
 
index 2e7615eaa25eeb9f83f3fc44d821d68ea409f00c..469f0cb96f5e05044a9cbf9329a929ec0bd17a70 100644 (file)
@@ -319,6 +319,7 @@ struct bgp_proto {
   struct bgp_socket *sock;             /* Shared listening socket */
   struct bfd_request *bfd_req;         /* BFD request, if BFD is used */
   struct birdsock *postponed_sk;       /* Postponed incoming socket for dynamic BGP */
+  event *uncork_ev;                    /* Uncork event in case of congestion */
   struct bgp_stats stats;              /* BGP statistics */
   btime last_established;              /* Last time of enter/leave of established state */
   btime last_rx_update;                        /* Last time of RX update */
@@ -610,6 +611,7 @@ 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_uncork(void *vp);
 const char * bgp_error_dsc(unsigned code, unsigned subcode);
 void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
 
index 4d4ae3eb95d71845e8542ad81b1c5839c3fb40e6..de976588f419162b83245d94f1af3a46a2e9c5d1 100644 (file)
@@ -3175,6 +3175,21 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
   }
 }
 
+void
+bgp_uncork(void *vp)
+{
+  struct bgp_proto *p = vp;
+
+  if (p && p->conn && (p->conn->state == BS_ESTABLISHED) && !p->conn->sk->rx_hook)
+  {
+    struct birdsock *sk = p->conn->sk;
+    ASSERT_DIE(sk->rpos > sk->rbuf);
+    sk->rx_hook = bgp_rx;
+    bgp_rx(sk, sk->rpos - sk->rbuf);
+    BGP_TRACE(D_PACKETS, "Uncorked");
+  }
+}
+
 /**
  * bgp_rx - handle received data
  * @sk: socket
@@ -3189,6 +3204,7 @@ int
 bgp_rx(sock *sk, uint size)
 {
   struct bgp_conn *conn = sk->data;
+  struct bgp_proto *p = conn->bgp;
   byte *pkt_start = sk->rbuf;
   byte *end = pkt_start + size;
   uint i, len;
@@ -3198,6 +3214,12 @@ bgp_rx(sock *sk, uint size)
     {
       if ((conn->state == BS_CLOSE) || (conn->sk != sk))
        return 0;
+      if ((conn->state == BS_ESTABLISHED) && rt_cork_check(conn->bgp->uncork_ev))
+      {
+       sk->rx_hook = NULL;
+       BGP_TRACE(D_PACKETS, "Corked");
+       return 0;
+      }
       for(i=0; i<16; i++)
        if (pkt_start[i] != 0xff)
          {