From ea7ada3809ed672bd9d2f9e5742f42b238cc5389 Mon Sep 17 00:00:00 2001
From: Ondrej Zajicek <santiago@crfreenet.org>
Date: Sun, 20 Dec 2009 14:59:12 +0100
Subject: [PATCH] Fixes a new bug in the pipe protocol soft reconfiguration.

Also updates route reload for pipes.
---
 doc/bird.sgml     |  4 +++-
 proto/pipe/pipe.c | 26 +++++++++++++++++++++++---
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/doc/bird.sgml b/doc/bird.sgml
index 3905a29e..a6278a1a 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -513,7 +513,9 @@ This argument can be omitted if there exists only a single instance.
 	Re-export always succeeds, but re-import is protocol-dependent
 	and might fail (for example, if BGP neighbor does not support
 	route-refresh extension). In that case, re-export is also
-	skipped.
+	skipped. Note that for the pipe protocol, both directions are
+	always reloaded together (<cf/in/ or <cf/out/ options are
+	ignored in that case).
 
 	<tag/down/
 	Shut BIRD down.
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 18f1c005..aa76a152 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -113,6 +113,19 @@ pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpo
   return 0;
 }
 
+static int
+pipe_reload_routes(struct proto *P)
+{
+  /*
+   * Because the pipe protocol feeds routes from both routing tables
+   * together, both directions are reloaded during refeed and 'reload
+   * out' command works like 'reload' command. For symmetry, we also
+   * request refeed when 'reload in' command is used.
+   */
+  proto_request_feeding(P);
+  return 1;
+}
+
 static int
 pipe_start(struct proto *P)
 {
@@ -183,6 +196,7 @@ pipe_init(struct proto_config *C)
   P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
   P->rt_notify = pipe_rt_notify_pri;
   P->import_control = pipe_import_control;
+  P->reload_routes = pipe_reload_routes;
   return P;
 }
 
@@ -206,12 +220,18 @@ pipe_get_status(struct proto *P, byte *buf)
 }
 
 static int
-pipe_reconfigure(struct proto *p, struct proto_config *new)
+pipe_reconfigure(struct proto *P, struct proto_config *new)
 {
-  struct pipe_config *o = (struct pipe_config *) p->cf;
+  struct pipe_proto *p = (struct pipe_proto *) P;
+  struct pipe_config *o = (struct pipe_config *) P->cf;
   struct pipe_config *n = (struct pipe_config *) new;
 
-  return (o->peer->table == n->peer->table) && (o->mode == n->mode);
+  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 protocol proto_pipe = {