Changes pipes to transfer all routes between routing table, not just optimal routes.
This commit is contained in:
parent
23e563d86b
commit
23ac9e9a9e
9 changed files with 97 additions and 42 deletions
|
@ -188,6 +188,8 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||||
* 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.
|
||||||
|
*
|
||||||
|
* FIXME documentation
|
||||||
*/
|
*/
|
||||||
void rt_notify(struct proto *p, net *net, rte *new, rte *old, ea_list *attrs)
|
void rt_notify(struct proto *p, net *net, rte *new, rte *old, ea_list *attrs)
|
||||||
{ DUMMY; }
|
{ DUMMY; }
|
||||||
|
|
|
@ -100,6 +100,7 @@ struct proto {
|
||||||
unsigned debug; /* Debugging flags */
|
unsigned debug; /* Debugging flags */
|
||||||
unsigned preference; /* Default route preference */
|
unsigned preference; /* Default route preference */
|
||||||
int min_scope; /* Minimal route scope accepted */
|
int min_scope; /* Minimal route scope accepted */
|
||||||
|
unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
|
||||||
unsigned disabled; /* Manually disabled */
|
unsigned disabled; /* Manually disabled */
|
||||||
unsigned proto_state; /* Protocol state machine (see below) */
|
unsigned proto_state; /* Protocol state machine (see below) */
|
||||||
unsigned core_state; /* Core state machine (see below) */
|
unsigned core_state; /* Core state machine (see below) */
|
||||||
|
|
|
@ -146,6 +146,7 @@ typedef struct network {
|
||||||
typedef struct rte {
|
typedef struct rte {
|
||||||
struct rte *next;
|
struct rte *next;
|
||||||
net *net; /* Network this RTE belongs to */
|
net *net; /* Network this RTE belongs to */
|
||||||
|
struct proto *sender; /* Protocol instance that sent the route to the routing table */
|
||||||
struct rta *attrs; /* Attributes of this route */
|
struct rta *attrs; /* Attributes of this route */
|
||||||
byte flags; /* Flags (REF_...) */
|
byte flags; /* Flags (REF_...) */
|
||||||
byte pflags; /* Protocol-specific flags */
|
byte pflags; /* Protocol-specific flags */
|
||||||
|
@ -178,6 +179,10 @@ typedef struct rte {
|
||||||
|
|
||||||
#define REF_COW 1 /* Copy this rte on write */
|
#define REF_COW 1 /* Copy this rte on write */
|
||||||
|
|
||||||
|
/* Types of route announcement, also used as flags */
|
||||||
|
#define RA_OPTIMAL 1 /* Announcement of optimal route change */
|
||||||
|
#define RA_ANY 2 /* Announcement of any route change */
|
||||||
|
|
||||||
struct config;
|
struct config;
|
||||||
|
|
||||||
void rt_init(void);
|
void rt_init(void);
|
||||||
|
@ -191,6 +196,7 @@ static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (ne
|
||||||
rte *rte_find(net *net, struct proto *p);
|
rte *rte_find(net *net, struct proto *p);
|
||||||
rte *rte_get_temp(struct rta *);
|
rte *rte_get_temp(struct rta *);
|
||||||
void rte_update(rtable *tab, net *net, struct proto *p, rte *new);
|
void rte_update(rtable *tab, net *net, struct proto *p, rte *new);
|
||||||
|
void rte_update2(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
|
||||||
void rte_discard(rtable *tab, rte *old);
|
void rte_discard(rtable *tab, rte *old);
|
||||||
void rte_dump(rte *);
|
void rte_dump(rte *);
|
||||||
void rte_free(rte *);
|
void rte_free(rte *);
|
||||||
|
@ -230,7 +236,7 @@ void rt_show(struct rt_show_data *);
|
||||||
|
|
||||||
typedef struct rta {
|
typedef struct rta {
|
||||||
struct rta *next, **pprev; /* Hash chain */
|
struct rta *next, **pprev; /* Hash chain */
|
||||||
struct proto *proto; /* Protocol instance */
|
struct proto *proto; /* Protocol instance that originally created the route */
|
||||||
unsigned uc; /* Use count */
|
unsigned uc; /* Use count */
|
||||||
byte source; /* Route source (RTS_...) */
|
byte source; /* Route source (RTS_...) */
|
||||||
byte scope; /* Route scope (SCOPE_... -- see ip.h) */
|
byte scope; /* Route scope (SCOPE_... -- see ip.h) */
|
||||||
|
|
|
@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *tmpa, int class)
|
do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class)
|
||||||
{
|
{
|
||||||
struct proto *p = a->proto;
|
struct proto *p = a->proto;
|
||||||
rte *new0 = new;
|
rte *new0 = new;
|
||||||
|
@ -234,14 +234,17 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *
|
||||||
/**
|
/**
|
||||||
* rte_announce - announce a routing table change
|
* rte_announce - announce a routing table change
|
||||||
* @tab: table the route has been added to
|
* @tab: table the route has been added to
|
||||||
|
* @type: type of route announcement (RA_OPTIMAL or RA_ANY)
|
||||||
* @net: network in question
|
* @net: network in question
|
||||||
* @new: the new route to be announced
|
* @new: the new route to be announced
|
||||||
* @old: previous optimal route for the same network
|
* @old: the previous route for the same network
|
||||||
* @tmpa: a list of temporary attributes belonging to the new route
|
* @tmpa: a list of temporary attributes belonging to the new route
|
||||||
*
|
*
|
||||||
* This function gets a routing table update and announces it
|
* This function gets a routing table update and announces it
|
||||||
* to all protocols connected to the same table by their announcement hooks.
|
* to all protocols connected to the same table by their announcement hooks.
|
||||||
*
|
*
|
||||||
|
* previous optimal route for the same network FIXME
|
||||||
|
*
|
||||||
* For each such protocol, we first call its import_control() hook which
|
* For each such protocol, we first call its import_control() hook which
|
||||||
* performs basic checks on the route (each protocol has a right to veto
|
* performs basic checks on the route (each protocol has a right to veto
|
||||||
* or force accept of the route before any filter is asked) and adds default
|
* or force accept of the route before any filter is asked) and adds default
|
||||||
|
@ -250,7 +253,7 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *
|
||||||
* route, the rt_notify() hook of the protocol gets called.
|
* route, the rt_notify() hook of the protocol gets called.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
rte_announce(rtable *tab, net *net, rte *new, rte *old, ea_list *tmpa)
|
rte_announce(rtable *tab, int type, net *net, rte *new, rte *old, ea_list *tmpa)
|
||||||
{
|
{
|
||||||
struct announce_hook *a;
|
struct announce_hook *a;
|
||||||
int class = ipa_classify(net->n.prefix);
|
int class = ipa_classify(net->n.prefix);
|
||||||
|
@ -258,7 +261,8 @@ rte_announce(rtable *tab, net *net, rte *new, rte *old, ea_list *tmpa)
|
||||||
WALK_LIST(a, tab->hooks)
|
WALK_LIST(a, tab->hooks)
|
||||||
{
|
{
|
||||||
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
||||||
do_rte_announce(a, net, new, old, tmpa, class);
|
if (a->proto->accept_ra_types == type)
|
||||||
|
do_rte_announce(a, type, net, new, old, tmpa, class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +275,7 @@ rte_validate(rte *e)
|
||||||
if (ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))))
|
if (ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))))
|
||||||
{
|
{
|
||||||
log(L_BUG "Ignoring bogus prefix %I/%d received via %s",
|
log(L_BUG "Ignoring bogus prefix %I/%d received via %s",
|
||||||
n->n.prefix, n->n.pxlen, e->attrs->proto->name);
|
n->n.prefix, n->n.pxlen, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (n->n.pxlen)
|
if (n->n.pxlen)
|
||||||
|
@ -290,14 +294,14 @@ rte_validate(rte *e)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
log(L_WARN "Ignoring bogus route %I/%d received via %s",
|
log(L_WARN "Ignoring bogus route %I/%d received via %s",
|
||||||
n->n.prefix, n->n.pxlen, e->attrs->proto->name);
|
n->n.prefix, n->n.pxlen, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((c & IADDR_SCOPE_MASK) < e->attrs->proto->min_scope)
|
if ((c & IADDR_SCOPE_MASK) < e->sender->min_scope)
|
||||||
{
|
{
|
||||||
log(L_WARN "Ignoring %s scope route %I/%d received from %I via %s",
|
log(L_WARN "Ignoring %s scope route %I/%d received from %I via %s",
|
||||||
ip_scope_text(c & IADDR_SCOPE_MASK),
|
ip_scope_text(c & IADDR_SCOPE_MASK),
|
||||||
n->n.prefix, n->n.pxlen, e->attrs->from, e->attrs->proto->name);
|
n->n.prefix, n->n.pxlen, e->attrs->from, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +341,7 @@ rte_same(rte *x, rte *y)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmpa)
|
rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
|
||||||
{
|
{
|
||||||
rte *old_best = net->routes;
|
rte *old_best = net->routes;
|
||||||
rte *old = NULL;
|
rte *old = NULL;
|
||||||
|
@ -346,7 +350,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
|
||||||
k = &net->routes; /* Find and remove original route from the same protocol */
|
k = &net->routes; /* Find and remove original route from the same protocol */
|
||||||
while (old = *k)
|
while (old = *k)
|
||||||
{
|
{
|
||||||
if (old->attrs->proto == p)
|
if (old->attrs->proto == src)
|
||||||
{
|
{
|
||||||
if (new && rte_same(old, new))
|
if (new && rte_same(old, new))
|
||||||
{
|
{
|
||||||
|
@ -362,10 +366,14 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
|
||||||
k = &old->next;
|
k = &old->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(L_WARN "ANNOUNCE %I/%d from %s (%s) %p", net->n.prefix, net->n.pxlen, p->name, src->name, old_best);
|
||||||
|
|
||||||
|
rte_announce(table, RA_ANY, net, new, old, tmpa);
|
||||||
|
|
||||||
if (new && rte_better(new, old_best)) /* It's a new optimal route => announce and relink it */
|
if (new && rte_better(new, old_best)) /* It's a new optimal route => announce and relink it */
|
||||||
{
|
{
|
||||||
rte_trace_in(D_ROUTES, p, new, "added [best]");
|
rte_trace_in(D_ROUTES, p, new, "added [best]");
|
||||||
rte_announce(table, net, new, old_best, tmpa);
|
rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
|
||||||
new->next = net->routes;
|
new->next = net->routes;
|
||||||
net->routes = new;
|
net->routes = new;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +385,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
|
||||||
for(s=net->routes; s; s=s->next)
|
for(s=net->routes; s; s=s->next)
|
||||||
if (rte_better(s, r))
|
if (rte_better(s, r))
|
||||||
r = s;
|
r = s;
|
||||||
rte_announce(table, net, r, old_best, tmpa);
|
rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
|
||||||
if (r) /* Re-link the new optimal route */
|
if (r) /* Re-link the new optimal route */
|
||||||
{
|
{
|
||||||
k = &net->routes;
|
k = &net->routes;
|
||||||
|
@ -477,12 +485,19 @@ rte_update_unlock(void)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
||||||
|
{
|
||||||
|
rte_update2(table, net, p, p, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rte_update2(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
|
||||||
{
|
{
|
||||||
ea_list *tmpa = NULL;
|
ea_list *tmpa = NULL;
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
|
new->sender = p;
|
||||||
struct filter *filter = p->in_filter;
|
struct filter *filter = p->in_filter;
|
||||||
|
|
||||||
/* Do not filter routes going to the secondary side of the pipe,
|
/* Do not filter routes going to the secondary side of the pipe,
|
||||||
|
@ -501,8 +516,8 @@ rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
||||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
if (p->make_tmp_attrs)
|
if (src->make_tmp_attrs)
|
||||||
tmpa = p->make_tmp_attrs(new, rte_update_pool);
|
tmpa = src->make_tmp_attrs(new, rte_update_pool);
|
||||||
if (filter)
|
if (filter)
|
||||||
{
|
{
|
||||||
ea_list *old_tmpa = tmpa;
|
ea_list *old_tmpa = tmpa;
|
||||||
|
@ -512,14 +527,14 @@ rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
||||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
if (tmpa != old_tmpa && p->store_tmp_attrs)
|
if (tmpa != old_tmpa && src->store_tmp_attrs)
|
||||||
p->store_tmp_attrs(new, tmpa);
|
src->store_tmp_attrs(new, tmpa);
|
||||||
}
|
}
|
||||||
if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
|
if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
|
||||||
new->attrs = rta_lookup(new->attrs);
|
new->attrs = rta_lookup(new->attrs);
|
||||||
new->flags |= REF_COW;
|
new->flags |= REF_COW;
|
||||||
}
|
}
|
||||||
rte_recalculate(table, net, p, new, tmpa);
|
rte_recalculate(table, net, p, src, new, tmpa);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -531,11 +546,8 @@ drop:
|
||||||
void
|
void
|
||||||
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
|
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
|
||||||
{
|
{
|
||||||
net *n = old->net;
|
|
||||||
struct proto *p = old->attrs->proto;
|
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
rte_recalculate(t, n, p, NULL, NULL);
|
rte_recalculate(t, old->net, old->sender, old->attrs->proto, NULL, NULL);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,8 +685,8 @@ again:
|
||||||
ncnt++;
|
ncnt++;
|
||||||
rescan:
|
rescan:
|
||||||
for (e=n->routes; e; e=e->next, rcnt++)
|
for (e=n->routes; e; e=e->next, rcnt++)
|
||||||
if (e->attrs->proto->core_state != FS_HAPPY &&
|
if (e->sender->core_state != FS_HAPPY &&
|
||||||
e->attrs->proto->core_state != FS_FEEDING)
|
e->sender->core_state != FS_FEEDING)
|
||||||
{
|
{
|
||||||
rte_discard(tab, e);
|
rte_discard(tab, e);
|
||||||
rdel++;
|
rdel++;
|
||||||
|
@ -827,6 +839,18 @@ rt_commit(struct config *new, struct config *old)
|
||||||
DBG("\tdone\n");
|
DBG("\tdone\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
|
||||||
|
{
|
||||||
|
struct proto *q = e->attrs->proto;
|
||||||
|
ea_list *tmpa;
|
||||||
|
|
||||||
|
rte_update_lock();
|
||||||
|
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
||||||
|
do_rte_announce(h, type, n, e, NULL, tmpa, ipa_classify(n->n.prefix));
|
||||||
|
rte_update_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rt_feed_baby - advertise routes to a new protocol
|
* rt_feed_baby - advertise routes to a new protocol
|
||||||
* @p: protocol to be fed
|
* @p: protocol to be fed
|
||||||
|
@ -865,19 +889,24 @@ again:
|
||||||
FIB_ITERATE_PUT(fit, fn);
|
FIB_ITERATE_PUT(fit, fn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (e)
|
|
||||||
{
|
|
||||||
struct proto *q = e->attrs->proto;
|
|
||||||
ea_list *tmpa;
|
|
||||||
|
|
||||||
if (p->core_state != FS_FEEDING)
|
if (p->accept_ra_types == RA_OPTIMAL)
|
||||||
return 1; /* In the meantime, the protocol fell down. */
|
if (e)
|
||||||
rte_update_lock();
|
{
|
||||||
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
if (p->core_state != FS_FEEDING)
|
||||||
do_rte_announce(h, n, e, NULL, tmpa, ipa_classify(n->n.prefix));
|
return 1; /* In the meantime, the protocol fell down. */
|
||||||
rte_update_unlock();
|
do_feed_baby(p, RA_OPTIMAL, h, n, e);
|
||||||
max_feed--;
|
max_feed--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->accept_ra_types == RA_ANY)
|
||||||
|
for(e = n->routes; e != NULL; e = e->next)
|
||||||
|
{
|
||||||
|
if (p->core_state != FS_FEEDING)
|
||||||
|
return 1; /* In the meantime, the protocol fell down. */
|
||||||
|
do_feed_baby(p, RA_ANY, h, n, e);
|
||||||
|
max_feed--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FIB_ITERATE_END(fn);
|
FIB_ITERATE_END(fn);
|
||||||
p->feed_ahook = h->next;
|
p->feed_ahook = h->next;
|
||||||
|
|
|
@ -753,6 +753,7 @@ bgp_init(struct proto_config *C)
|
||||||
struct proto *P = proto_new(C, sizeof(struct bgp_proto));
|
struct proto *P = proto_new(C, sizeof(struct bgp_proto));
|
||||||
struct bgp_proto *p = (struct bgp_proto *) P;
|
struct bgp_proto *p = (struct bgp_proto *) P;
|
||||||
|
|
||||||
|
P->accept_ra_types = RA_OPTIMAL;
|
||||||
P->rt_notify = bgp_rt_notify;
|
P->rt_notify = bgp_rt_notify;
|
||||||
P->rte_better = bgp_rte_better;
|
P->rte_better = bgp_rte_better;
|
||||||
P->import_control = bgp_import_control;
|
P->import_control = bgp_import_control;
|
||||||
|
|
|
@ -224,6 +224,7 @@ ospf_init(struct proto_config *c)
|
||||||
p->import_control = ospf_import_control;
|
p->import_control = ospf_import_control;
|
||||||
p->make_tmp_attrs = ospf_make_tmp_attrs;
|
p->make_tmp_attrs = ospf_make_tmp_attrs;
|
||||||
p->store_tmp_attrs = ospf_store_tmp_attrs;
|
p->store_tmp_attrs = ospf_store_tmp_attrs;
|
||||||
|
p->accept_ra_types = RA_OPTIMAL;
|
||||||
p->rt_notify = ospf_rt_notify;
|
p->rt_notify = ospf_rt_notify;
|
||||||
p->if_notify = ospf_iface_notify;
|
p->if_notify = ospf_iface_notify;
|
||||||
p->rte_better = ospf_rte_better;
|
p->rte_better = ospf_rte_better;
|
||||||
|
|
|
@ -31,12 +31,16 @@
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
|
pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old, ea_list *attrs)
|
||||||
{
|
{
|
||||||
|
struct proto *src;
|
||||||
net *nn;
|
net *nn;
|
||||||
rte *e;
|
rte *e;
|
||||||
rta a;
|
rta a;
|
||||||
|
|
||||||
|
if (!new && !old)
|
||||||
|
return;
|
||||||
|
|
||||||
if (dest->pipe_busy)
|
if (dest->pipe_busy)
|
||||||
{
|
{
|
||||||
log(L_ERR "Pipe loop detected when sending %I/%d to table %s",
|
log(L_ERR "Pipe loop detected when sending %I/%d to table %s",
|
||||||
|
@ -47,17 +51,24 @@ pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old UNUSED,
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
memcpy(&a, new->attrs, sizeof(rta));
|
memcpy(&a, new->attrs, sizeof(rta));
|
||||||
a.proto = &p->p;
|
|
||||||
a.source = RTS_PIPE;
|
|
||||||
a.aflags = 0;
|
a.aflags = 0;
|
||||||
a.eattrs = attrs;
|
a.eattrs = attrs;
|
||||||
e = rte_get_temp(&a);
|
e = rte_get_temp(&a);
|
||||||
e->net = nn;
|
e->net = nn;
|
||||||
|
|
||||||
|
/* Copy protocol specific embedded attributes. */
|
||||||
|
memcpy(&(e->u), &(new->u), sizeof(e->u));
|
||||||
|
|
||||||
|
src = new->attrs->proto;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
e = NULL;
|
{
|
||||||
|
e = NULL;
|
||||||
|
src = old->attrs->proto;
|
||||||
|
}
|
||||||
|
|
||||||
dest->pipe_busy = 1;
|
dest->pipe_busy = 1;
|
||||||
rte_update(dest, nn, &p->p, e);
|
rte_update2(dest, nn, &p->p, src, e);
|
||||||
dest->pipe_busy = 0;
|
dest->pipe_busy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +93,7 @@ pipe_rt_notify_sec(struct proto *P, net *net, rte *new, rte *old, ea_list *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)->attrs->proto;
|
struct proto *pp = (*ee)->sender;
|
||||||
|
|
||||||
if (pp == P || pp == &((struct pipe_proto *) P)->phantom->p)
|
if (pp == P || pp == &((struct pipe_proto *) P)->phantom->p)
|
||||||
return -1; /* Avoid local loops automatically */
|
return -1; /* Avoid local loops automatically */
|
||||||
|
@ -106,6 +117,7 @@ pipe_start(struct proto *P)
|
||||||
memcpy(ph, p, sizeof(struct pipe_proto));
|
memcpy(ph, p, sizeof(struct pipe_proto));
|
||||||
p->phantom = ph;
|
p->phantom = ph;
|
||||||
ph->phantom = p;
|
ph->phantom = p;
|
||||||
|
ph->p.accept_ra_types = RA_ANY;
|
||||||
ph->p.rt_notify = pipe_rt_notify_sec;
|
ph->p.rt_notify = pipe_rt_notify_sec;
|
||||||
ph->p.proto_state = PS_UP;
|
ph->p.proto_state = PS_UP;
|
||||||
ph->p.core_state = ph->p.core_goal = FS_HAPPY;
|
ph->p.core_state = ph->p.core_goal = FS_HAPPY;
|
||||||
|
@ -141,6 +153,7 @@ pipe_init(struct proto_config *C)
|
||||||
struct pipe_proto *p = (struct pipe_proto *) P;
|
struct pipe_proto *p = (struct pipe_proto *) P;
|
||||||
|
|
||||||
p->peer = c->peer->table;
|
p->peer = c->peer->table;
|
||||||
|
P->accept_ra_types = RA_ANY;
|
||||||
P->rt_notify = pipe_rt_notify_pri;
|
P->rt_notify = pipe_rt_notify_pri;
|
||||||
P->import_control = pipe_import_control;
|
P->import_control = pipe_import_control;
|
||||||
return P;
|
return P;
|
||||||
|
|
|
@ -946,6 +946,7 @@ rip_rte_remove(net *net UNUSED, rte *rte)
|
||||||
void
|
void
|
||||||
rip_init_instance(struct proto *p)
|
rip_init_instance(struct proto *p)
|
||||||
{
|
{
|
||||||
|
p->accept_ra_types = RA_OPTIMAL;
|
||||||
p->if_notify = rip_if_notify;
|
p->if_notify = rip_if_notify;
|
||||||
p->rt_notify = rip_rt_notify;
|
p->rt_notify = rip_rt_notify;
|
||||||
p->import_control = rip_import_control;
|
p->import_control = rip_import_control;
|
||||||
|
|
|
@ -875,6 +875,7 @@ krt_init(struct proto_config *c)
|
||||||
{
|
{
|
||||||
struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
|
struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
|
||||||
|
|
||||||
|
p->p.accept_ra_types = RA_OPTIMAL;
|
||||||
p->p.rt_notify = krt_notify;
|
p->p.rt_notify = krt_notify;
|
||||||
p->p.min_scope = SCOPE_HOST;
|
p->p.min_scope = SCOPE_HOST;
|
||||||
return &p->p;
|
return &p->p;
|
||||||
|
|
Loading…
Reference in a new issue