]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'f15f2fcee7eeb5a100bd204a0e67018e25953420' into haugesund
authorMaria Matejka <mq@ucw.cz>
Mon, 30 May 2022 15:36:36 +0000 (17:36 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 30 May 2022 15:37:08 +0000 (17:37 +0200)
15 files changed:
1  2 
filter/f-inst.c
lib/route.h
nest/rt-dev.c
nest/rt-show.c
nest/rt-table.c
proto/babel/babel.c
proto/bgp/packets.c
proto/ospf/rt.c
proto/ospf/topology.c
proto/ospf/topology.h
proto/perf/perf.c
proto/rip/rip.c
proto/static/static.c
sysdep/linux/netlink.c
sysdep/unix/krt.c

diff --cc filter/f-inst.c
index caf473f0f92b471b9a9327dde1c137d8b0be30a3,8ce78a998e63f72d9d00ae4359bbfa1a8be64cd1..b276387fe43c452de6b15a35218ef609c7c5711d
      {
        STATIC_ATTR;
        ACCESS_RTE;
 -      struct rta *rta = (*fs->rte)->attrs;
+       ACCESS_EATTRS;
 +      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);
+         }
+       }
        }
      }
    }
  
      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 lib/route.h
Simple merge
diff --cc nest/rt-dev.c
index b0ad34e66766aa43a677bce89ce490f9e72afb21,9953e2702050b84b017c1d8bdf0c02ab1b2fca0e..107f67a795cc2ab52a4068d536c7d4a4e4b85576
@@@ -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-show.c
Simple merge
diff --cc nest/rt-table.c
index ba4f51153283f8eb5578ce56557f9acd4400d597,6f948adadc1cb4edcc48cb98609589ac7a83ba95..d43305c99bab1b6efc72263d1a9f915d3941c35c
@@@ -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;
index be75694fd4bcce6dbfa99d6f3a7316292ed2fe5d,9a43f484fe5c313a97e4adf249bf8ef384f99519..f3456369a10213a81c10bacab4590e3fe8a087af
@@@ -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))
    {
Simple merge
diff --cc proto/ospf/rt.c
Simple merge
index 81207e6885dc063b86977e2ddcd61bec16a36b57,ca4620cca9b145a1bf40f7fd9185029a812c87fa..c2b12cfc4c90c0d2bcff81104a17572cec1d6a85
@@@ -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))
Simple merge
Simple merge
diff --cc proto/rip/rip.c
Simple merge
Simple merge
index 9c78ca48f8c379a99f54a7118980edf0f4021970,fdfd48855fe1a84398289487717a564cb2c84be8..e63fe938246e562655e78fc5e829a7b09131df2c
@@@ -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");
  
        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;
        }
  
            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;
            }
        }
    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;
Simple merge