summaryrefslogtreecommitdiffstats
path: root/proto
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 /proto
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).
Diffstat (limited to 'proto')
-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
6 files changed, 31 insertions, 81 deletions
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;