mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +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:
parent
4b7f14aaa6
commit
9d798cd843
@ -942,7 +942,7 @@ interpret(struct f_inst *what)
|
||||
{
|
||||
case SA_FROM: res.val.ip = rta->from; 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_SOURCE: res.val.i = rta->source; break;
|
||||
case SA_SCOPE: res.val.i = rta->scope; break;
|
||||
@ -1531,7 +1531,7 @@ interpret(struct f_inst *what)
|
||||
{
|
||||
ACCESS_RTE;
|
||||
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 */
|
||||
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
|
||||
|
@ -207,7 +207,7 @@ struct hostentry {
|
||||
|
||||
typedef struct rte {
|
||||
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 rta *attrs; /* Attributes of this route */
|
||||
byte flags; /* Flags (REF_...) */
|
||||
@ -258,6 +258,8 @@ typedef struct rte {
|
||||
#define REF_DISCARD 8 /* Route is scheduled for discard */
|
||||
#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 */
|
||||
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
|
||||
|
||||
|
@ -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 tm[TM_DATETIME_BUFFER_SIZE], info[256];
|
||||
rta *a = e->attrs;
|
||||
int primary = (e->net->routes == e);
|
||||
int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
|
||||
net *nn = RTE_NET(e);
|
||||
int primary = nn && (nn->routes == e);
|
||||
int sync_error = nn && (nn->n.flags & KRF_SYNC_ERROR);
|
||||
void (*get_route_info)(struct rte *, byte *buf);
|
||||
struct nexthop *nh;
|
||||
|
||||
|
@ -376,7 +376,7 @@ rte_mergable(rte *pri, rte *sec)
|
||||
static void
|
||||
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
|
||||
@ -923,36 +923,36 @@ static inline int
|
||||
rte_validate(rte *e)
|
||||
{
|
||||
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",
|
||||
n->n.addr, e->sender->proto->name);
|
||||
n, e->sender->proto->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: better handling different nettypes */
|
||||
c = !net_is_flow(n->n.addr) ?
|
||||
net_classify(n->n.addr): (IADDR_HOST | SCOPE_UNIVERSE);
|
||||
c = !net_is_flow(n) ?
|
||||
net_classify(n): (IADDR_HOST | SCOPE_UNIVERSE);
|
||||
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||
{
|
||||
log(L_WARN "Ignoring bogus route %N received via %s",
|
||||
n->n.addr, e->sender->proto->name);
|
||||
n, e->sender->proto->name);
|
||||
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",
|
||||
n->n.addr, e->attrs->dest, e->sender->proto->name);
|
||||
n, e->attrs->dest, e->sender->proto->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((e->attrs->dest == RTD_UNICAST) && !nexthop_is_sorted(&(e->attrs->nh)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1346,9 +1346,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||
rte_update_lock();
|
||||
if (new)
|
||||
{
|
||||
nn = net_get(c->table, n);
|
||||
|
||||
new->net = nn;
|
||||
new->netA = n;
|
||||
new->sender = c;
|
||||
|
||||
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 */
|
||||
new->attrs = rta_lookup(new->attrs);
|
||||
new->flags |= REF_COW;
|
||||
|
||||
new->netA = (nn = net_get(c->table, n))->n.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1420,7 +1420,12 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||
drop:
|
||||
rte_free(new);
|
||||
new = NULL;
|
||||
goto recalc;
|
||||
|
||||
if ((nn = net_find(c->table, n)) && src)
|
||||
goto recalc;
|
||||
|
||||
rte_update_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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
|
||||
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_recalculate(old->sender, old->net, NULL, old->attrs->src);
|
||||
rte_recalculate(old->sender, n, NULL, old->attrs->src);
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
/* Modify existing route by protocol hook, used for long-lived graceful restart */
|
||||
static inline void
|
||||
rte_modify(rte *old)
|
||||
rte_modify(net *n, rte *old)
|
||||
{
|
||||
rte_update_lock();
|
||||
|
||||
@ -1458,7 +1463,7 @@ rte_modify(rte *old)
|
||||
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();
|
||||
@ -1580,9 +1585,13 @@ rt_modify_stale(rtable *t, struct channel *c)
|
||||
void
|
||||
rte_dump(rte *e)
|
||||
{
|
||||
net *n = e->net;
|
||||
debug("%-1N ", n->n.addr);
|
||||
debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
|
||||
debug("%-1N ", e->netA);
|
||||
net *n = RTE_NET(e);
|
||||
if (n)
|
||||
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);
|
||||
if (e->attrs->src->proto->proto->dump_attrs)
|
||||
e->attrs->src->proto->proto->dump_attrs(e);
|
||||
@ -1769,7 +1778,7 @@ again:
|
||||
return;
|
||||
}
|
||||
|
||||
rte_discard(e);
|
||||
rte_discard(n, e);
|
||||
limit--;
|
||||
|
||||
goto rescan;
|
||||
@ -1784,7 +1793,7 @@ again:
|
||||
return;
|
||||
}
|
||||
|
||||
rte_modify(e);
|
||||
rte_modify(n, e);
|
||||
limit--;
|
||||
|
||||
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 */
|
||||
rte *e = rte_do_cow(new);
|
||||
e->flags |= REF_COW;
|
||||
e->net = net;
|
||||
e->netA = net->n.addr;
|
||||
e->sender = c;
|
||||
e->lastmod = current_time();
|
||||
e->next = *pos;
|
||||
|
@ -627,7 +627,7 @@ bgp_decode_large_community(struct bgp_parse_state *s, uint code UNUSED, uint fla
|
||||
static void
|
||||
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;
|
||||
uint lnum = a->u.ptr->length / 4;
|
||||
|
||||
|
@ -459,7 +459,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -390,9 +390,9 @@ radv_trigger_valid(struct radv_config *cf)
|
||||
}
|
||||
|
||||
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
|
||||
@ -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_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;
|
||||
|
||||
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;
|
||||
eattr *ea;
|
||||
|
||||
if (radv_net_match_trigger(cf, n))
|
||||
if (radv_net_match_trigger(cf, n->n.addr))
|
||||
{
|
||||
u8 old_active = p->active;
|
||||
p->active = !!new;
|
||||
|
@ -199,7 +199,7 @@ sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa)
|
||||
static int
|
||||
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;
|
||||
static int msg_seq;
|
||||
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;
|
||||
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));
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
else
|
||||
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;
|
||||
|
||||
switch (net->n.addr->type) {
|
||||
switch (n->type) {
|
||||
case NET_IP4:
|
||||
af = AF_INET;
|
||||
break;
|
||||
@ -268,12 +268,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||
af = AF_INET6;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0);
|
||||
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
|
||||
sockaddr_fill(&dst, af, net_prefix(n), NULL, 0);
|
||||
sockaddr_fill(&mask, af, net_pxmask(n), NULL, 0);
|
||||
|
||||
switch (a->dest)
|
||||
{
|
||||
@ -303,7 +303,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||
|
||||
#if __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)
|
||||
{
|
||||
@ -339,15 +339,15 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||
msg.rtm.rtm_msglen = l;
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
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 err = 0;
|
||||
|
||||
@ -357,10 +357,7 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
|
||||
if (new)
|
||||
err = krt_send_route(p, RTM_ADD, new);
|
||||
|
||||
if (err < 0)
|
||||
n->n.flags |= KRF_SYNC_ERROR;
|
||||
else
|
||||
n->n.flags &= ~KRF_SYNC_ERROR;
|
||||
return (err >= 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;
|
||||
rte *e;
|
||||
net *net;
|
||||
sockaddr dst, gate, mask;
|
||||
ip_addr idst, igate, imask;
|
||||
net_addr ndst;
|
||||
@ -489,8 +485,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||
else
|
||||
src = KRT_SRC_KERNEL;
|
||||
|
||||
net = net_get(p->p.main_channel->table, &ndst);
|
||||
|
||||
rta a = {
|
||||
.src = p->p.main_source,
|
||||
.source = RTS_INHERIT,
|
||||
@ -518,7 +512,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||
if (!a.nh.iface)
|
||||
{
|
||||
log(L_ERR "KRT: Received route %N with unknown ifindex %u",
|
||||
net->n.addr, msg->rtm.rtm_index);
|
||||
&ndst, msg->rtm.rtm_index);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -541,14 +535,14 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||
return;
|
||||
|
||||
log(L_ERR "KRT: Received route %N with strange next-hop %I",
|
||||
net->n.addr, a.nh.gw);
|
||||
&ndst, a.nh.gw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
e = rte_get_temp(&a);
|
||||
e->net = net;
|
||||
e->netA = &ndst;
|
||||
e->u.krt.src = src;
|
||||
e->u.krt.proto = src2;
|
||||
e->u.krt.seen = 0;
|
||||
|
@ -104,7 +104,7 @@ struct nl_parse_state
|
||||
int scan;
|
||||
int merge;
|
||||
|
||||
net *net;
|
||||
const net_addr *netA;
|
||||
rta *attrs;
|
||||
struct krt_proto *proto;
|
||||
s8 new;
|
||||
@ -1180,7 +1180,7 @@ static int
|
||||
nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
||||
{
|
||||
eattr *ea;
|
||||
net *net = e->net;
|
||||
const net_addr *n = e->netA;
|
||||
rta *a = e->attrs;
|
||||
ea_list *eattrs = a->eattrs;
|
||||
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;
|
||||
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->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->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_scope = RT_SCOPE_NOWHERE;
|
||||
#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
|
||||
*/
|
||||
|
||||
u32 label = net_mpls(net->n.addr);
|
||||
u32 label = net_mpls(n);
|
||||
nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
|
||||
r->r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
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
|
||||
#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 */
|
||||
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);
|
||||
r->r.rtm_src_len = a->src_pxlen;
|
||||
}
|
||||
@ -1364,8 +1364,8 @@ nl_delete_rte(struct krt_proto *p, rte *e)
|
||||
return err;
|
||||
}
|
||||
|
||||
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 err = 0;
|
||||
|
||||
@ -1386,21 +1386,18 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
|
||||
if (new)
|
||||
err = nl_add_rte(p, new);
|
||||
|
||||
if (err < 0)
|
||||
n->n.flags |= KRF_SYNC_ERROR;
|
||||
else
|
||||
n->n.flags &= ~KRF_SYNC_ERROR;
|
||||
return (err >= 0);
|
||||
}
|
||||
|
||||
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 */
|
||||
if (!s->merge)
|
||||
return 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Both must be regular unicast routes */
|
||||
@ -1414,7 +1411,7 @@ static void
|
||||
nl_announce_route(struct nl_parse_state *s)
|
||||
{
|
||||
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.proto = s->krt_proto;
|
||||
e->u.krt.seen = 0;
|
||||
@ -1426,7 +1423,7 @@ nl_announce_route(struct nl_parse_state *s)
|
||||
else
|
||||
krt_got_route_async(s->proto, e, s->new);
|
||||
|
||||
s->net = NULL;
|
||||
s->netA = NULL;
|
||||
s->attrs = NULL;
|
||||
s->proto = NULL;
|
||||
lp_flush(s->pool);
|
||||
@ -1444,7 +1441,7 @@ nl_parse_begin(struct nl_parse_state *s, int scan, int merge)
|
||||
static inline void
|
||||
nl_parse_end(struct nl_parse_state *s)
|
||||
{
|
||||
if (s->net)
|
||||
if (s->netA)
|
||||
nl_announce_route(s);
|
||||
}
|
||||
|
||||
@ -1571,18 +1568,21 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||
krt_src = KRT_SRC_ALIEN;
|
||||
}
|
||||
|
||||
net_addr *n = &dst;
|
||||
net_addr *nloc;
|
||||
if (p->p.net_type == NET_IP6_SADR)
|
||||
{
|
||||
n = alloca(sizeof(net_addr_ip6_sadr));
|
||||
net_fill_ip6_sadr(n, net6_prefix(&dst), net6_pxlen(&dst),
|
||||
net6_prefix(&src), net6_pxlen(&src));
|
||||
}
|
||||
{
|
||||
nloc = alloca(sizeof(net_addr_ip6_sadr));
|
||||
net_fill_ip6_sadr(nloc, net6_prefix(&dst), net6_pxlen(&dst),
|
||||
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))
|
||||
nl_announce_route(s);
|
||||
net_addr *n = lp_alloc(s->pool, dst.length);
|
||||
net_copy(n, nloc);
|
||||
|
||||
rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1610,7 +1610,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||
ra->nh.iface = if_find_by_index(oif);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1640,7 +1640,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||
(ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1776,10 +1776,10 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||
* Otherwise, we ignore additional next hops in nexthop_insert().
|
||||
*/
|
||||
|
||||
if (!s->net)
|
||||
if (!s->netA)
|
||||
{
|
||||
/* Store the new route */
|
||||
s->net = net;
|
||||
s->netA = n;
|
||||
s->attrs = ra;
|
||||
s->proto = p;
|
||||
s->new = new;
|
||||
|
@ -251,14 +251,14 @@ static inline void
|
||||
krt_trace_in(struct krt_proto *p, rte *e, char *msg)
|
||||
{
|
||||
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
|
||||
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
|
||||
{
|
||||
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
|
||||
krt_learn_announce_update(struct krt_proto *p, rte *e)
|
||||
{
|
||||
net *n = e->net;
|
||||
rta *aa = rta_clone(e->attrs);
|
||||
rte *ee = rte_get_temp(aa);
|
||||
ee->pflags = 0;
|
||||
ee->u.krt = e->u.krt;
|
||||
rte_update(&p->p, n->n.addr, ee);
|
||||
rte_update(&p->p, e->netA, ee);
|
||||
}
|
||||
|
||||
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 */
|
||||
static void
|
||||
krt_learn_scan(struct krt_proto *p, rte *e)
|
||||
{
|
||||
net *n0 = e->net;
|
||||
net *n = net_get(&p->krt_table, n0->n.addr);
|
||||
net *n = net_get(&p->krt_table, e->netA);
|
||||
rte *m, **mm;
|
||||
|
||||
e->attrs = rta_lookup(e->attrs);
|
||||
@ -346,6 +344,7 @@ krt_learn_scan(struct krt_proto *p, rte *e)
|
||||
if (!m)
|
||||
{
|
||||
e->next = n->routes;
|
||||
e->netA = n->n.addr;
|
||||
n->routes = e;
|
||||
e->u.krt.seen = 1;
|
||||
}
|
||||
@ -401,7 +400,7 @@ again:
|
||||
{
|
||||
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
|
||||
if (old_best)
|
||||
krt_learn_announce_delete(p, n);
|
||||
krt_learn_announce_delete(p, n->n.addr);
|
||||
|
||||
FIB_ITERATE_PUT(&fit);
|
||||
fib_delete(fib, n);
|
||||
@ -429,8 +428,7 @@ again:
|
||||
static void
|
||||
krt_learn_async(struct krt_proto *p, rte *e, int new)
|
||||
{
|
||||
net *n0 = e->net;
|
||||
net *n = net_get(&p->krt_table, n0->n.addr);
|
||||
net *n = net_get(&p->krt_table, e->netA);
|
||||
rte *g, **gg, *best, **bestp, *old_best;
|
||||
|
||||
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;
|
||||
n->routes = e;
|
||||
e->netA = n->n.addr;
|
||||
}
|
||||
else if (!g)
|
||||
{
|
||||
@ -499,7 +498,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
|
||||
if (best)
|
||||
krt_learn_announce_update(p, best);
|
||||
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
|
||||
*/
|
||||
|
||||
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
|
||||
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))
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
@ -621,8 +629,8 @@ krt_same_dest(rte *k, rte *e)
|
||||
void
|
||||
krt_got_route(struct krt_proto *p, rte *e)
|
||||
{
|
||||
net *net = e->net;
|
||||
int verdict;
|
||||
net *net = net_get(p->p.main_channel->table, e->netA);
|
||||
|
||||
#ifdef KRT_ALLOW_LEARN
|
||||
switch (e->u.krt.src)
|
||||
@ -635,7 +643,7 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||
verdict = KRF_DELETE;
|
||||
goto sentenced;
|
||||
|
||||
case KRT_SRC_ALIEN:
|
||||
case KRT_SRC_ALIEN:
|
||||
if (KRT_CF->learn)
|
||||
krt_learn_scan(p, e);
|
||||
else
|
||||
@ -697,6 +705,7 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||
e->attrs = rta_lookup(a);
|
||||
e->next = net->routes;
|
||||
net->routes = e;
|
||||
e->netA = net->n.addr;
|
||||
}
|
||||
else
|
||||
rte_free(e);
|
||||
@ -739,7 +748,7 @@ krt_prune(struct krt_proto *p)
|
||||
if (new && (n->n.flags & KRF_INSTALLED))
|
||||
{
|
||||
krt_trace_in(p, new, "reinstalling");
|
||||
krt_replace_rte(p, n, new, NULL);
|
||||
krt_replace_net_rte(p, n, new, NULL);
|
||||
}
|
||||
break;
|
||||
case KRF_SEEN:
|
||||
@ -748,11 +757,11 @@ krt_prune(struct krt_proto *p)
|
||||
break;
|
||||
case KRF_UPDATE:
|
||||
krt_trace_in(p, new, "updating");
|
||||
krt_replace_rte(p, n, new, old);
|
||||
krt_replace_net_rte(p, n, new, old);
|
||||
break;
|
||||
case KRF_DELETE:
|
||||
krt_trace_in(p, old, "deleting");
|
||||
krt_replace_rte(p, n, NULL, old);
|
||||
krt_replace_net_rte(p, n, NULL, old);
|
||||
break;
|
||||
default:
|
||||
bug("krt_prune: invalid route status");
|
||||
@ -779,8 +788,6 @@ krt_prune(struct krt_proto *p)
|
||||
void
|
||||
krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
||||
{
|
||||
net *net = e->net;
|
||||
|
||||
switch (e->u.krt.src)
|
||||
{
|
||||
case KRT_SRC_BIRD:
|
||||
@ -791,7 +798,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
||||
if (new)
|
||||
{
|
||||
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 */
|
||||
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
|
||||
* processed in krt_rt_notify() and krt_replace_rte().
|
||||
*/
|
||||
if (e == e->net->routes)
|
||||
e->net->n.flags &= ~KRF_INSTALLED;
|
||||
struct network *n = RTE_NET(e);
|
||||
if (e == n->routes)
|
||||
n->n.flags &= ~KRF_INSTALLED;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@ -984,7 +992,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
|
||||
else
|
||||
net->n.flags &= ~KRF_INSTALLED;
|
||||
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
|
||||
|
@ -139,7 +139,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
|
||||
|
||||
int krt_capable(rte *e);
|
||||
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);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user