]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Removes phantom protocol from the pipe design.
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 13 Feb 2010 11:26:26 +0000 (12:26 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 13 Feb 2010 11:26:26 +0000 (12:26 +0100)
It seems that by adding one pipe-specific exception to route
announcement code and by adding one argument to rt_notify() callback i
could completely eliminate the need for the phantom protocol instance
and therefore make the code more straightforward. It will also fix some
minor bugs (like ignoring debug flag changes from the command line).

nest/proto-hooks.c
nest/proto.c
nest/protocol.h
nest/rt-table.c
proto/bgp/attrs.c
proto/bgp/bgp.h
proto/ospf/ospf.c
proto/pipe/pipe.c
proto/pipe/pipe.h
proto/rip/rip.c
sysdep/unix/krt.c

index c30b1070f73ae89da8a78879d85ba9ad1762e786..3d19e3fead75f8112f4f3ce32d8d355584a8f81e 100644 (file)
@@ -178,13 +178,14 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
 /**
  * rt_notify - notify instance about routing table change
  * @p: protocol instance
+ * @table: a routing table 
  * @net: a network entry
  * @new: new route for the network
  * @old: old route for the network
  * @attrs: extended attributes associated with the @new entry
  *
  * The rt_notify() hook is called to inform the protocol instance about
- * changes in the routing table it's connected to, that is a route @old
+ * changes in the connected routing table @table, that is a route @old
  * belonging to network @net being replaced by a new route @new with
  * extended attributes @attrs. Either @new or @old or both can be %NULL
  * if the corresponding route doesn't exist.
index a7e4e0c9dfc1650211b6b7b148444a4a8618661a..57c2aa13e33d87d4a6f51179bdcf7defadf58595 100644 (file)
@@ -133,11 +133,6 @@ proto_init_instance(struct proto *p)
   p->attn = ev_new(p->pool);
   p->attn->data = p;
   rt_lock_table(p->table);
-
-#ifdef CONFIG_PIPE
-  if (proto_is_pipe(p))
-    rt_lock_table(pipe_get_peer_table(p));
-#endif
 }
 
 /**
index 876427ab8889e7823831cf3012e70f0c3085078d..82f3766f1a5d5767f6df6eac9be78926cb5a1a57 100644 (file)
@@ -16,6 +16,7 @@
 
 struct iface;
 struct ifa;
+struct rtable;
 struct rte;
 struct neighbor;
 struct rta;
@@ -162,7 +163,7 @@ struct proto {
 
   void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
   void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
-  void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs);
+  void (*rt_notify)(struct proto *, struct rtable *table, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs);
   void (*neigh_notify)(struct neighbor *neigh);
   struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
   void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs);
@@ -339,13 +340,7 @@ struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
  */
 
 #ifdef CONFIG_PIPE
-
-static inline int proto_is_pipe(struct proto *p)
-{ return p->proto == &proto_pipe; }
-
-struct rtable *pipe_get_peer_table(struct proto *p);
-struct proto_stats *pipe_get_peer_stats(struct proto *p);
-
+#include "proto/pipe/pipe.h"
 #endif
 
 
index c9e421e9428f3ffd19e4ccace0ac79c0679d848b..72a1cb0e230b8bb8b55ad2ec61fa7f9d6ad79e0c 100644 (file)
@@ -161,6 +161,7 @@ static inline void
 do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
 {
   struct proto *p = a->proto;
+  struct filter *filter = p->out_filter;
   struct proto_stats *stats = &p->stats;
   rte *new0 = new;
   rte *old0 = old;
@@ -168,6 +169,15 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
 
   int fast_exit_hack = 0;
 
+#ifdef CONFIG_PIPE
+  /* The secondary direction of the pipe */
+  if (proto_is_pipe(p) && (p->table != a->table))
+    {
+      filter = p->in_filter;
+      stats = pipe_get_peer_stats(p);
+    }
+#endif
+
   if (new)
     {
       stats->exp_updates_received++;
@@ -186,8 +196,8 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
        }
       else if (ok)
        rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
-      else if (p->out_filter == FILTER_REJECT ||
-              p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
+      else if (filter == FILTER_REJECT ||
+              filter && f_run(filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
        {
          stats->exp_updates_filtered++;
          drop_reason = "filtered out";
@@ -230,13 +240,13 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
 
   if (old && !refeed)
     {
-      if (p->out_filter == FILTER_REJECT)
+      if (filter == FILTER_REJECT)
        old = NULL;
       else
        {
          ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
          ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
-         if (ok < 0 || (!ok && p->out_filter && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
+         if (ok < 0 || (!ok && filter && f_run(filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
            {
              if (old != old0)
                rte_free(old);
@@ -271,18 +281,18 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
        rte_trace_out(D_ROUTES, p, old, "removed");
     }
   if (!new)
-    p->rt_notify(p, net, NULL, old, NULL);
+    p->rt_notify(p, a->table, net, NULL, old, NULL);
   else if (tmpa)
     {
       ea_list *t = tmpa;
       while (t->next)
        t = t->next;
       t->next = new->attrs->eattrs;
-      p->rt_notify(p, net, new, old, tmpa);
+      p->rt_notify(p, a->table, net, new, old, tmpa);
       t->next = NULL;
     }
   else
-    p->rt_notify(p, net, new, old, new->attrs->eattrs);
+    p->rt_notify(p, a->table, net, new, old, new->attrs->eattrs);
   if (new && new != new0)      /* Discard temporary rte's */
     rte_free(new);
   if (old && old != old0)
index 4cfabf18a0add71dfa95cba7322e2c9ea1411c7a..966798702592dde558223a4a5e9b003fa4420f50 100644 (file)
@@ -772,7 +772,7 @@ bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck)
 }
 
 void
-bgp_rt_notify(struct proto *P, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
+bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
 {
   struct bgp_proto *p = (struct bgp_proto *) P;
   struct bgp_bucket *buck;
index 7f574ed451d5e8d89514a13cf5832180a17c850b..1a291952660f8259f9d757b3eabb84a966e300ba 100644 (file)
@@ -179,7 +179,7 @@ byte *bgp_attach_attr_wa(struct ea_list **to, struct linpool *pool, unsigned att
 struct rta *bgp_decode_attrs(struct bgp_conn *conn, byte *a, unsigned int len, struct linpool *pool, int mandatory);
 int bgp_get_attr(struct eattr *e, byte *buf, int buflen);
 int bgp_rte_better(struct rte *, struct rte *);
-void bgp_rt_notify(struct proto *, struct network *, struct rte *, struct rte *, struct ea_list *);
+void bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs);
 int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *);
 void bgp_attr_init(struct bgp_proto *);
 unsigned int bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains);
index d2ceab25a7040cd01ecf62f41a3214766ab55eb3..26a05d959d895bb12c2ecc1d4085306d66ebf5c6 100644 (file)
@@ -78,7 +78,7 @@
 
 
 static int ospf_reload_routes(struct proto *p);
-static void ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED, ea_list * attrs);
+static void ospf_rt_notify(struct proto *p, struct rtable *table UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs);
 static void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
 static int ospf_rte_better(struct rte *new, struct rte *old);
 static int ospf_rte_same(struct rte *new, struct rte *old);
@@ -484,8 +484,7 @@ ospf_shutdown(struct proto *p)
 }
 
 static void
-ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED,
-              ea_list * attrs)
+ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs)
 {
   struct proto_ospf *po = (struct proto_ospf *) p;
 
index 879135d14d399aaf2861df07c0bfe9c44aba1bc7..943d3a0ea5977c727e18dd97fb6f3fb6e060a69f 100644 (file)
 #include "pipe.h"
 
 static void
-pipe_send(struct pipe_proto *p, rtable *src_table, rtable *dest, net *n, rte *new, rte *old, ea_list *attrs)
+pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs)
 {
+  struct pipe_proto *p = (struct pipe_proto *) P;
+  rtable *dest = (src_table == P->table) ? p->peer : P->table; /* The other side of the pipe */
   struct proto *src;
+
   net *nn;
   rte *e;
   rta a;
@@ -85,30 +88,12 @@ pipe_send(struct pipe_proto *p, rtable *src_table, rtable *dest, net *n, rte *ne
   src_table->pipe_busy = 0;
 }
 
-static void
-pipe_rt_notify_pri(struct proto *P, net *net, rte *new, rte *old, ea_list *attrs)
-{
-  struct pipe_proto *p = (struct pipe_proto *) P;
-
-  DBG("PIPE %c> %I/%d\n", (new ? '+' : '-'), net->n.prefix, net->n.pxlen);
-  pipe_send(p, p->p.table, p->peer, net, new, old, attrs);
-}
-
-static void
-pipe_rt_notify_sec(struct proto *P, net *net, rte *new, rte *old, ea_list *attrs)
-{
-  struct pipe_proto *p = ((struct pipe_proto *) P)->phantom;
-
-  DBG("PIPE %c< %I/%d\n", (new ? '+' : '-'), net->n.prefix, net->n.pxlen);
-  pipe_send(p, p->peer, p->p.table, net, new, old, attrs);
-}
-
 static int
 pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
 {
   struct proto *pp = (*ee)->sender;
 
-  if (pp == P || pp == &((struct pipe_proto *) P)->phantom->p)
+  if (pp == P)
     return -1; /* Avoid local loops automatically */
   return 0;
 }
@@ -130,49 +115,16 @@ static int
 pipe_start(struct proto *P)
 {
   struct pipe_proto *p = (struct pipe_proto *) P;
-  struct pipe_proto *ph;
   struct announce_hook *a;
 
-  /*
-   *  Create a phantom protocol which will represent the remote
-   *  end of the pipe (we need to do this in order to get different
-   *  filters and announce functions and it unfortunately involves
-   *  a couple of magic trickery).
-   *
-   *  The phantom protocol is used ONLY in announce hooks and
-   *  therefore in do_rte_announce() function.
-   */
-  ph = mb_alloc(P->pool, sizeof(struct pipe_proto));
-  memcpy(ph, p, sizeof(struct pipe_proto));
-  p->phantom = ph;
-  ph->phantom = p;
-  ph->p.accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
-  ph->p.rt_notify = pipe_rt_notify_sec;
-  ph->p.proto_state = PS_UP;
-  ph->p.core_state = ph->p.core_goal = FS_HAPPY;
+  /* Clean up the secondary stats */
+  bzero(&p->peer_stats, sizeof(struct proto_stats));
 
-  /*
-   *  Routes should be filtered in the do_rte_announce() (export
-   *  filter for protocols). Reverse direction is handled by putting
-   *  specified import filter to out_filter field of the phantom
-   *  protocol.
-   *
-   *  in_filter fields are not important, there is an exception in
-   *  rte_update() to ignore it for pipes. We cannot just set
-   *  P->in_filter to FILTER_ACCEPT, because that would break other
-   *  things (reconfiguration, show-protocols command).
-   */
-  ph->p.in_filter = FILTER_ACCEPT;
-  ph->p.out_filter = P->in_filter;
+  /* Lock the peer table, unlock is handled in proto_fell_down() */
+  rt_lock_table(p->peer);
 
-  /*
-   *  Connect the phantom protocol to the peer routing table, but
-   *  keep it in the list of connections of the primary protocol,
-   *  so that it gets disconnected at the right time and we also
-   *  get all routes from both sides during the feeding phase.
-   */
+  /* Connect the protocol also to the peer routing table. */
   a = proto_add_announce_hook(P, p->peer);
-  a->proto = &ph->p;
 
   return PS_UP;
 }
@@ -187,9 +139,10 @@ pipe_init(struct proto_config *C)
   p->peer = c->peer->table;
   p->mode = c->mode;
   P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
-  P->rt_notify = pipe_rt_notify_pri;
+  P->rt_notify = pipe_rt_notify;
   P->import_control = pipe_import_control;
   P->reload_routes = pipe_reload_routes;
+
   return P;
 }
 
@@ -222,24 +175,9 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
   if ((o->peer->table != n->peer->table) || (o->mode != n->mode))
     return 0;
 
-  /* Update also the filter in the phantom protocol */
-  p->phantom->p.out_filter = new->in_filter;
   return 1;
 }
 
-struct rtable *
-pipe_get_peer_table(struct proto *P)
-{
-  struct pipe_proto *p = (struct pipe_proto *) P;
-  return p->peer;
-}
-
-struct proto_stats *
-pipe_get_peer_stats(struct proto *P)
-{
-  struct pipe_proto *p = (struct pipe_proto *) P;
-  return &p->phantom->p.stats;
-}
 
 struct protocol proto_pipe = {
   name:                "Pipe",
index 368ba41ba63b814ec2d1f63b5948e568f464f1dd..fbd2129153c72e21e83a0d4948966a17f6ea512c 100644 (file)
@@ -21,8 +21,20 @@ struct pipe_config {
 struct pipe_proto {
   struct proto p;
   struct rtable *peer;
+  struct proto_stats peer_stats;       /* Statistics for the direction peer->primary */
   int mode;                            /* PIPE_OPAQUE or PIPE_TRANSPARENT */
-  struct pipe_proto *phantom;
 };
 
+
+extern struct protocol proto_pipe;
+
+static inline int proto_is_pipe(struct proto *p)
+{ return p->proto == &proto_pipe; }
+
+static inline struct rtable * pipe_get_peer_table(struct proto *P)
+{ return ((struct pipe_proto *) P)->peer; }
+
+static inline struct proto_stats * pipe_get_peer_stats(struct proto *P)
+{ return &((struct pipe_proto *) P)->peer_stats; }
+
 #endif
index f9a160e63c1cb5faf46d58338f1d7c36c7570c54..d69d643208ed92735042c592d8ecda06a4fd3c6b 100644 (file)
@@ -864,7 +864,8 @@ rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
  * own), so store it into our data structures. 
  */
 static void
-rip_rt_notify(struct proto *p, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs)
+rip_rt_notify(struct proto *p, struct rtable *table UNUSED, struct network *net,
+             struct rte *new, struct rte *old, struct ea_list *attrs)
 {
   CHK_MAGIC;
 
index 488447b78cbdaf129be2063a8482e126882499d8..6d94cada2a810c2ed03fac98dca02ed603557415 100644 (file)
@@ -742,7 +742,8 @@ krt_scan(timer *t UNUSED)
  */
 
 static void
-krt_notify(struct proto *P, net *net, rte *new, rte *old, struct ea_list *attrs UNUSED)
+krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
+          rte *new, rte *old, struct ea_list *attrs UNUSED)
 {
   struct krt_proto *p = (struct krt_proto *) P;