]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements import route limits.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 4 Jun 2009 11:31:09 +0000 (13:31 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 4 Jun 2009 11:31:09 +0000 (13:31 +0200)
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c

index b42ea302c2d031b1703c7d45985bc4943cecd20f..eae835ab387aba5a25c54c56d88b16066a3899bb 100644 (file)
@@ -212,7 +212,7 @@ bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned co
   struct bgp_config *cf = p->cf;
 
   /* Don't handle cease messages as errors */
-  if (code == 6 && !subcode)
+  if (code == 6 && !subcode && p->last_error_class != BE_AUTO_DOWN)
     {
       p->startup_delay = 0;
       return;
@@ -483,6 +483,21 @@ bgp_active(struct bgp_proto *p, int delay)
   bgp_start_timer(conn->connect_retry_timer, delay);
 }
 
+int
+bgp_apply_limits(struct bgp_proto *p)
+{
+  if (p->cf->route_limit && (p->p.stats.imp_routes > p->cf->route_limit))
+    {
+      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);
+      return -1;
+    }
+
+  return 0;
+}
+
+
 /**
  * bgp_connect - initiate an outgoing connection
  * @p: BGP instance
@@ -848,8 +863,9 @@ bgp_check(struct bgp_config *c)
 }
 
 static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
-static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown", ""};
+static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown", ""};
 static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed" };
+static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
 
 
 static void
@@ -873,6 +889,9 @@ bgp_get_status(struct proto *P, byte *buf)
     case BE_BGP_TX:
       err2 = bgp_error_dsc(errbuf, p->last_error_code >> 16, p->last_error_code & 0xFF);
       break;
+    case BE_AUTO_DOWN:
+      err2 = bgp_auto_errors[p->last_error_code];
+      break;
     }
 
   if (P->proto_state == PS_DOWN)
index 8477f9e5f7d537db2354202e9719200a44d6e33d..1f29d59d0dc7e9753cc030f917f6c7e42d8ef5a5 100644 (file)
@@ -31,6 +31,7 @@ struct bgp_config {
   int rr_client;                       /* Whether neighbor is RR client of me */
   int rs_client;                       /* Whether neighbor is RS client of me */
   int advertise_ipv4;                  /* Whether we should add IPv4 capability advertisement to OPEN message */
+  u32 route_limit;                     /* Number of routes that may be imported, 0 means disable limit */
   unsigned connect_retry_time;
   unsigned hold_time, initial_hold_time;
   unsigned keepalive_time;
@@ -132,6 +133,7 @@ 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);
 
 
 #ifdef LOCAL_DEBUG
@@ -256,8 +258,11 @@ void bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subco
 
 #define BEM_NEIGHBOR_LOST      1
 #define BEM_INVALID_NEXT_HOP   2
-#define BEM_INVALID_MD5                3       /* MD5 authentication kernel request failed (possibly not supported */
+#define BEM_INVALID_MD5                3       /* MD5 authentication kernel request failed (possibly not supported) */
 
+/* Automatic shutdown error codes */
+
+#define BEA_ROUTE_LIMIT_EXCEEDED 1
 
 /* Well-known communities */
 
index c5ea87dec0086dabb1e5225399939f0bbd8f4d31..872fb27144b722be71863379442dedf331b51b7a 100644 (file)
@@ -22,7 +22,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
        BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP,
        BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
        PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
-       CAPABILITIES)
+       CAPABILITIES, LIMIT)
 
 CF_GRAMMAR
 
@@ -77,6 +77,7 @@ bgp_proto:
  | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
  | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
  | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
+ | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
  ;
 
 CF_ADDTO(dynamic_attr, BGP_PATH
index d5397f5f772dfb8bc52ce9579f2ed3aaf93ce0b0..f358012af3aa665becd1316c43fdb29cd4b37293 100644 (file)
@@ -725,13 +725,19 @@ bgp_do_rx_update(struct bgp_conn *conn,
          e->net = n;
          e->pflags = 0;
          rte_update(p->p.table, n, &p->p, &p->p, e);
+         if (bgp_apply_limits(p) < 0)
+           goto bad2;
        }
+      rta_free(a);
     }
-bad:
+
+  return;
+
+ bad:
+  bgp_error(conn, 3, err, NULL, 0);
+ bad2:
   if (a)
     rta_free(a);
-  if (err)
-    bgp_error(conn, 3, err, NULL, 0);
   return;
 }
 
@@ -825,6 +831,8 @@ bgp_do_rx_update(struct bgp_conn *conn,
              e->net = n;
              e->pflags = 0;
              rte_update(p->p.table, n, &p->p, &p->p, e);
+             if (bgp_apply_limits(p) < 0)
+               goto bad2;
            }
          rta_free(a);
        }
@@ -832,8 +840,9 @@ bgp_do_rx_update(struct bgp_conn *conn,
 
   return;
 
-bad:
+ bad:
   bgp_error(conn, 3, 9, start, len0);
+ bad2:
   if (a)
     rta_free(a);
   return;