]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixes a tricky bug in the pipe protocol.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 11 Feb 2010 21:27:06 +0000 (22:27 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 11 Feb 2010 21:27:06 +0000 (22:27 +0100)
When uncofiguring the pipe and the peer table, the peer table was
unlocked when pipe protocol state changed to down/flushing and not to
down/hungry. This leads to the removal of the peer table before
the routes from the pipe were flushed.

The fix leads to adding some pipe-specific hacks to the nest,
but this seems inevitable.

nest/proto.c
nest/protocol.h
nest/rt-table.c
proto/pipe/pipe.c

index 870edddd8a7f61ff3a2f63391e1f35fb0b70873a..c6b7e63c90ddc3f7452f795ceb78ec921031db29 100644 (file)
@@ -133,6 +133,11 @@ 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
 }
 
 /**
@@ -583,6 +588,12 @@ proto_fell_down(struct proto *p)
 
   bzero(&p->stats, sizeof(struct proto_stats));
   rt_unlock_table(p->table);
+
+#ifdef CONFIG_PIPE
+  if (proto_is_pipe(p))
+    rt_unlock_table(pipe_get_peer_table(p));
+#endif
+
   proto_rethink_goal(p);
 }
 
index 5a69b33b48f28b1dc152791df24a5af19df88332..99d8dc80e63f46dcde56fb114b3f9aa22bece181 100644 (file)
@@ -334,4 +334,18 @@ struct announce_hook {
 
 struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
 
+/*
+ *     Some pipe-specific nest hacks
+ */
+
+#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);
+
+#endif
+
+
 #endif
index 413675c9c17e94642ad0fcad627fa3029201ff24..fee571897478af94c3358ade3424137e0217571d 100644 (file)
@@ -642,7 +642,7 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
       /* Do not filter routes going through the pipe, 
         they are filtered in the export filter only. */
 #ifdef CONFIG_PIPE
-      if (p->proto == &proto_pipe)
+      if (proto_is_pipe(p))
        filter = FILTER_ACCEPT;
 #endif
 
index aa76a1523ce310b24c0073e83b7ed8a61b3e89c3..d9df03bad2314fa703a8cf532fd124743735050b 100644 (file)
@@ -138,6 +138,9 @@ pipe_start(struct proto *P)
    *  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));
@@ -170,20 +173,10 @@ pipe_start(struct proto *P)
    */
   a = proto_add_announce_hook(P, p->peer);
   a->proto = &ph->p;
-  rt_lock_table(p->peer);
 
   return PS_UP;
 }
 
-static int
-pipe_shutdown(struct proto *P)
-{
-  struct pipe_proto *p = (struct pipe_proto *) P;
-
-  rt_unlock_table(p->peer);
-  return PS_DOWN;
-}
-
 static struct proto *
 pipe_init(struct proto_config *C)
 {
@@ -234,13 +227,19 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
   return 1;
 }
 
+struct rtable *
+pipe_get_peer_table(struct proto *P)
+{
+  struct pipe_proto *p = (struct pipe_proto *) P;
+  return p->peer;
+}
+
 struct protocol proto_pipe = {
   name:                "Pipe",
   template:    "pipe%d",
   postconfig:  pipe_postconfig,
   init:                pipe_init,
   start:       pipe_start,
-  shutdown:    pipe_shutdown,
   reconfigure: pipe_reconfigure,
   get_status:  pipe_get_status,
 };