]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixes in generalized import limits.
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 21 Apr 2012 19:05:36 +0000 (21:05 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 21 Apr 2012 19:05:36 +0000 (21:05 +0200)
nest/proto.c
nest/protocol.h
nest/rt-table.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/pipe/pipe.c

index 418a7a61cb88e5fae8e901eda00faee50e3362a6..cf81573fdc64cafb2c84b605b570490c92378160 100644 (file)
@@ -785,7 +785,9 @@ proto_schedule_feed(struct proto *p, int initial)
       p->main_ahook->in_filter = p->cf->in_filter;
       p->main_ahook->out_filter = p->cf->out_filter;
       p->main_ahook->in_limit = p->cf->in_limit;
+      proto_reset_limit(p->main_ahook->in_limit);
       // p->main_ahook->out_limit = p->cf->out_limit;
+      // proto_reset_limit(p->main_ahook->out_limit);
     }
 
   proto_relink(p);
@@ -953,43 +955,42 @@ proto_limit_name(struct proto_limit *l)
  * proto_notify_limit: notify about limit hit and take appropriate action
  * @ah: announce hook
  * @l: limit being hit
+ * @rt_count: the number of routes 
  *
  * The function is called by the route processing core when limit @l
  * is breached. It activates the limit and tooks appropriate action
- * according to @l->action. It also says what should be done with the
- * route that breached the limit.
- *
- * Returns 1 if the route should be freed, 0 otherwise.
+ * according to @l->action.
  */
-int
-proto_notify_limit(struct announce_hook *ah, struct proto_limit *l)
+void
+proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
 {
   struct proto *p = ah->proto;
   int dir = (ah->in_limit == l);
 
-  if (l->active)
-    return (l->action != PLA_WARN);
+  if (l->state == PLS_BLOCKED)
+    return;
 
-  l->active = 1;
-  log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
-      p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
+  if (rt_count == l->limit)
+    log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
+       p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
 
   switch (l->action)
     {
     case PLA_WARN:
-      return 0;
+      l->state = PLS_ACTIVE;
+      break;
 
     case PLA_BLOCK:
-      return 1;
+      l->state = PLS_BLOCKED;
+      break;
 
     case PLA_RESTART:
     case PLA_DISABLE:
+      l->state = PLS_BLOCKED;
       proto_schedule_down(p, l->action == PLA_RESTART,
                          dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
-      return 1;
+      break;
     }
-
-  return 0;
 }
 
 /**
@@ -1101,9 +1102,11 @@ proto_show_stats(struct proto_stats *s)
 void
 proto_show_limit(struct proto_limit *l, const char *dsc)
 {
-  if (l)
-    cli_msg(-1006, "  %16s%d, action: %s%s", dsc, l->limit,
-           proto_limit_name(l), l->active ? " [HIT]" : "");
+  if (!l)
+    return;
+
+  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
+  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
 }
 
 void
@@ -1233,8 +1236,8 @@ proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
        * Should be done before reload_routes() hook?
        * Perhaps, but these hooks work asynchronously.
        */
-      if (!p->proto->multitable && p->main_ahook->in_limit)
-       p->main_ahook->in_limit->active = 0;
+      if (!p->proto->multitable)
+       proto_reset_limit(p->main_ahook->in_limit);
     }
 
   /* re-exporting routes */
index 3dd7cf2fffc5ec3e18bc74eca39e93ff43ddd954..d8442acb5c59c47947c22614b4bd2ff615a70ecd 100644 (file)
@@ -375,13 +375,24 @@ extern struct proto_config *cf_dev_proto;
 #define PLA_RESTART    4       /* Force protocol restart */
 #define PLA_DISABLE    5       /* Shutdown and disable protocol */
 
+#define PLS_INITIAL    0       /* Initial limit state after protocol start */
+#define PLS_ACTIVE     1       /* Limit was hit */
+#define PLS_BLOCKED    2       /* Limit is active and blocking new routes */
+
 struct proto_limit {
   u32 limit;                   /* Maximum number of prefixes */
   byte action;                 /* Action to take (PLA_*) */
-  byte active;                 /* Limit is active */
+  byte state;                  /* State of limit (PLS_*) */
 };
 
-int proto_notify_limit(struct announce_hook *ah, struct proto_limit *l);
+void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count);
+
+static inline void proto_reset_limit(struct proto_limit *l)
+{
+  if (l)
+    l->state = PLS_INITIAL;
+}
+
  
 /*
  *     Route Announcement Hook
index 6a28fd43dff87a33d12dd9d52a33da519454116b..6d82e1d3769e3336b84ea2a7fba4c810628a3567 100644 (file)
@@ -485,12 +485,18 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
     }
 
   struct proto_limit *l = ah->in_limit;
-  if (l && !old && new && (stats->imp_routes >= l->limit) && proto_notify_limit(ah, l))
+  if (l && !old && new)
     {
-      stats->imp_updates_ignored++;
-      rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
-      rte_free_quick(new);
-      return;
+      if (stats->imp_routes >= l->limit)
+       proto_notify_limit(ah, l, stats->imp_routes);
+
+      if (l->state == PLS_BLOCKED)
+       {
+         stats->imp_updates_ignored++;
+         rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
+         rte_free_quick(new);
+         return;
+       }
     }
 
   if (new)
index cf743dff01ced3160f8706a702f1b4dedc324ded..95dbe47706546da52f67c115f4694887f54a99da 100644 (file)
@@ -1165,9 +1165,9 @@ bgp_show_proto_info(struct proto *P)
              p->rs_client ? " route-server" : "",
              p->as4_session ? " AS4" : "");
       cli_msg(-1006, "    Source address:   %I", p->source_addr);
-      if (p->cf->route_limit)
+      if (P->cf->in_limit)
        cli_msg(-1006, "    Route limit:      %d/%d",
-               p->p.stats.imp_routes, p->cf->route_limit);
+               p->p.stats.imp_routes, P->cf->in_limit->limit);
       cli_msg(-1006, "    Hold timer:       %d/%d",
              tm_remains(c->hold_timer), c->hold_time);
       cli_msg(-1006, "    Keepalive timer:  %d/%d",
index aa2db4b093b51fa2ab813ad5e8e6adb90da80708..1c16f4853591c2f1b4fcb2ed0f06201f3f299bed 100644 (file)
@@ -40,7 +40,6 @@ 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 */
   int passive;                         /* Do not initiate outgoing connection */
   int interpret_communities;           /* Hardwired handling of well-known communities */
   unsigned connect_retry_time;
index a5fcc6f65ecf2ac8c53f4b5e1094c9af730e44a5..41bac474b9c99d76fb970757fa745a66255c4d04 100644 (file)
@@ -127,10 +127,8 @@ pipe_reload_routes(struct proto *P)
    */
   proto_request_feeding(P);
 
-  if (P->main_ahook->in_limit)
-    P->main_ahook->in_limit->active = 0;
-  if (p->peer_ahook->in_limit)
-    p->peer_ahook->in_limit->active = 0;
+  proto_reset_limit(P->main_ahook->in_limit);
+  proto_reset_limit(p->peer_ahook->in_limit);
 
   return 1;
 }
@@ -168,10 +166,12 @@ pipe_start(struct proto *P)
   P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
   P->main_ahook->out_filter = cf->c.out_filter;
   P->main_ahook->in_limit = cf->c.in_limit;
+  proto_reset_limit(P->main_ahook->in_limit);
 
   p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
   p->peer_ahook->out_filter = cf->c.in_filter;
   p->peer_ahook->in_limit = cf->out_limit;
+  proto_reset_limit(p->peer_ahook->in_limit);
 
   return PS_UP;
 }