Commit dca75fd7 authored by Ondřej Zajíček's avatar Ondřej Zajíček

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).
parent 9db74169
...@@ -178,13 +178,14 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a) ...@@ -178,13 +178,14 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
/** /**
* rt_notify - notify instance about routing table change * rt_notify - notify instance about routing table change
* @p: protocol instance * @p: protocol instance
* @table: a routing table
* @net: a network entry * @net: a network entry
* @new: new route for the network * @new: new route for the network
* @old: old route for the network * @old: old route for the network
* @attrs: extended attributes associated with the @new entry * @attrs: extended attributes associated with the @new entry
* *
* The rt_notify() hook is called to inform the protocol instance about * 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 * belonging to network @net being replaced by a new route @new with
* extended attributes @attrs. Either @new or @old or both can be %NULL * extended attributes @attrs. Either @new or @old or both can be %NULL
* if the corresponding route doesn't exist. * if the corresponding route doesn't exist.
......
...@@ -133,11 +133,6 @@ proto_init_instance(struct proto *p) ...@@ -133,11 +133,6 @@ proto_init_instance(struct proto *p)
p->attn = ev_new(p->pool); p->attn = ev_new(p->pool);
p->attn->data = p; p->attn->data = p;
rt_lock_table(p->table); rt_lock_table(p->table);
#ifdef CONFIG_PIPE
if (proto_is_pipe(p))
rt_lock_table(pipe_get_peer_table(p));
#endif
} }
/** /**
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
struct iface; struct iface;
struct ifa; struct ifa;
struct rtable;
struct rte; struct rte;
struct neighbor; struct neighbor;
struct rta; struct rta;
...@@ -162,7 +163,7 @@ struct proto { ...@@ -162,7 +163,7 @@ struct proto {
void (*if_notify)(struct proto *, unsigned flags, struct iface *i); void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); 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); void (*neigh_notify)(struct neighbor *neigh);
struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool); struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs); 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 *); ...@@ -339,13 +340,7 @@ struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
*/ */
#ifdef CONFIG_PIPE #ifdef CONFIG_PIPE
#include "proto/pipe/pipe.h"
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);
#endif #endif
......
...@@ -161,6 +161,7 @@ static inline void ...@@ -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) 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 proto *p = a->proto;
struct filter *filter = p->out_filter;
struct proto_stats *stats = &p->stats; struct proto_stats *stats = &p->stats;
rte *new0 = new; rte *new0 = new;
rte *old0 = old; rte *old0 = old;
...@@ -168,6 +169,15 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *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; 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) if (new)
{ {
stats->exp_updates_received++; stats->exp_updates_received++;
...@@ -186,8 +196,8 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ...@@ -186,8 +196,8 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
} }
else if (ok) else if (ok)
rte_trace_out(D_FILTERS, p, new, "forced accept by protocol"); rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
else if (p->out_filter == FILTER_REJECT || else if (filter == FILTER_REJECT ||
p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT) filter && f_run(filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
{ {
stats->exp_updates_filtered++; stats->exp_updates_filtered++;
drop_reason = "filtered out"; drop_reason = "filtered out";
...@@ -230,13 +240,13 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ...@@ -230,13 +240,13 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
if (old && !refeed) if (old && !refeed)
{ {
if (p->out_filter == FILTER_REJECT) if (filter == FILTER_REJECT)
old = NULL; old = NULL;
else else
{ {
ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL; 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; 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) if (old != old0)
rte_free(old); rte_free(old);
...@@ -271,18 +281,18 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *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"); rte_trace_out(D_ROUTES, p, old, "removed");
} }
if (!new) if (!new)
p->rt_notify(p, net, NULL, old, NULL); p->rt_notify(p, a->table, net, NULL, old, NULL);
else if (tmpa) else if (tmpa)
{ {
ea_list *t = tmpa; ea_list *t = tmpa;
while (t->next) while (t->next)
t = t->next; t = t->next;
t->next = new->attrs->eattrs; 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; t->next = NULL;
} }
else 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 */ if (new && new != new0) /* Discard temporary rte's */
rte_free(new); rte_free(new);
if (old && old != old0) if (old && old != old0)
......
...@@ -772,7 +772,7 @@ bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck) ...@@ -772,7 +772,7 @@ bgp_free_bucket(struct bgp_proto *p, struct bgp_bucket *buck)
} }
void 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_proto *p = (struct bgp_proto *) P;
struct bgp_bucket *buck; struct bgp_bucket *buck;
......
...@@ -179,7 +179,7 @@ byte *bgp_attach_attr_wa(struct ea_list **to, struct linpool *pool, unsigned att ...@@ -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); 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_get_attr(struct eattr *e, byte *buf, int buflen);
int bgp_rte_better(struct rte *, struct rte *); 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 *); int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *);
void bgp_attr_init(struct bgp_proto *); void bgp_attr_init(struct bgp_proto *);
unsigned int bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains); unsigned int bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains);
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
static int ospf_reload_routes(struct proto *p); 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 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_better(struct rte *new, struct rte *old);
static int ospf_rte_same(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) ...@@ -484,8 +484,7 @@ ospf_shutdown(struct proto *p)
} }
static void static void
ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED, ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * old UNUSED, ea_list * attrs)
ea_list * attrs)
{ {
struct proto_ospf *po = (struct proto_ospf *) p; struct proto_ospf *po = (struct proto_ospf *) p;
......
...@@ -31,9 +31,12 @@ ...@@ -31,9 +31,12 @@
#include "pipe.h" #include "pipe.h"
static void 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; struct proto *src;
net *nn; net *nn;
rte *e; rte *e;
rta a; rta a;
...@@ -85,30 +88,12 @@ pipe_send(struct pipe_proto *p, rtable *src_table, rtable *dest, net *n, rte *ne ...@@ -85,30 +88,12 @@ pipe_send(struct pipe_proto *p, rtable *src_table, rtable *dest, net *n, rte *ne
src_table->pipe_busy = 0; 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 static int
pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED) pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
{ {
struct proto *pp = (*ee)->sender; 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 -1; /* Avoid local loops automatically */
return 0; return 0;
} }
...@@ -130,49 +115,16 @@ static int ...@@ -130,49 +115,16 @@ static int
pipe_start(struct proto *P) pipe_start(struct proto *P)
{ {
struct pipe_proto *p = (struct pipe_proto *) P; struct pipe_proto *p = (struct pipe_proto *) P;
struct pipe_proto *ph;
struct announce_hook *a; struct announce_hook *a;
/* /* Clean up the secondary stats */
* Create a phantom protocol which will represent the remote bzero(&p->peer_stats, sizeof(struct proto_stats));
* 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;
/* /* Lock the peer table, unlock is handled in proto_fell_down() */
* Routes should be filtered in the do_rte_announce() (export rt_lock_table(p->peer);
* 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;
/* /* Connect the protocol also to the peer routing table. */
* 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.
*/
a = proto_add_announce_hook(P, p->peer); a = proto_add_announce_hook(P, p->peer);
a->proto = &ph->p;
return PS_UP; return PS_UP;
} }
...@@ -187,9 +139,10 @@ pipe_init(struct proto_config *C) ...@@ -187,9 +139,10 @@ pipe_init(struct proto_config *C)
p->peer = c->peer->table; p->peer = c->peer->table;
p->mode = c->mode; p->mode = c->mode;
P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY; 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->import_control = pipe_import_control;
P->reload_routes = pipe_reload_routes; P->reload_routes = pipe_reload_routes;
return P; return P;
} }
...@@ -222,24 +175,9 @@ pipe_reconfigure(struct proto *P, struct proto_config *new) ...@@ -222,24 +175,9 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
if ((o->peer->table != n->peer->table) || (o->mode != n->mode)) if ((o->peer->table != n->peer->table) || (o->mode != n->mode))
return 0; return 0;
/* Update also the filter in the phantom protocol */
p->phantom->p.out_filter = new->in_filter;
return 1; 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 = { struct protocol proto_pipe = {
name: "Pipe", name: "Pipe",
......
...@@ -21,8 +21,20 @@ struct pipe_config { ...@@ -21,8 +21,20 @@ struct pipe_config {
struct pipe_proto { struct pipe_proto {
struct proto p; struct proto p;
struct rtable *peer; struct rtable *peer;
struct proto_stats peer_stats; /* Statistics for the direction peer->primary */
int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */ 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 #endif
...@@ -864,7 +864,8 @@ rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) ...@@ -864,7 +864,8 @@ rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
* own), so store it into our data structures. * own), so store it into our data structures.
*/ */
static void 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; CHK_MAGIC;
......
...@@ -742,7 +742,8 @@ krt_scan(timer *t UNUSED) ...@@ -742,7 +742,8 @@ krt_scan(timer *t UNUSED)
*/ */
static void 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; struct krt_proto *p = (struct krt_proto *) P;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment