]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - sysdep/unix/krt.c
Filter: Allow silent filter execution
[thirdparty/bird.git] / sysdep / unix / krt.c
index d8d28c7c32bdb8d9b939722ca3e210d1ac7426fa..526c0cab64a70a96f0f7a5a30f0722260b8351ff 100644 (file)
@@ -77,14 +77,15 @@ krt_io_init(void)
   krt_pool = rp_new(&root_pool, "Kernel Syncer");
   krt_filter_lp = lp_new(krt_pool, 4080);
   init_list(&krt_proto_list);
+  krt_sys_io_init();
 }
 
 /*
  *     Interfaces
  */
 
+struct kif_proto *kif_proto;
 static struct kif_config *kif_cf;
-static struct kif_proto *kif_proto;
 static timer *kif_scan_timer;
 static bird_clock_t kif_last_shot;
 
@@ -416,46 +417,58 @@ again:
       net *n = (net *) f;
       rte *e, **ee, *best, **pbest, *old_best;
 
-      old_best = n->routes;
+      /*
+       * Note that old_best may be NULL even if there was an old best route in
+       * the previous step, because it might be replaced in krt_learn_scan().
+       * But in that case there is a new valid best route.
+       */
+
+      old_best = NULL;
       best = NULL;
       pbest = NULL;
       ee = &n->routes;
       while (e = *ee)
        {
+         if (e->u.krt.best)
+           old_best = e;
+
          if (!e->u.krt.seen)
            {
              *ee = e->next;
              rte_free(e);
              continue;
            }
+
          if (!best || best->u.krt.metric > e->u.krt.metric)
            {
              best = e;
              pbest = ee;
            }
+
          e->u.krt.seen = 0;
+         e->u.krt.best = 0;
          ee = &e->next;
        }
       if (!n->routes)
        {
          DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
          if (old_best)
-           {
-             krt_learn_announce_delete(p, n);
-             n->n.flags &= ~KRF_INSTALLED;
-           }
+           krt_learn_announce_delete(p, n);
+
          FIB_ITERATE_PUT(&fit, f);
          fib_delete(fib, f);
          goto again;
        }
+
+      best->u.krt.best = 1;
       *pbest = best->next;
       best->next = n->routes;
       n->routes = best;
-      if (best != old_best || !(n->n.flags & KRF_INSTALLED) || p->reload)
+
+      if ((best != old_best) || p->reload)
        {
          DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
          krt_learn_announce_update(p, best);
-         n->n.flags |= KRF_INSTALLED;
        }
       else
        DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
@@ -514,31 +527,31 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
   best = n->routes;
   bestp = &n->routes;
   for(gg=&n->routes; g=*gg; gg=&g->next)
+  {
     if (best->u.krt.metric > g->u.krt.metric)
       {
        best = g;
        bestp = gg;
       }
+
+    g->u.krt.best = 0;
+  }
+
   if (best)
     {
+      best->u.krt.best = 1;
       *bestp = best->next;
       best->next = n->routes;
       n->routes = best;
     }
+
   if (best != old_best)
     {
       DBG("krt_learn_async: distributing change\n");
       if (best)
-       {
-         krt_learn_announce_update(p, best);
-         n->n.flags |= KRF_INSTALLED;
-       }
+       krt_learn_announce_update(p, best);
       else
-       {
-         n->routes = NULL;
-         krt_learn_announce_delete(p, n);
-         n->n.flags &= ~KRF_INSTALLED;
-       }
+       krt_learn_announce_delete(p, n);
     }
 }
 
@@ -563,7 +576,7 @@ krt_dump(struct proto *P)
 static void
 krt_dump_attrs(rte *e)
 {
-  debug(" [m=%d,p=%d,t=%d]", e->u.krt.metric, e->u.krt.proto, e->u.krt.type);
+  debug(" [m=%d,p=%d]", e->u.krt.metric, e->u.krt.proto);
 }
 
 #endif
@@ -595,9 +608,13 @@ krt_flush_routes(struct krt_proto *p)
 static struct rte *
 krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
 {
-  struct filter *filter = p->p.main_ahook->out_filter;
+  struct announce_hook *ah = p->p.main_ahook;
+  struct filter *filter = ah->out_filter;
   rte *rt;
 
+  if (p->p.accept_ra_types == RA_MERGED)
+    return rt_export_merged(ah, net, rt_free, tmpa, krt_filter_lp, 1);
+
   rt = net->routes;
   *rt_free = NULL;
 
@@ -615,7 +632,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
   if (filter == FILTER_ACCEPT)
     goto accept;
 
-  if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) > F_ACCEPT)
+  if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT)
     goto reject;
 
 
@@ -892,7 +909,7 @@ krt_scan_timer_start(struct krt_proto *p)
 }
 
 static void
-krt_scan_timer_stop(struct krt_proto *p)
+krt_scan_timer_stop(struct krt_proto *p UNUSED)
 {
   krt_scan_count--;
 
@@ -981,7 +998,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
 }
 
 static int
-krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
+krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
 {
   struct krt_proto *p = (struct krt_proto *) P;
   rte *e = *new;
@@ -1091,11 +1108,13 @@ krt_rte_same(rte *a, rte *b)
 struct krt_config *krt_cf;
 
 static struct proto *
-krt_init(struct proto_config *c)
+krt_init(struct proto_config *C)
 {
-  struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
+  struct krt_proto *p = proto_new(C, sizeof(struct krt_proto));
+  struct krt_config *c = (struct krt_config *) C;
 
-  p->p.accept_ra_types = RA_OPTIMAL;
+  p->p.accept_ra_types = c->merge_paths ? RA_MERGED : RA_OPTIMAL;
+  p->p.merge_limit = c->merge_paths;
   p->p.import_control = krt_import_control;
   p->p.rt_notify = krt_rt_notify;
   p->p.if_notify = krt_if_notify;
@@ -1120,7 +1139,11 @@ krt_start(struct proto *P)
   krt_learn_init(p);
 #endif
 
-  krt_sys_start(p);
+  if (!krt_sys_start(p))
+  {
+    rem_node(&p->krt_node);
+    return PS_START;
+  }
 
   krt_scan_timer_start(p);
 
@@ -1144,8 +1167,10 @@ krt_shutdown(struct proto *P)
   p->ready = 0;
   p->initialized = 0;
 
-  krt_sys_shutdown(p);
+  if (p->p.proto_state == PS_START)
+    return PS_DOWN;
 
+  krt_sys_shutdown(p);
   rem_node(&p->krt_node);
 
   return PS_DOWN;
@@ -1161,7 +1186,8 @@ krt_reconfigure(struct proto *p, struct proto_config *new)
     return 0;
 
   /* persist, graceful restart need not be the same */
-  return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
+  return o->scan_time == n->scan_time && o->learn == n->learn &&
+    o->devroutes == n->devroutes && o->merge_paths == n->merge_paths;
 }
 
 static void