From: Maria Matejka Date: Mon, 30 May 2022 15:36:36 +0000 (+0200) Subject: Merge commit 'f15f2fcee7eeb5a100bd204a0e67018e25953420' into haugesund X-Git-Tag: v3.0-alpha1~171^2~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1493695c6ba2b169523f7c2097fac8e8343352fe;p=thirdparty%2Fbird.git Merge commit 'f15f2fcee7eeb5a100bd204a0e67018e25953420' into haugesund --- 1493695c6ba2b169523f7c2097fac8e8343352fe diff --cc filter/f-inst.c index caf473f0f,8ce78a998..b276387fe --- a/filter/f-inst.c +++ b/filter/f-inst.c @@@ -529,21 -529,40 +529,40 @@@ { STATIC_ATTR; ACCESS_RTE; + ACCESS_EATTRS; - struct rta *rta = (*fs->rte)->attrs; + struct rta *rta = fs->rte->attrs; switch (sa.sa_code) { - case SA_GW: RESULT(sa.type, ip, rta->nh.gw); break; - case SA_NET: RESULT(sa.type, net, (*fs->rte)->net->n.addr); break; - case SA_PROTO: RESULT(sa.type, s, (*fs->rte)->src->proto->name); break; + case SA_NET: RESULT(sa.type, net, fs->rte->net); break; + case SA_PROTO: RESULT(sa.type, s, fs->rte->src->proto->name); break; case SA_DEST: RESULT(sa.type, i, rta->dest); break; - case SA_IFNAME: RESULT(sa.type, s, rta->nh.iface ? rta->nh.iface->name : ""); break; - case SA_IFINDEX: RESULT(sa.type, i, rta->nh.iface ? rta->nh.iface->index : 0); break; - case SA_WEIGHT: RESULT(sa.type, i, rta->nh.weight + 1); break; - case SA_GW_MPLS: RESULT(sa.type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break; - default: - bug("Invalid static attribute access (%u/%u)", sa.type, sa.sa_code); + { + struct eattr *nh_ea = ea_find(*fs->eattrs, &ea_gen_nexthop); + struct nexthop *nh = nh_ea ? &((struct nexthop_adata *) nh_ea->u.ptr)->nh : NULL; + + switch (sa.sa_code) + { + case SA_GW: + RESULT(sa.type, ip, nh ? nh->gw : IPA_NONE); + break; + case SA_IFNAME: + RESULT(sa.type, s, (nh && nh->iface) ? nh->iface->name : ""); + break; + case SA_IFINDEX: + RESULT(sa.type, i, (nh && nh->iface) ? nh->iface->index : 0); + break; + case SA_WEIGHT: + RESULT(sa.type, i, (nh ? nh->weight : 0) + 1); + break; + case SA_GW_MPLS: + RESULT(sa.type, i, (nh && nh->labels) ? nh->label[0] : MPLS_NULL); + break; + default: + bug("Invalid static attribute access (%u/%u)", sa.type, sa.sa_code); + } + } } } } @@@ -556,15 -576,45 +576,45 @@@ f_rta_cow(fs); { - struct rta *rta = (*fs->rte)->attrs; + struct rta *rta = fs->rte->attrs; - switch (sa.sa_code) + if (sa.sa_code == SA_DEST) + { + int i = v1.val.i; + if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT)) + runtime( "Destination can be changed only to blackhole, unreachable or prohibit" ); + + rta->dest = i; + ea_unset_attr(fs->eattrs, 1, &ea_gen_nexthop); + } + else { + union { + struct nexthop_adata nha; + struct { + struct adata ad; + struct nexthop nh; + u32 label; + }; + } nha; + + nha.ad = (struct adata) { + .length = sizeof (struct nexthop_adata) - sizeof (struct adata), + }; + + eattr *a = NULL; + + switch (sa.sa_code) + { case SA_GW: { + struct eattr *nh_ea = ea_find(*fs->eattrs, &ea_gen_nexthop); + ip_addr ip = v1.val.ip; - struct iface *ifa = ipa_is_link_local(ip) ? rta->nh.iface : NULL; + struct iface *ifa = (ipa_is_link_local(ip) && nh_ea) ? + ((struct nexthop_adata *) nh_ea->u.ptr)->nh.iface : NULL; + - neighbor *n = neigh_find((*fs->rte)->src->proto, ip, ifa, 0); + neighbor *n = neigh_find(fs->rte->src->proto, ip, ifa, 0); if (!n || (n->scope == SCOPE_HOST)) runtime( "Invalid gw address" ); diff --cc nest/rt-dev.c index b0ad34e66,9953e2702..107f67a79 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@@ -86,13 -93,12 +90,14 @@@ dev_ifa_notify(struct proto *P, uint fl ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, c->preference); ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_DEVICE); + ea_set_attr_data(&a0.eattrs, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length); - a = rta_lookup(&a0); - e = rte_get_temp(a, src); - e->pflags = 0; - rte_update2(c, net, e, src); + rte e0 = { + .attrs = rta_lookup(&a0), + .src = src, + }; + + rte_update(c, net, &e0, src); } } diff --cc nest/rt-table.c index ba4f51153,6f948adad..d43305c99 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@@ -910,100 -913,92 +910,100 @@@ rt_notify_accepted(struct rt_export_req } } - /* Find new_best */ - if ((new_changed == old_changed) || (old_best == old_changed)) - { - /* Feed or old_best changed -> find first accepted by filters */ - for (rte *r = net->routes; rte_is_valid(r); r = r->next) - if (new_best = export_filter(c, r, &new_free, 0)) + /* Check obsolete routes for previously exported */ + if (!old_best) + if (rpe && rpe->old && bmap_test(&c->export_map, rpe->old->rte.id)) + old_best = &rpe->old->rte; + +/* for (; rpe; rpe = atomic_load_explicit(&rpe->next, memory_order_relaxed)) + { + if (rpe->old && bmap_test(&hook->accept_map, rpe->old->id)) + { + old_best = &rpe->old.rte; break; - } - else - { - /* Other cases -> either new_changed, or old_best (and nothing changed) */ - if (new_first && (new_changed = export_filter(c, new_changed, &new_free, 0))) - new_best = new_changed; - else - return; - } + } + if (rpe == rpe_last) + break; + } + */ + + /* Nothing to export */ if (!new_best && !old_best) - return; + { + DBG("rt_notify_accepted: nothing to export\n"); + goto done; + } - do_rt_notify(c, net, new_best, old_best, refeed); + do_rt_notify(c, n, new_best, old_best); - /* Discard temporary rte */ - if (new_free) - rte_free(new_free); +done: + /* Drop the old stored rejection if applicable. + * new->id == old->id happens when updating hostentries. */ + if (rpe && rpe->old && (!rpe->new || (rpe->new->rte.id != rpe->old->rte.id))) + bmap_clear(&c->export_reject_map, rpe->old->rte.id); } - - static struct nexthop * - nexthop_merge_rta(struct nexthop *nhs, rta *a, linpool *pool, int max) - { - return nexthop_merge(nhs, &(a->nh), 1, 0, max, pool); - } - rte * -rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent) +rt_export_merged(struct channel *c, struct rte **feed, uint count, linpool *pool, int silent) { + _Thread_local static rte rloc; + // struct proto *p = c->proto; - struct nexthop *nhs = NULL; + struct nexthop_adata *nhs = NULL; - rte *best0, *best, *rt0, *rt, *tmp; - - best0 = net->routes; - *rt_free = NULL; + rte *best0 = feed[0]; + rte *best = NULL; if (!rte_is_valid(best0)) return NULL; - best = export_filter(c, best0, rt_free, silent); + /* Already rejected, no need to re-run the filter */ + if (!c->refeeding && bmap_test(&c->export_reject_map, best0->id)) + return NULL; + + rloc = *best0; + best = export_filter(c, &rloc, silent); + + if (!best) + /* Best route doesn't pass the filter */ + return NULL; - if (!best || !rte_is_reachable(best)) + if (!rte_is_reachable(best)) + /* Unreachable routes can't be merged */ return best; - for (rt0 = best0->next; rt0; rt0 = rt0->next) + for (uint i = 1; i < count; i++) { - if (!rte_mergable(best0, rt0)) + if (!rte_mergable(best0, feed[i])) continue; - rt = export_filter(c, rt0, &tmp, 1); + rte tmp0 = *feed[i]; + rte *tmp = export_filter(c, &tmp0, 1); - if (!rt) + if (!tmp || !rte_is_reachable(tmp)) continue; - nhs = nexthop_merge_rta(nhs, tmp->attrs, pool, c->merge_limit); - if (rte_is_reachable(rt)) - { - eattr *nhea = ea_find(rt->attrs->eattrs, &ea_gen_nexthop); - ASSERT_DIE(nhea); - - if (nhs) - nhs = nexthop_merge(nhs, (struct nexthop_adata *) nhea->u.ptr, c->merge_limit, pool); - else - nhs = (struct nexthop_adata *) nhea->u.ptr; - } ++ eattr *nhea = ea_find(tmp->attrs->eattrs, &ea_gen_nexthop); ++ ASSERT_DIE(nhea); + - if (tmp) - rte_free(tmp); ++ if (nhs) ++ nhs = nexthop_merge(nhs, (struct nexthop_adata *) nhea->u.ptr, c->merge_limit, pool); ++ else ++ nhs = (struct nexthop_adata *) nhea->u.ptr; } - if (nhs) { - nhs = nexthop_merge_rta(nhs, best->attrs, pool, c->merge_limit); + eattr *nhea = ea_find(best->attrs->eattrs, &ea_gen_nexthop); + ASSERT_DIE(nhea); - if (nhs->next) - { - best->attrs = rta_cow(best->attrs, pool); - nexthop_link(best->attrs, nhs); - } + nhs = nexthop_merge(nhs, (struct nexthop_adata *) nhea->u.ptr, c->merge_limit, pool); + - best = rte_cow_rta(best, pool); ++ best->attrs = rta_cow(best->attrs, pool); + ea_set_attr(&best->attrs->eattrs, + EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nhs->ad)); } - if (best != best0) - *rt_free = best; - return best; } @@@ -1234,10 -1187,19 +1234,19 @@@ rte_validate(struct channel *ch, rte *e return 0; } - if ((e->attrs->dest == RTD_UNICAST) && !nexthop_is_sorted(&(e->attrs->nh))) + eattr *nhea = ea_find(e->attrs->eattrs, &ea_gen_nexthop); + if ((!nhea) != (e->attrs->dest != RTD_UNICAST)) + { + log(L_WARN "Ignoring route %N with destination %d and %snexthop received via %s", - n->n.addr, e->attrs->dest, (nhea ? "" : "no "), e->sender->proto->name); ++ n, e->attrs->dest, (nhea ? "" : "no "), ch->proto->name); + return 0; + } + + if ((e->attrs->dest == RTD_UNICAST) && + !nexthop_is_sorted((struct nexthop_adata *) nhea->u.ptr)) { log(L_WARN "Ignoring unsorted multipath route %N received via %s", - n->n.addr, e->sender->proto->name); + n, ch->proto->name); return 0; } @@@ -2604,13 -2493,18 +2609,18 @@@ rta_next_hop_outdated(rta *a if (!he->src) return a->dest != RTD_UNREACHABLE; + eattr *he_nh_ea = ea_find(he->src->eattrs, &ea_gen_nexthop); + eattr *a_nh_ea = ea_find(a->eattrs, &ea_gen_nexthop); + return (a->dest != he->dest) || (ea_get_int(a->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN) != he->igp_metric) || - (!he->nexthop_linkable) || !nexthop_same(&(a->nh), &(he->src->nh)); + (!he->nexthop_linkable) || + (!he_nh_ea != !a_nh_ea) || + (he_nh_ea && a_nh_ea && !adata_same(he_nh_ea->u.ptr, a_nh_ea->u.ptr)); } -static inline rte * -rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) +static inline struct rte_storage * +rt_next_hop_update_rte(rtable *tab, net *n, rte *old) { if (!rta_next_hop_outdated(old->attrs)) return NULL; diff --cc proto/babel/babel.c index be75694fd,9a43f484f..f3456369a --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@@ -663,23 -682,11 +682,13 @@@ babel_announce_rte(struct babel_proto * .eattrs = &eattrs.l, }; - /* - * If we cannot find a reachable neighbour, set the entry to be onlink. This - * makes it possible to, e.g., assign /32 addresses on a mesh interface and - * have routing work. - */ - if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0)) - a0.nh.flags = RNF_ONLINK; - - rta *a = rta_lookup(&a0); - rte *rte = rte_get_temp(a, p->p.main_source); + rte e0 = { + .attrs = &a0, + .src = p->p.main_source, + }; e->unreachable = 0; - rte_update2(c, e->n.addr, rte, p->p.main_source); + rte_update(c, e->n.addr, &e0, p->p.main_source); } else if (e->valid && (e->router_id != p->router_id)) { diff --cc proto/ospf/topology.c index 81207e688,ca4620cca..c2b12cfc4 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@@ -1366,8 -1366,20 +1366,20 @@@ ospf_rt_notify(struct proto *P, struct uint tag = ea_get_int(a->eattrs, &ea_ospf_tag, 0); ip_addr fwd = IPA_NONE; - if ((a->dest == RTD_UNICAST) && use_gw_for_fwaddr(p, a->nh.gw, a->nh.iface)) - fwd = a->nh.gw; + if (a->dest == RTD_UNICAST) + { + eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); + if (!nhea) + { + log(L_ERR "%s: Unicast route without nexthop for %N", - p->p.name, n->n.addr); ++ p->p.name, n); + return; + } + + struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr; + if (use_gw_for_fwaddr(p, nhad->nh.gw, nhad->nh.iface)) + fwd = nhad->nh.gw; + } /* NSSA-LSA with P-bit set must have non-zero forwarding address */ if (oa && ipa_zero(fwd)) diff --cc sysdep/linux/netlink.c index 9c78ca48f,fdfd48855..e63fe9382 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@@ -1421,12 -1432,14 +1432,13 @@@ nh_bufsize(struct nexthop_adata *nhad } static int - nl_send_route(struct krt_proto *p, const rte *e, int op, int dest, struct nexthop *nh) -nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop_adata *nh) ++nl_send_route(struct krt_proto *p, const rte *e, int op, int dest, struct nexthop_adata *nh) { eattr *ea; - net *net = e->net; rta *a = e->attrs; ea_list *eattrs = a->eattrs; - int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh)); + + int bufsize = 128 + KRT_METRICS_MAX*8 + (nh ? nh_bufsize(nh) : 0); u32 priority = 0; struct { @@@ -1867,7 -1905,7 +1904,7 @@@ nl_parse_route(struct nl_parse_state *s if (a[RTA_MULTIPATH]) { - struct nexthop *nh = nl_parse_multipath(s, p, net, a[RTA_MULTIPATH], i->rtm_family, krt_src); - struct nexthop_adata *nh = nl_parse_multipath(s, p, n, a[RTA_MULTIPATH], i->rtm_family, krt_src); ++ struct nexthop_adata *nh = nl_parse_multipath(s, p, net, a[RTA_MULTIPATH], i->rtm_family, krt_src); if (!nh) SKIP("strange RTA_MULTIPATH\n"); @@@ -1878,10 -1917,10 +1916,10 @@@ if ((i->rtm_flags & RTNH_F_DEAD) && (krt_src != KRT_SRC_BIRD)) SKIP("ignore RTNH_F_DEAD\n"); - ra->nh.iface = if_find_by_index(oif); - if (!ra->nh.iface) + nhad.nh.iface = if_find_by_index(oif); + if (!nhad.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", net, oif); return; } @@@ -1901,14 -1940,15 +1939,15 @@@ return; if (i->rtm_flags & RTNH_F_ONLINK) - ra->nh.flags |= RNF_ONLINK; + nhad.nh.flags |= RNF_ONLINK; neighbor *nbr; - nbr = neigh_find(&p->p, ra->nh.gw, ra->nh.iface, - (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); + nbr = neigh_find(&p->p, nhad.nh.gw, nhad.nh.iface, + (nhad.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, ra->nh.gw); - 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", net, + nhad.nh.gw); return; } } @@@ -1995,10 -2038,12 +2037,14 @@@ if (!s->net) { /* Store the new route */ - s->net = net; + s->net = lp_alloc(s->pool, net->length); + net_copy(s->net, net); + s->attrs = ra; + + ea_set_attr_data(&ra->eattrs, &ea_gen_nexthop, 0, + nhad.ad.data, nhad.ad.length); + s->proto = p; s->new = new; s->krt_src = krt_src;