]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '4fe9881d625f10e44109a649e369a413bd98de71' into haugesund
authorMaria Matejka <mq@ucw.cz>
Tue, 31 May 2022 10:51:34 +0000 (12:51 +0200)
committerMaria Matejka <mq@ucw.cz>
Tue, 31 May 2022 10:51:34 +0000 (12:51 +0200)
1  2 
lib/route.h
nest/rt-table.c
nest/rt.h
proto/bgp/bgp.h
proto/bgp/packets.c
proto/pipe/pipe.c
proto/static/static.c

diff --cc lib/route.h
index 1ade1a817b440d77d354153be95b996a5ae785a6,3ce8021dcbf5ded53f35d2c7efc4c4296514a969..613df0c38f660ca9472b3e60586ce58c6d2337cd
@@@ -329,13 -328,9 +330,9 @@@ extern struct ea_class ea_gen_from
  /* Source: An old method to devise the route source protocol and kind.
   * To be superseded in a near future by something more informative. */
  extern struct ea_class ea_gen_source;
 -static inline u32 rt_get_source_attr(rte *rt)
 +static inline u32 rt_get_source_attr(const rte *rt)
  { return ea_get_int(rt->attrs->eattrs, &ea_gen_source, 0); }
  
- /* MPLS labels: Use with a recursive nexthop specification
-  * to add additional labels to the resolved nexthop */
- extern struct ea_class ea_mpls_labels;
  /* Next hop: For now, stored as adata */
  extern struct ea_class ea_gen_nexthop;
  
diff --cc nest/rt-table.c
index d43305c99bab1b6efc72263d1a9f915d3941c35c,d98f33e4dd7dc5ccc73a85aef0744c37f8c1644e..8677c177d3147409223dd866dd30cfcb7001a004
@@@ -121,45 -121,11 +121,47 @@@ static void rt_free_hostcache(rtable *t
  static void rt_notify_hostcache(rtable *tab, net *net);
  static void rt_update_hostcache(rtable *tab);
  static void rt_next_hop_update(rtable *tab);
++static inline void rt_next_hop_resolve_rte(rte *r);
  static inline void rt_prune_table(rtable *tab);
  static inline void rt_schedule_notify(rtable *tab);
  static void rt_flowspec_notify(rtable *tab, net *net);
 -static inline rte *rt_next_hop_update_rte(rtable *tab, rte *old);
 +static void rt_feed_channel(void *);
 +
 +const char *rt_import_state_name_array[TIS_MAX] = {
 +  [TIS_DOWN] = "DOWN",
 +  [TIS_UP] = "UP",
 +  [TIS_STOP] = "STOP",
 +  [TIS_FLUSHING] = "FLUSHING",
 +  [TIS_WAITING] = "WAITING",
 +  [TIS_CLEARED] = "CLEARED",
 +};
 +
 +const char *rt_export_state_name_array[TES_MAX] = {
 +  [TES_DOWN] = "DOWN",
 +  [TES_HUNGRY] = "HUNGRY",
 +  [TES_FEEDING] = "FEEDING",
 +  [TES_READY] = "READY",
 +  [TES_STOP] = "STOP"
 +};
 +
 +const char *rt_import_state_name(u8 state)
 +{
 +  if (state >= TIS_MAX)
 +    return "!! INVALID !!";
 +  else
 +    return rt_import_state_name_array[state];
 +}
 +
 +const char *rt_export_state_name(u8 state)
 +{
 +  if (state >= TES_MAX)
 +    return "!! INVALID !!";
 +  else
 +    return rt_export_state_name_array[state];
 +}
 +
++static inline struct rte_storage *rt_next_hop_update_rte(rtable *tab, net *n, rte *old);
+ static struct hostentry *rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
  
  static void
  net_init_with_trie(struct fib *f, void *N)
@@@ -1550,60 -1573,91 +1552,65 @@@ rte_update_direct(struct channel *c, co
    rte_update_lock();
    if (new)
      {
 -      /* Create a temporary table node */
 -      nn = alloca(sizeof(net) + n->length);
 -      memset(nn, 0, sizeof(net) + n->length);
 -      net_copy(nn->n.addr, n);
 -
 -      new->net = nn;
 -      new->sender = c;
 -
 -      stats->imp_updates_received++;
 -      if (filter == FILTER_REJECT)
 -      {
 -        stats->imp_updates_filtered++;
 -        rte_trace_in(D_FILTERS, c, new, "filtered out");
 +      new->net = n;
  
 -        if (! c->in_keep_filtered)
 -          goto drop;
 +      int fr;
  
 -        /* new is a private copy, i could modify it */
 -        new->flags |= REF_FILTERED;
 -      }
 -      else if (filter)
 +      stats->updates_received++;
-       if (!rte_validate(c, new))
-       {
-         channel_rte_trace_in(D_FILTERS, c, new, "invalid");
-         stats->updates_invalid++;
-         new = NULL;
-       }
-       else if ((filter == FILTER_REJECT) ||
++      if ((filter == FILTER_REJECT) ||
 +      ((fr = f_run(filter, new, 0)) > F_ACCEPT))
        {
 -        int fr = f_run(filter, &new, 0);
 -        if (fr > F_ACCEPT)
 -        {
 -          stats->imp_updates_filtered++;
 -          rte_trace_in(D_FILTERS, c, new, "filtered out");
 -
 -          if (! c->in_keep_filtered)
 -            goto drop;
 +        stats->updates_filtered++;
 +        channel_rte_trace_in(D_FILTERS, c, new, "filtered out");
  
 +        if (c->in_keep_filtered)
            new->flags |= REF_FILTERED;
 -        }
 +        else
 +          new = NULL;
        }
 -      rte *new_resolved = rt_next_hop_update_rte(c->table, new);
 -      if (new_resolved)
 -      {
 -      rte_free(new);
 -      new = new_resolved;
 -      }
 -      /* After all checks, updates and filters have been done,
 -       * validate the route */
 -      if (!rte_validate(new))
++      if (new)
++      rt_next_hop_resolve_rte(new);
 -        rte_trace_in(D_FILTERS, c, new, "invalid");
 -        stats->imp_updates_invalid++;
 -        goto drop;
++      if (new && !rte_validate(c, new))
+       {
 -      if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
 -      new->attrs = rta_lookup(new->attrs);
 -      new->flags |= REF_COW;
 -
 -      /* Use the actual struct network, not the dummy one */
 -      nn = net_get(c->table, n);
 -      new->net = nn;
++        channel_rte_trace_in(D_FILTERS, c, new, "invalid");
++        stats->updates_invalid++;
++        new = NULL;
+       }
      }
    else
 -    {
 -      stats->imp_withdraws_received++;
 -
 -      if (!(nn = net_find(c->table, n)) || !src)
 -      {
 -        stats->imp_withdraws_ignored++;
 -        rte_update_unlock();
 -        return;
 -      }
 -    }
 +    stats->withdraws_received++;
  
 - recalc:
 -  /* And recalculate the best route */
 -  rte_recalculate(c, nn, new, src);
 +  rte_import(&c->in_req, n, new, src);
  
    rte_update_unlock();
 -  return;
 +}
  
 - drop:
 -  rte_free(new);
 -  new = NULL;
 -  if (nn = net_find(c->table, n))
 -    goto recalc;
 +void
 +rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rte_src *src)
 +{
 +  struct rt_import_hook *hook = req->hook;
 +  if (!hook)
 +    return;
  
 -  rte_update_unlock();
 +  net *nn;
 +  if (new)
 +    {
 +      /* Use the actual struct network, not the dummy one */
 +      nn = net_get(hook->table, n);
 +      new->net = nn->n.addr;
 +      new->sender = hook;
 +    }
 +  else if (!(nn = net_find(hook->table, n)))
 +    {
 +      req->hook->stats.withdraws_ignored++;
 +      return;
 +    }
 +
 +  /* And recalculate the best route */
 +  rte_recalculate(hook, nn, new, src);
  }
  
  /* Independent call to rte_announce(), used from next hop
@@@ -2598,45 -2508,48 +2620,65 @@@ rta_apply_hostentry(rta *a, struct host
        &ea_gen_nexthop, 0, &new->ad));
  }
  
- static inline int
+ static inline struct hostentry_adata *
  rta_next_hop_outdated(rta *a)
  {
-   struct hostentry *he = a->hostentry;
+   eattr *heea = ea_find(a->eattrs, &ea_gen_hostentry);
+   if (!heea)
+     return NULL;
  
-   if (!he)
-     return 0;
+   struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr;
  
-   if (!he->src)
-     return a->dest != RTD_UNREACHABLE;
+   if (!head->he->src)
+     return (a->dest != RTD_UNREACHABLE) ? head : NULL;
  
-   eattr *he_nh_ea = ea_find(he->src->eattrs, &ea_gen_nexthop);
+   eattr *he_nh_ea = ea_find(head->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) ||
-     (!he_nh_ea != !a_nh_ea) ||
-     (he_nh_ea && a_nh_ea && !adata_same(he_nh_ea->u.ptr, a_nh_ea->u.ptr));
+   return ((a->dest != head->he->dest) ||
+       (ea_get_int(a->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN) != head->he->igp_metric) ||
+       (!head->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)))
+     ? head : NULL;
  }
  
 -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))
+   struct hostentry_adata *head = rta_next_hop_outdated(old->attrs);
+   if (!head)
      return NULL;
  
-   rta *a = alloca(RTA_MAX_SIZE);
-   memcpy(a, old->attrs, rta_size(old->attrs));
-   rta_apply_hostentry(a, old->attrs->hostentry);
-   a->cached = 0;
+   rta a = *old->attrs;
+   a.cached = 0;
+   rta_apply_hostentry(&a, head);
  
 -  rte *e = sl_alloc(rte_slab);
 -  memcpy(e, old, sizeof(rte));
 -  e->attrs = rta_lookup(&a);
 -  rt_lock_source(e->src);
 +  rte e0 = *old;
-   e0.attrs = a;
++  e0.attrs = &a;
  
 -  return e;
 +  return rte_store(&e0, n, tab);
  }
  
++static inline void
++rt_next_hop_resolve_rte(rte *r)
++{
++  eattr *heea = ea_find(r->attrs->eattrs, &ea_gen_hostentry);
++  if (!heea)
++    return;
++
++  struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr;
++
++  if (r->attrs->cached)
++  {
++    rta *a = tmp_alloc(RTA_MAX_SIZE);
++    *a = *r->attrs;
++    a->cached = 0;
++    r->attrs = a;
++  }
++
++  rta_apply_hostentry(r->attrs, head);
++}
  
  #ifdef CONFIG_BGP
  
@@@ -3581,11 -3533,11 +3623,11 @@@ rt_update_hostentry(rtable *tab, struc
    net *n = net_route(tab, &he_addr);
    if (n)
      {
 -      rte *e = n->routes;
 -      rta *a = e->attrs;
 +      struct rte_storage *e = n->routes;
 +      rta *a = e->rte.attrs;
        pxlen = n->n.addr->pxlen;
  
-       if (a->hostentry)
+       if (ea_find(a->eattrs, &ea_gen_hostentry))
        {
          /* Recursive route should not depend on another recursive route */
          log(L_WARN "Next hop address %I resolvable through recursive route for %N",
diff --cc nest/rt.h
Simple merge
diff --cc proto/bgp/bgp.h
Simple merge
Simple merge
index b99df434ffe40f0b0302c47297777a95c0b5c9f5,e458a238b5b021ac44213d69613b63b51d58156e..e122d77155e5152008752742475c4a11f091c24e
@@@ -62,18 -75,26 +62,19 @@@ pipe_rt_notify(struct proto *P, struct 
        memcpy(a, new->attrs, rta_size(new->attrs));
  
        a->cached = 0;
-       a->hostentry = NULL;
+       ea_unset_attr(&a->eattrs, 0, &ea_gen_hostentry);
 -      e = rte_get_temp(a, src);
 -      e->pflags = new->pflags;
  
 -#ifdef CONFIG_BGP
 -      /* Hack to cleanup cached value */
 -      if (e->src->proto->proto == &proto_bgp)
 -      e->pflags &= ~(BGP_REF_STALE | BGP_REF_NOT_STALE);
 -#endif
 +      rte e0 = {
 +      .attrs = a,
 +      .src = new->src,
 +      .generation = new->generation + 1,
 +      };
 +
 +      rte_update(dst, n, &e0, new->src);
      }
    else
 -    {
 -      e = NULL;
 -      src = old->src;
 -    }
 -
 -  src_ch->table->pipe_busy = 1;
 -  rte_update2(dst, n->n.addr, e, src);
 -  src_ch->table->pipe_busy = 0;
 +    rte_update(dst, n, NULL, old->src);
  }
  
  static int
Simple merge