]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Minor BGP changes related to error wait time.
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 6 Jun 2009 22:38:38 +0000 (00:38 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 6 Jun 2009 22:38:38 +0000 (00:38 +0200)
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 80116c5b4afcc6f667f5236d76b322ade3aba942..3b597dcfe2a0fff8966c30610ba80b9342284c51 100644 (file)
@@ -74,7 +74,6 @@ static int bgp_counter;                       /* Number of protocol instances using the listening so
 static void bgp_close(struct bgp_proto *p, int apply_md5);
 static void bgp_connect(struct bgp_proto *p);
 static void bgp_active(struct bgp_proto *p);
-static void bgp_stop(struct bgp_proto *p);
 static sock *bgp_setup_listen_sk(void);
 
 
@@ -221,9 +220,6 @@ bgp_close_conn(struct bgp_conn *conn)
 /**
  * bgp_update_startup_delay - update a startup delay
  * @p: BGP instance
- * @conn: related BGP connection
- * @code: BGP error code
- * @subcode: BGP error subcode
  *
  * This function updates a startup delay that is used to postpone next BGP connect.
  * It also handles disable_after_error and might stop BGP instance when error
@@ -232,26 +228,11 @@ bgp_close_conn(struct bgp_conn *conn)
  * It should be called when BGP protocol error happened.
  */
 void
-bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned code, unsigned subcode)
+bgp_update_startup_delay(struct bgp_proto *p)
 {
   struct bgp_config *cf = p->cf;
 
-  /* Don't handle cease messages as errors */
-  if (code == 6 && !subcode && p->last_error_class != BE_AUTO_DOWN)
-    {
-      p->startup_delay = 0;
-      return;
-    }
-
-  /* During start, we only consider errors on outgoing connection, because
-     otherwise delay timer for outgoing connection is already running and
-     we could increase delay time two times (or more) per one attempt to
-     connect.
-  */
-  if ((p->p.proto_state == PS_START) && (conn != &p->outgoing_conn))
-    return;
-
-  DBG("BGP: Updating startup delay %d %d\n", code, subcode);
+  DBG("BGP: Updating startup delay\n");
 
   if (p->last_proto_error && ((now - p->last_proto_error) >= cf->error_amnesia_time))
     p->startup_delay = 0;
@@ -262,25 +243,17 @@ bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned co
     {
       p->startup_delay = 0;
       p->p.disabled = 1;
-      if (p->p.proto_state == PS_START)
-       bgp_stop(p);
-
       return;
     }
 
-
   if (!p->startup_delay)
     p->startup_delay = cf->error_delay_time_min;
   else
-    {
-      p->startup_delay *= 2;
-      if (p->startup_delay > cf->error_delay_time_max)
-       p->startup_delay = cf->error_delay_time_max;
-    }
+    p->startup_delay = MIN(2 * p->startup_delay, cf->error_delay_time_max);
 }
 
 static void
-bgp_graceful_close_conn(struct bgp_conn *conn)
+bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
 {
   switch (conn->state)
     {
@@ -294,7 +267,7 @@ bgp_graceful_close_conn(struct bgp_conn *conn)
     case BS_OPENSENT:
     case BS_OPENCONFIRM:
     case BS_ESTABLISHED:
-      bgp_error(conn, 6, 0, NULL, 0);
+      bgp_error(conn, 6, subcode, NULL, 0);
       return;
     default:
       bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
@@ -307,7 +280,7 @@ bgp_down(struct bgp_proto *p)
   if (p->start_state > BSS_PREPARE)
     bgp_close(p, 1);
 
-  DBG("BGP: DOWN\n");
+  BGP_TRACE(D_EVENTS, "Down");
   proto_notify_state(&p->p, PS_DOWN);
 }
 
@@ -327,12 +300,12 @@ bgp_decision(void *vp)
     bgp_down(p);
 }
 
-static void
-bgp_stop(struct bgp_proto *p)
+void
+bgp_stop(struct bgp_proto *p, unsigned subcode)
 {
   proto_notify_state(&p->p, PS_STOP);
-  bgp_graceful_close_conn(&p->outgoing_conn);
-  bgp_graceful_close_conn(&p->incoming_conn);
+  bgp_graceful_close_conn(&p->outgoing_conn, subcode);
+  bgp_graceful_close_conn(&p->incoming_conn, subcode);
   ev_schedule(p->event);
 }
 
@@ -359,7 +332,7 @@ bgp_conn_leave_established_state(struct bgp_proto *p)
   p->conn = NULL;
 
   if (p->p.proto_state == PS_UP)
-    bgp_stop(p);
+    bgp_stop(p, 0);
 }
 
 void
@@ -501,7 +474,7 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
 static void
 bgp_active(struct bgp_proto *p)
 {
-  int delay = MIN(1, p->cf->start_delay_time);
+  int delay = MAX(1, p->cf->start_delay_time);
   struct bgp_conn *conn = &p->outgoing_conn;
 
   BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
@@ -517,7 +490,8 @@ bgp_apply_limits(struct bgp_proto *p)
     {
       log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
       bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
-      bgp_stop(p);
+      bgp_update_startup_delay(p);
+      bgp_stop(p, 1); // Errcode 6, 1 - max number of prefixes reached
       return -1;
     }
 
@@ -684,7 +658,7 @@ bgp_neigh_notify(neighbor *n)
        {
          BGP_TRACE(D_EVENTS, "Neighbor lost");
          bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
-         bgp_stop(p);
+         bgp_stop(p, 0);
        }
     }
 }
@@ -772,11 +746,23 @@ static int
 bgp_shutdown(struct proto *P)
 {
   struct bgp_proto *p = (struct bgp_proto *) P;
+  unsigned subcode;
 
   BGP_TRACE(D_EVENTS, "Shutdown requested");
   bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
+
+  if (P->reconfiguring)
+    {
+      if (P->cf_new)
+       subcode = 6; // Errcode 6, 6 - other configuration change
+      else
+       subcode = 3; // Errcode 6, 3 - peer de-configured
+    }
+  else
+    subcode = 2; // Errcode 6, 2 - administrative shutdown
+
   p->startup_delay = 0;
-  bgp_stop(p);
+  bgp_stop(p, subcode);
 
   return p->p.proto_state;
 }
@@ -815,12 +801,13 @@ bgp_init(struct proto_config *C)
 void
 bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len)
 {
+  struct bgp_proto *p = c->bgp;
+
   if (c->state == BS_CLOSE)
     return;
 
-  bgp_log_error(c->bgp, "Error", code, subcode, data, (len > 0) ? len : -len);
-  bgp_store_error(c->bgp, c, BE_BGP_TX, (code << 16) | subcode);
-  bgp_update_startup_delay(c->bgp, c, code, subcode);
+  bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, (len > 0) ? len : -len);
+  bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode);
   bgp_conn_enter_close_state(c);
 
   c->notify_code = code;
@@ -828,6 +815,12 @@ bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int l
   c->notify_data = data;
   c->notify_size = (len > 0) ? len : 0;
   bgp_schedule_packet(c, PKT_NOTIFICATION);
+
+  if (code != 6)
+    {
+      bgp_update_startup_delay(p);
+      bgp_stop(p, 0);
+    }
 }
 
 /**
index 15c7cf0a5f11fb32cd68b2dc703a9f0fe52723d9..9bbdab8efa3b9f3f22f35014b9d219aadf685124 100644 (file)
@@ -129,12 +129,14 @@ void bgp_start_timer(struct timer *t, int value);
 void bgp_check(struct bgp_config *c);
 void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
 void bgp_close_conn(struct bgp_conn *c);
-void bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned code, unsigned subcode);
+void bgp_update_startup_delay(struct bgp_proto *p);
 void bgp_conn_enter_established_state(struct bgp_conn *conn);
 void bgp_conn_enter_close_state(struct bgp_conn *conn);
 void bgp_conn_enter_idle_state(struct bgp_conn *conn);
 void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
 int bgp_apply_limits(struct bgp_proto *p);
+void bgp_stop(struct bgp_proto *p, unsigned subcode);
+
 
 
 #ifdef LOCAL_DEBUG
@@ -184,7 +186,7 @@ void bgp_kick_tx(void *vconn);
 void bgp_tx(struct birdsock *sk);
 int bgp_rx(struct birdsock *sk, int size);
 const byte * bgp_error_dsc(byte *buff, unsigned code, unsigned subcode);
-void bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
+void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len);
 
 /* Packet types */
 
index f358012af3aa665becd1316c43fdb29cd4b37293..ae4906eec338b8b3df1035ad6c76b3a1eeb1d8de 100644 (file)
@@ -619,14 +619,14 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
        {
          /* Should close the other connection */
          BGP_TRACE(D_EVENTS, "Connection collision, giving up the other connection");
-         bgp_error(other, 6, 0, NULL, 0);
+         bgp_error(other, 6, 7, NULL, 0);
          break;
        }
       /* Fall thru */
     case BS_ESTABLISHED:
       /* Should close this connection */
       BGP_TRACE(D_EVENTS, "Connection collision, giving up this connection");
-      bgp_error(conn, 6, 0, NULL, 0);
+      bgp_error(conn, 6, 7, NULL, 0);
       return;
     default:
       bug("bgp_rx_open: Unknown state");
@@ -957,14 +957,15 @@ bgp_error_dsc(byte *buff, unsigned code, unsigned subcode)
 }
 
 void
-bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
+bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
 {
   const byte *name;
   byte namebuf[32];
   byte *t, argbuf[36];
   unsigned i;
 
-  if (code == 6 && !subcode)           /* Don't report Cease messages */
+  /* Don't report Cease messages generated by myself */
+  if (code == 6 && class == BE_BGP_TX)
     return;
 
   name = bgp_error_dsc(namebuf, code, subcode);
@@ -994,10 +995,10 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
 
   unsigned code = pkt[19];
   unsigned subcode = pkt[20];
-  int delay = 1;
+  int err = (code != 6);
 
-  bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
-  bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
+  bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21);
+  bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode);
 
 #ifndef IPV6
   if ((code == 2) && ((subcode == 4) || (subcode == 7))
@@ -1014,14 +1015,19 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
     {
       /* We try connect without capabilities */
       log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name);
-      conn->bgp->start_state = BSS_CONNECT_NOCAP;
-      delay = 0;
+      p->start_state = BSS_CONNECT_NOCAP;
+      err = 0;
     }
 #endif
 
-  if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
   bgp_conn_enter_close_state(conn);
   bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
+
+  if (err) 
+    {
+      bgp_update_startup_delay(p);
+      bgp_stop(p, 0);
+    }
 }
 
 static void