diff --git a/filter/filter.c b/filter/filter.c index 37cf16a3..d3c60a97 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -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 */ diff --git a/nest/route.h b/nest/route.h index 93afae57..ca1b5eb7 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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); } diff --git a/nest/rt-show.c b/nest/rt-show.c index c7bcdf2f..024b5623 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -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; diff --git a/nest/rt-table.c b/nest/rt-table.c index 1cb8d2a1..5f910dcd 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 868caca5..16a3be40 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -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; diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index 95014958..d21bbe8f 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -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; } diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 990b6024..33225bc7 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -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; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index e646c414..ae7ce0e4 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -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; diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 834504d0..557bd150 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -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; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index ded5dfe4..18489826 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -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 diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 6ace2a86..62e32cd8 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -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);