0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Nest: Changed struct network * in struct rte to const net_addr *. [WIP]

This allows filtering the route without even touching the table on
import. Therefore rejected routes don't mess with the table in any way.
Only accepted routes are linked to the table.

Kernel protocol still uses a dirty hack to get routes synchronized. This
should be sanitized in future to allow proper concurrency.
This commit is contained in:
Maria Matejka 2018-10-30 20:57:38 +01:00 committed by Maria Matejka
parent 4b7f14aaa6
commit 9d798cd843
11 changed files with 129 additions and 115 deletions

View File

@ -942,7 +942,7 @@ interpret(struct f_inst *what)
{ {
case SA_FROM: res.val.ip = rta->from; break; case SA_FROM: res.val.ip = rta->from; break;
case SA_GW: res.val.ip = rta->nh.gw; break; case SA_GW: res.val.ip = rta->nh.gw; break;
case SA_NET: res.val.net = (*f_rte)->net->n.addr; break; case SA_NET: res.val.net = (*f_rte)->netA; break;
case SA_PROTO: res.val.s = rta->src->proto->name; break; case SA_PROTO: res.val.s = rta->src->proto->name; break;
case SA_SOURCE: res.val.i = rta->source; break; case SA_SOURCE: res.val.i = rta->source; break;
case SA_SCOPE: res.val.i = rta->scope; break; case SA_SCOPE: res.val.i = rta->scope; break;
@ -1531,7 +1531,7 @@ interpret(struct f_inst *what)
{ {
ACCESS_RTE; ACCESS_RTE;
ACCESS_EATTRS; ACCESS_EATTRS;
v1.val.net = (*f_rte)->net->n.addr; v1.val.net = (*f_rte)->netA;
/* We ignore temporary attributes, probably not a problem here */ /* We ignore temporary attributes, probably not a problem here */
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */ /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */

View File

@ -207,7 +207,7 @@ struct hostentry {
typedef struct rte { typedef struct rte {
struct rte *next; struct rte *next;
net *net; /* Network this RTE belongs to */ const net_addr *netA; /* Network this RTE belongs to */
struct channel *sender; /* Channel used to send the route to the routing table */ struct channel *sender; /* Channel used to send 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_...) */
@ -258,6 +258,8 @@ typedef struct rte {
#define REF_DISCARD 8 /* Route is scheduled for discard */ #define REF_DISCARD 8 /* Route is scheduled for discard */
#define REF_MODIFY 16 /* Route is scheduled for modify */ #define REF_MODIFY 16 /* Route is scheduled for modify */
#define RTE_NET(e) (((e)->flags & REF_COW) ? SKIP_BACK(struct network, n, SKIP_BACK(struct fib_node, addr, (e)->netA)) : NULL)
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */ /* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); } static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }

View File

@ -34,8 +34,9 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
byte from[IPA_MAX_TEXT_LENGTH+8]; byte from[IPA_MAX_TEXT_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
rta *a = e->attrs; rta *a = e->attrs;
int primary = (e->net->routes == e); net *nn = RTE_NET(e);
int sync_error = (e->net->n.flags & KRF_SYNC_ERROR); int primary = nn && (nn->routes == e);
int sync_error = nn && (nn->n.flags & KRF_SYNC_ERROR);
void (*get_route_info)(struct rte *, byte *buf); void (*get_route_info)(struct rte *, byte *buf);
struct nexthop *nh; struct nexthop *nh;

View File

@ -376,7 +376,7 @@ rte_mergable(rte *pri, rte *sec)
static void static void
rte_trace(struct proto *p, rte *e, int dir, char *msg) rte_trace(struct proto *p, rte *e, int dir, char *msg)
{ {
log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->net->n.addr, rta_dest_name(e->attrs->dest)); log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->netA, rta_dest_name(e->attrs->dest));
} }
static inline void static inline void
@ -923,36 +923,36 @@ static inline int
rte_validate(rte *e) rte_validate(rte *e)
{ {
int c; int c;
net *n = e->net; const net_addr *n = e->netA;
if (!net_validate(n->n.addr)) if (!net_validate(n))
{ {
log(L_WARN "Ignoring bogus prefix %N received via %s", log(L_WARN "Ignoring bogus prefix %N received via %s",
n->n.addr, e->sender->proto->name); n, e->sender->proto->name);
return 0; return 0;
} }
/* FIXME: better handling different nettypes */ /* FIXME: better handling different nettypes */
c = !net_is_flow(n->n.addr) ? c = !net_is_flow(n) ?
net_classify(n->n.addr): (IADDR_HOST | SCOPE_UNIVERSE); net_classify(n): (IADDR_HOST | SCOPE_UNIVERSE);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
{ {
log(L_WARN "Ignoring bogus route %N received via %s", log(L_WARN "Ignoring bogus route %N received via %s",
n->n.addr, e->sender->proto->name); n, e->sender->proto->name);
return 0; return 0;
} }
if (net_type_match(n->n.addr, NB_DEST) == !e->attrs->dest) if (net_type_match(n, NB_DEST) == !e->attrs->dest)
{ {
log(L_WARN "Ignoring route %N with invalid dest %d received via %s", log(L_WARN "Ignoring route %N with invalid dest %d received via %s",
n->n.addr, e->attrs->dest, e->sender->proto->name); n, e->attrs->dest, e->sender->proto->name);
return 0; return 0;
} }
if ((e->attrs->dest == RTD_UNICAST) && !nexthop_is_sorted(&(e->attrs->nh))) if ((e->attrs->dest == RTD_UNICAST) && !nexthop_is_sorted(&(e->attrs->nh)))
{ {
log(L_WARN "Ignoring unsorted multipath route %N received via %s", log(L_WARN "Ignoring unsorted multipath route %N received via %s",
n->n.addr, e->sender->proto->name); n, e->sender->proto->name);
return 0; return 0;
} }
@ -1346,9 +1346,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
rte_update_lock(); rte_update_lock();
if (new) if (new)
{ {
nn = net_get(c->table, n); new->netA = n;
new->net = nn;
new->sender = c; new->sender = c;
if (!new->pref) if (!new->pref)
@ -1397,6 +1395,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
if (!rta_is_cached(new->attrs)) /* Need to copy attributes */ if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
new->attrs = rta_lookup(new->attrs); new->attrs = rta_lookup(new->attrs);
new->flags |= REF_COW; new->flags |= REF_COW;
new->netA = (nn = net_get(c->table, n))->n.addr;
} }
else else
{ {
@ -1420,7 +1420,12 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
drop: drop:
rte_free(new); rte_free(new);
new = NULL; new = NULL;
if ((nn = net_find(c->table, n)) && src)
goto recalc; goto recalc;
rte_update_unlock();
return;
} }
/* Independent call to rte_announce(), used from next hop /* Independent call to rte_announce(), used from next hop
@ -1435,16 +1440,16 @@ rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old,
} }
static inline void static inline void
rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collection */ rte_discard(net *n, rte *old) /* Non-filtered route deletion, used during garbage collection */
{ {
rte_update_lock(); rte_update_lock();
rte_recalculate(old->sender, old->net, NULL, old->attrs->src); rte_recalculate(old->sender, n, NULL, old->attrs->src);
rte_update_unlock(); rte_update_unlock();
} }
/* Modify existing route by protocol hook, used for long-lived graceful restart */ /* Modify existing route by protocol hook, used for long-lived graceful restart */
static inline void static inline void
rte_modify(rte *old) rte_modify(net *n, rte *old)
{ {
rte_update_lock(); rte_update_lock();
@ -1458,7 +1463,7 @@ rte_modify(rte *old)
new->flags = (old->flags & ~REF_MODIFY) | REF_COW; new->flags = (old->flags & ~REF_MODIFY) | REF_COW;
} }
rte_recalculate(old->sender, old->net, new, old->attrs->src); rte_recalculate(old->sender, n, new, old->attrs->src);
} }
rte_update_unlock(); rte_update_unlock();
@ -1580,9 +1585,13 @@ rt_modify_stale(rtable *t, struct channel *c)
void void
rte_dump(rte *e) rte_dump(rte *e)
{ {
net *n = e->net; debug("%-1N ", e->netA);
debug("%-1N ", n->n.addr); net *n = RTE_NET(e);
if (n)
debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref); debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
else
debug("outside fib, PF=%02x pref=%d ", e->pflags, e->pref);
rta_dump(e->attrs); rta_dump(e->attrs);
if (e->attrs->src->proto->proto->dump_attrs) if (e->attrs->src->proto->proto->dump_attrs)
e->attrs->src->proto->proto->dump_attrs(e); e->attrs->src->proto->proto->dump_attrs(e);
@ -1769,7 +1778,7 @@ again:
return; return;
} }
rte_discard(e); rte_discard(n, e);
limit--; limit--;
goto rescan; goto rescan;
@ -1784,7 +1793,7 @@ again:
return; return;
} }
rte_modify(e); rte_modify(n, e);
limit--; limit--;
goto rescan; goto rescan;
@ -2360,7 +2369,7 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
/* Insert the new rte */ /* Insert the new rte */
rte *e = rte_do_cow(new); rte *e = rte_do_cow(new);
e->flags |= REF_COW; e->flags |= REF_COW;
e->net = net; e->netA = net->n.addr;
e->sender = c; e->sender = c;
e->lastmod = current_time(); e->lastmod = current_time();
e->next = *pos; e->next = *pos;

View File

@ -627,7 +627,7 @@ bgp_decode_large_community(struct bgp_parse_state *s, uint code UNUSED, uint fla
static void static void
bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a) bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
{ {
net_addr *n = s->route->net->n.addr; const net_addr *n = s->route->netA;
u32 *labels = (u32 *) a->u.ptr->data; u32 *labels = (u32 *) a->u.ptr->data;
uint lnum = a->u.ptr->length / 4; uint lnum = a->u.ptr->length / 4;

View File

@ -459,7 +459,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
if (alen < 0) if (alen < 0)
{ {
mrt_log(s, "Attribute list too long for %N", r->net->n.addr); mrt_log(s, "Attribute list too long for %N", r->netA);
alen = 0; alen = 0;
} }

View File

@ -390,9 +390,9 @@ radv_trigger_valid(struct radv_config *cf)
} }
static inline int static inline int
radv_net_match_trigger(struct radv_config *cf, net *n) radv_net_match_trigger(struct radv_config *cf, const net_addr *n)
{ {
return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger); return radv_trigger_valid(cf) && net_equal(n, &cf->trigger);
} }
int int
@ -401,7 +401,7 @@ radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
// struct radv_proto *p = (struct radv_proto *) P; // struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf); struct radv_config *cf = (struct radv_config *) (P->cf);
if (radv_net_match_trigger(cf, (*new)->net)) if (radv_net_match_trigger(cf, (*new)->netA))
return RIC_PROCESS; return RIC_PROCESS;
if (cf->propagate_routes) if (cf->propagate_routes)
@ -418,7 +418,7 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
struct radv_route *rt; struct radv_route *rt;
eattr *ea; eattr *ea;
if (radv_net_match_trigger(cf, n)) if (radv_net_match_trigger(cf, n->n.addr))
{ {
u8 old_active = p->active; u8 old_active = p->active;
p->active = !!new; p->active = !!new;

View File

@ -199,7 +199,7 @@ sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa)
static int static int
krt_send_route(struct krt_proto *p, int cmd, rte *e) krt_send_route(struct krt_proto *p, int cmd, rte *e)
{ {
net *net = e->net; const net_addr *n = e->netA;
rta *a = e->attrs; rta *a = e->attrs;
static int msg_seq; static int msg_seq;
struct iface *j, *i = a->nh.iface; struct iface *j, *i = a->nh.iface;
@ -208,7 +208,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
char *body = (char *)msg.buf; char *body = (char *)msg.buf;
sockaddr gate, mask, dst; sockaddr gate, mask, dst;
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); DBG("krt-sock: send %N via %I\n", n, a->gw);
bzero(&msg,sizeof (struct rt_msghdr)); bzero(&msg,sizeof (struct rt_msghdr));
msg.rtm.rtm_version = RTM_VERSION; msg.rtm.rtm_version = RTM_VERSION;
@ -218,7 +218,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1; msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
/* XXXX */ /* XXXX */
if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type]) if (net_pxlen(n) == net_max_prefix_length[n->type])
msg.rtm.rtm_flags |= RTF_HOST; msg.rtm.rtm_flags |= RTF_HOST;
else else
msg.rtm.rtm_addrs |= RTA_NETMASK; msg.rtm.rtm_addrs |= RTA_NETMASK;
@ -260,7 +260,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
int af = AF_UNSPEC; int af = AF_UNSPEC;
switch (net->n.addr->type) { switch (n->type) {
case NET_IP4: case NET_IP4:
af = AF_INET; af = AF_INET;
break; break;
@ -268,12 +268,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
af = AF_INET6; af = AF_INET6;
break; break;
default: default:
log(L_ERR "KRT: Not sending route %N to kernel", net->n.addr); log(L_ERR "KRT: Not sending route %N to kernel", n);
return -1; return -1;
} }
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0); sockaddr_fill(&dst, af, net_prefix(n), NULL, 0);
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0); sockaddr_fill(&mask, af, net_pxmask(n), NULL, 0);
switch (a->dest) switch (a->dest)
{ {
@ -303,7 +303,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
#if __OpenBSD__ #if __OpenBSD__
/* Keeping temporarily old code for OpenBSD */ /* Keeping temporarily old code for OpenBSD */
struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6); struct ifa *addr = (n->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
if (!addr) if (!addr)
{ {
@ -339,15 +339,15 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
msg.rtm.rtm_msglen = l; msg.rtm.rtm_msglen = l;
if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) { if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr); log(L_ERR "KRT: Error sending route %N to kernel: %m", n);
return -1; return -1;
} }
return 0; return 0;
} }
void int
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
{ {
int err = 0; int err = 0;
@ -357,10 +357,7 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
if (new) if (new)
err = krt_send_route(p, RTM_ADD, new); err = krt_send_route(p, RTM_ADD, new);
if (err < 0) return (err >= 0);
n->n.flags |= KRF_SYNC_ERROR;
else
n->n.flags &= ~KRF_SYNC_ERROR;
} }
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0) #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
@ -372,7 +369,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
int ipv6; int ipv6;
rte *e; rte *e;
net *net;
sockaddr dst, gate, mask; sockaddr dst, gate, mask;
ip_addr idst, igate, imask; ip_addr idst, igate, imask;
net_addr ndst; net_addr ndst;
@ -489,8 +485,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
else else
src = KRT_SRC_KERNEL; src = KRT_SRC_KERNEL;
net = net_get(p->p.main_channel->table, &ndst);
rta a = { rta a = {
.src = p->p.main_source, .src = p->p.main_source,
.source = RTS_INHERIT, .source = RTS_INHERIT,
@ -518,7 +512,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
if (!a.nh.iface) if (!a.nh.iface)
{ {
log(L_ERR "KRT: Received route %N with unknown ifindex %u", log(L_ERR "KRT: Received route %N with unknown ifindex %u",
net->n.addr, msg->rtm.rtm_index); &ndst, msg->rtm.rtm_index);
return; return;
} }
@ -541,14 +535,14 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
return; return;
log(L_ERR "KRT: Received route %N with strange next-hop %I", log(L_ERR "KRT: Received route %N with strange next-hop %I",
net->n.addr, a.nh.gw); &ndst, a.nh.gw);
return; return;
} }
} }
done: done:
e = rte_get_temp(&a); e = rte_get_temp(&a);
e->net = net; e->netA = &ndst;
e->u.krt.src = src; e->u.krt.src = src;
e->u.krt.proto = src2; e->u.krt.proto = src2;
e->u.krt.seen = 0; e->u.krt.seen = 0;

View File

@ -104,7 +104,7 @@ struct nl_parse_state
int scan; int scan;
int merge; int merge;
net *net; const net_addr *netA;
rta *attrs; rta *attrs;
struct krt_proto *proto; struct krt_proto *proto;
s8 new; s8 new;
@ -1180,7 +1180,7 @@ static int
nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh) nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
{ {
eattr *ea; eattr *ea;
net *net = e->net; const net_addr *n = e->netA;
rta *a = e->attrs; rta *a = e->attrs;
ea_list *eattrs = a->eattrs; ea_list *eattrs = a->eattrs;
int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh)); int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh));
@ -1195,7 +1195,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
int rsize = sizeof(*r) + bufsize; int rsize = sizeof(*r) + bufsize;
r = alloca(rsize); r = alloca(rsize);
DBG("nl_send_route(%N,op=%x)\n", net->n.addr, op); DBG("nl_send_route(%N,op=%x)\n", n, op);
bzero(&r->h, sizeof(r->h)); bzero(&r->h, sizeof(r->h));
bzero(&r->r, sizeof(r->r)); bzero(&r->r, sizeof(r->r));
@ -1204,7 +1204,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
r->h.nlmsg_flags = op | NLM_F_REQUEST | NLM_F_ACK; r->h.nlmsg_flags = op | NLM_F_REQUEST | NLM_F_ACK;
r->r.rtm_family = p->af; r->r.rtm_family = p->af;
r->r.rtm_dst_len = net_pxlen(net->n.addr); r->r.rtm_dst_len = net_pxlen(n);
r->r.rtm_protocol = RTPROT_BIRD; r->r.rtm_protocol = RTPROT_BIRD;
r->r.rtm_scope = RT_SCOPE_NOWHERE; r->r.rtm_scope = RT_SCOPE_NOWHERE;
#ifdef HAVE_MPLS_KERNEL #ifdef HAVE_MPLS_KERNEL
@ -1216,7 +1216,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
* 2) Never use RTA_PRIORITY * 2) Never use RTA_PRIORITY
*/ */
u32 label = net_mpls(net->n.addr); u32 label = net_mpls(n);
nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label); nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
r->r.rtm_scope = RT_SCOPE_UNIVERSE; r->r.rtm_scope = RT_SCOPE_UNIVERSE;
r->r.rtm_type = RTN_UNICAST; r->r.rtm_type = RTN_UNICAST;
@ -1224,12 +1224,12 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
else else
#endif #endif
{ {
nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr)); nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(n));
/* Add source address for IPv6 SADR routes */ /* Add source address for IPv6 SADR routes */
if (net->n.addr->type == NET_IP6_SADR) if (n->type == NET_IP6_SADR)
{ {
net_addr_ip6_sadr *a = (void *) &net->n.addr; net_addr_ip6_sadr *a = (void *) n;
nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix); nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix);
r->r.rtm_src_len = a->src_pxlen; r->r.rtm_src_len = a->src_pxlen;
} }
@ -1364,8 +1364,8 @@ nl_delete_rte(struct krt_proto *p, rte *e)
return err; return err;
} }
void int
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
{ {
int err = 0; int err = 0;
@ -1386,21 +1386,18 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
if (new) if (new)
err = nl_add_rte(p, new); err = nl_add_rte(p, new);
if (err < 0) return (err >= 0);
n->n.flags |= KRF_SYNC_ERROR;
else
n->n.flags &= ~KRF_SYNC_ERROR;
} }
static int static int
nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type) nl_mergable_route(struct nl_parse_state *s, const net_addr *netA, struct krt_proto *p, uint priority, uint krt_type)
{ {
/* Route merging must be active */ /* Route merging must be active */
if (!s->merge) if (!s->merge)
return 0; return 0;
/* Saved and new route must have same network, proto/table, and priority */ /* Saved and new route must have same network, proto/table, and priority */
if ((s->net != net) || (s->proto != p) || (s->krt_metric != priority)) if (!net_equal(s->netA, netA) || (s->proto != p) || (s->krt_metric != priority))
return 0; return 0;
/* Both must be regular unicast routes */ /* Both must be regular unicast routes */
@ -1414,7 +1411,7 @@ static void
nl_announce_route(struct nl_parse_state *s) nl_announce_route(struct nl_parse_state *s)
{ {
rte *e = rte_get_temp(s->attrs); rte *e = rte_get_temp(s->attrs);
e->net = s->net; e->netA = s->netA;
e->u.krt.src = s->krt_src; e->u.krt.src = s->krt_src;
e->u.krt.proto = s->krt_proto; e->u.krt.proto = s->krt_proto;
e->u.krt.seen = 0; e->u.krt.seen = 0;
@ -1426,7 +1423,7 @@ nl_announce_route(struct nl_parse_state *s)
else else
krt_got_route_async(s->proto, e, s->new); krt_got_route_async(s->proto, e, s->new);
s->net = NULL; s->netA = NULL;
s->attrs = NULL; s->attrs = NULL;
s->proto = NULL; s->proto = NULL;
lp_flush(s->pool); lp_flush(s->pool);
@ -1444,7 +1441,7 @@ nl_parse_begin(struct nl_parse_state *s, int scan, int merge)
static inline void static inline void
nl_parse_end(struct nl_parse_state *s) nl_parse_end(struct nl_parse_state *s)
{ {
if (s->net) if (s->netA)
nl_announce_route(s); nl_announce_route(s);
} }
@ -1571,18 +1568,21 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
krt_src = KRT_SRC_ALIEN; krt_src = KRT_SRC_ALIEN;
} }
net_addr *n = &dst; net_addr *nloc;
if (p->p.net_type == NET_IP6_SADR) if (p->p.net_type == NET_IP6_SADR)
{ {
n = alloca(sizeof(net_addr_ip6_sadr)); nloc = alloca(sizeof(net_addr_ip6_sadr));
net_fill_ip6_sadr(n, net6_prefix(&dst), net6_pxlen(&dst), net_fill_ip6_sadr(nloc, net6_prefix(&dst), net6_pxlen(&dst),
net6_prefix(&src), net6_pxlen(&src)); net6_prefix(&src), net6_pxlen(&src));
} }
else
nloc = &dst;
net *net = net_get(p->p.main_channel->table, n); if (s->netA && !nl_mergable_route(s, nloc, p, priority, i->rtm_type))
nl_announce_route(s); /* Here is the s->pool flushed! */
if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) net_addr *n = lp_alloc(s->pool, dst.length);
nl_announce_route(s); net_copy(n, nloc);
rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE); rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
ra->src = p->p.main_source; ra->src = p->p.main_source;
@ -1599,7 +1599,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family); struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family);
if (!nh) if (!nh)
{ {
log(L_ERR "KRT: Received strange multipath route %N", net->n.addr); log(L_ERR "KRT: Received strange multipath route %N", n);
return; return;
} }
@ -1610,7 +1610,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
ra->nh.iface = if_find_by_index(oif); ra->nh.iface = if_find_by_index(oif);
if (!ra->nh.iface) if (!ra->nh.iface)
{ {
log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif); log(L_ERR "KRT: Received route %N with unknown ifindex %u", n, oif);
return; return;
} }
@ -1640,7 +1640,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
(ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
if (!nbr || (nbr->scope == SCOPE_HOST)) if (!nbr || (nbr->scope == SCOPE_HOST))
{ {
log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr, log(L_ERR "KRT: Received route %N with strange next-hop %I", n,
ra->nh.gw); ra->nh.gw);
return; return;
} }
@ -1745,7 +1745,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0) if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
{ {
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr); log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", n);
return; return;
} }
@ -1776,10 +1776,10 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
* Otherwise, we ignore additional next hops in nexthop_insert(). * Otherwise, we ignore additional next hops in nexthop_insert().
*/ */
if (!s->net) if (!s->netA)
{ {
/* Store the new route */ /* Store the new route */
s->net = net; s->netA = n;
s->attrs = ra; s->attrs = ra;
s->proto = p; s->proto = p;
s->new = new; s->new = new;

View File

@ -251,14 +251,14 @@ static inline void
krt_trace_in(struct krt_proto *p, rte *e, char *msg) krt_trace_in(struct krt_proto *p, rte *e, char *msg)
{ {
if (p->p.debug & D_PACKETS) if (p->p.debug & D_PACKETS)
log(L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg); log(L_TRACE "%s: %N: %s", p->p.name, e->netA, msg);
} }
static inline void static inline void
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg) krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
{ {
if (p->p.debug & D_PACKETS) if (p->p.debug & D_PACKETS)
log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg); log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->netA, msg);
} }
/* /*
@ -298,26 +298,24 @@ krt_uptodate(rte *a, rte *b)
static void static void
krt_learn_announce_update(struct krt_proto *p, rte *e) krt_learn_announce_update(struct krt_proto *p, rte *e)
{ {
net *n = e->net;
rta *aa = rta_clone(e->attrs); rta *aa = rta_clone(e->attrs);
rte *ee = rte_get_temp(aa); rte *ee = rte_get_temp(aa);
ee->pflags = 0; ee->pflags = 0;
ee->u.krt = e->u.krt; ee->u.krt = e->u.krt;
rte_update(&p->p, n->n.addr, ee); rte_update(&p->p, e->netA, ee);
} }
static void static void
krt_learn_announce_delete(struct krt_proto *p, net *n) krt_learn_announce_delete(struct krt_proto *p, net_addr *n)
{ {
rte_update(&p->p, n->n.addr, NULL); rte_update(&p->p, n, NULL);
} }
/* Called when alien route is discovered during scan */ /* Called when alien route is discovered during scan */
static void static void
krt_learn_scan(struct krt_proto *p, rte *e) krt_learn_scan(struct krt_proto *p, rte *e)
{ {
net *n0 = e->net; net *n = net_get(&p->krt_table, e->netA);
net *n = net_get(&p->krt_table, n0->n.addr);
rte *m, **mm; rte *m, **mm;
e->attrs = rta_lookup(e->attrs); e->attrs = rta_lookup(e->attrs);
@ -346,6 +344,7 @@ krt_learn_scan(struct krt_proto *p, rte *e)
if (!m) if (!m)
{ {
e->next = n->routes; e->next = n->routes;
e->netA = n->n.addr;
n->routes = e; n->routes = e;
e->u.krt.seen = 1; e->u.krt.seen = 1;
} }
@ -401,7 +400,7 @@ again:
{ {
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen); DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
if (old_best) if (old_best)
krt_learn_announce_delete(p, n); krt_learn_announce_delete(p, n->n.addr);
FIB_ITERATE_PUT(&fit); FIB_ITERATE_PUT(&fit);
fib_delete(fib, n); fib_delete(fib, n);
@ -429,8 +428,7 @@ again:
static void static void
krt_learn_async(struct krt_proto *p, rte *e, int new) krt_learn_async(struct krt_proto *p, rte *e, int new)
{ {
net *n0 = e->net; net *n = net_get(&p->krt_table, e->netA);
net *n = net_get(&p->krt_table, n0->n.addr);
rte *g, **gg, *best, **bestp, *old_best; rte *g, **gg, *best, **bestp, *old_best;
e->attrs = rta_lookup(e->attrs); e->attrs = rta_lookup(e->attrs);
@ -458,6 +456,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
e->next = n->routes; e->next = n->routes;
n->routes = e; n->routes = e;
e->netA = n->n.addr;
} }
else if (!g) else if (!g)
{ {
@ -499,7 +498,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
if (best) if (best)
krt_learn_announce_update(p, best); krt_learn_announce_update(p, best);
else else
krt_learn_announce_delete(p, n); krt_learn_announce_delete(p, n->n.addr);
} }
} }
@ -539,6 +538,15 @@ krt_dump_attrs(rte *e)
* Routes * Routes
*/ */
static void
krt_replace_net_rte(struct krt_proto *p, net *net, rte *new, rte *old)
{
if (krt_replace_rte(p, new, old))
net->n.flags &= ~KRF_SYNC_ERROR;
else
net->n.flags |= KRF_SYNC_ERROR;
}
static void static void
krt_flush_routes(struct krt_proto *p) krt_flush_routes(struct krt_proto *p)
{ {
@ -551,7 +559,7 @@ krt_flush_routes(struct krt_proto *p)
if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED)) if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
{ {
/* FIXME: this does not work if gw is changed in export filter */ /* FIXME: this does not work if gw is changed in export filter */
krt_replace_rte(p, e->net, NULL, e); krt_replace_net_rte(p, n, NULL, e);
n->n.flags &= ~KRF_INSTALLED; n->n.flags &= ~KRF_INSTALLED;
} }
} }
@ -621,8 +629,8 @@ krt_same_dest(rte *k, rte *e)
void void
krt_got_route(struct krt_proto *p, rte *e) krt_got_route(struct krt_proto *p, rte *e)
{ {
net *net = e->net;
int verdict; int verdict;
net *net = net_get(p->p.main_channel->table, e->netA);
#ifdef KRT_ALLOW_LEARN #ifdef KRT_ALLOW_LEARN
switch (e->u.krt.src) switch (e->u.krt.src)
@ -697,6 +705,7 @@ krt_got_route(struct krt_proto *p, rte *e)
e->attrs = rta_lookup(a); e->attrs = rta_lookup(a);
e->next = net->routes; e->next = net->routes;
net->routes = e; net->routes = e;
e->netA = net->n.addr;
} }
else else
rte_free(e); rte_free(e);
@ -739,7 +748,7 @@ krt_prune(struct krt_proto *p)
if (new && (n->n.flags & KRF_INSTALLED)) if (new && (n->n.flags & KRF_INSTALLED))
{ {
krt_trace_in(p, new, "reinstalling"); krt_trace_in(p, new, "reinstalling");
krt_replace_rte(p, n, new, NULL); krt_replace_net_rte(p, n, new, NULL);
} }
break; break;
case KRF_SEEN: case KRF_SEEN:
@ -748,11 +757,11 @@ krt_prune(struct krt_proto *p)
break; break;
case KRF_UPDATE: case KRF_UPDATE:
krt_trace_in(p, new, "updating"); krt_trace_in(p, new, "updating");
krt_replace_rte(p, n, new, old); krt_replace_net_rte(p, n, new, old);
break; break;
case KRF_DELETE: case KRF_DELETE:
krt_trace_in(p, old, "deleting"); krt_trace_in(p, old, "deleting");
krt_replace_rte(p, n, NULL, old); krt_replace_net_rte(p, n, NULL, old);
break; break;
default: default:
bug("krt_prune: invalid route status"); bug("krt_prune: invalid route status");
@ -779,8 +788,6 @@ krt_prune(struct krt_proto *p)
void void
krt_got_route_async(struct krt_proto *p, rte *e, int new) krt_got_route_async(struct krt_proto *p, rte *e, int new)
{ {
net *net = e->net;
switch (e->u.krt.src) switch (e->u.krt.src)
{ {
case KRT_SRC_BIRD: case KRT_SRC_BIRD:
@ -791,7 +798,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
if (new) if (new)
{ {
krt_trace_in(p, e, "[redirect] deleting"); krt_trace_in(p, e, "[redirect] deleting");
krt_replace_rte(p, net, NULL, e); krt_replace_rte(p, NULL, e);
} }
/* If !new, it is probably echo of our deletion */ /* If !new, it is probably echo of our deletion */
break; break;
@ -957,8 +964,9 @@ krt_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
* We will remove KRT_INSTALLED flag, which stops such withdraw to be * We will remove KRT_INSTALLED flag, which stops such withdraw to be
* processed in krt_rt_notify() and krt_replace_rte(). * processed in krt_rt_notify() and krt_replace_rte().
*/ */
if (e == e->net->routes) struct network *n = RTE_NET(e);
e->net->n.flags &= ~KRF_INSTALLED; if (e == n->routes)
n->n.flags &= ~KRF_INSTALLED;
#endif #endif
return -1; return -1;
} }
@ -984,7 +992,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
else else
net->n.flags &= ~KRF_INSTALLED; net->n.flags &= ~KRF_INSTALLED;
if (p->initialized) /* Before first scan we don't touch the routes */ if (p->initialized) /* Before first scan we don't touch the routes */
krt_replace_rte(p, net, new, old); krt_replace_net_rte(p, net, new, old);
} }
static void static void

View File

@ -139,7 +139,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
int krt_capable(rte *e); int krt_capable(rte *e);
void krt_do_scan(struct krt_proto *); void krt_do_scan(struct krt_proto *);
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old); int krt_replace_rte(struct krt_proto *p, rte *new, rte *old);
int krt_sys_get_attr(eattr *a, byte *buf, int buflen); int krt_sys_get_attr(eattr *a, byte *buf, int buflen);