summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-02-13 12:26:26 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2010-02-13 12:26:26 +0100
commitdca75fd7c207f0bfc627cb6b74a484da3b27e05f (patch)
treec8e2f7469e10bb692c3b09b3735b90883318180b
parent9db74169be76f658df2207d1ec99eac48fa36f5f (diff)
downloadbird-dca75fd7c207f0bfc627cb6b74a484da3b27e05f.tar
bird-dca75fd7c207f0bfc627cb6b74a484da3b27e05f.zip
Removes phantom protocol from the pipe design.
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).
-rw-r--r--nest/proto-hooks.c3
-rw-r--r--nest/proto.c5
-rw-r--r--nest/protocol.h11
-rw-r--r--nest/rt-table.c24
-rw-r--r--proto/bgp/attrs.c2
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/ospf/ospf.c5
-rw-r--r--proto/pipe/pipe.c86
-rw-r--r--proto/pipe/pipe.h14
-rw-r--r--proto/rip/rip.c3
-rw-r--r--sysdep/unix/krt.c3
11 files changed, 55 insertions, 103 deletions
diff --git a/nest/proto-hooks.c b/nest/proto-hooks.c
index c30b107..3d19e3f 100644
--- a/nest/proto-hooks.c
+++ b/nest/proto-hooks.c
@@ -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.
diff --git a/nest/proto.c b/nest/proto.c
index a7e4e0c..57c2aa1 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -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
}
/**
diff --git a/nest/protocol.h b/nest/protocol.h
index 876427a..82f3766 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -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
diff --git a/nest/rt-table.c b/nest/rt-table.c
index c9e421e..72a1cb0 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -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)
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 4cfabf1..9667987 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -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;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 7f574ed..1a29195 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -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);
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index d2ceab2..26a05d9 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -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;
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 879135d..943d3a0 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -31,9 +31,12 @@
#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",
diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h
index 368ba41..fbd2129 100644
--- a/proto/pipe/pipe.h
+++ b/proto/pipe/pipe.h
@@ -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
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index f9a160e..d69d643 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -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;
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 488447b..6d94cad 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -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;