]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge branch 'master' into add-path
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 23 Nov 2013 10:50:34 +0000 (11:50 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 23 Nov 2013 10:50:34 +0000 (11:50 +0100)
Conflicts:

filter/filter.c
nest/proto.c
nest/rt-table.c
proto/bgp/bgp.h
proto/bgp/config.Y

22 files changed:
1  2 
filter/filter.c
lib/string.h
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-attr.c
nest/rt-dev.c
nest/rt-table.c
proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c
proto/ospf/ospf.c
proto/ospf/rt.c
proto/pipe/pipe.c
proto/rip/rip.c
proto/rip/rip.h
proto/static/static.c
sysdep/bsd/krt-sock.c
sysdep/linux/netlink.c
sysdep/unix/krt.c

diff --cc filter/filter.c
index 7c883fffe9c3ed9ff1c07b3bfefbf42bc16576ed,e0451aa157d6b98d1e6e82480d6ca8ff46b84199..ed8efd54e08406e4ed70734b6abf108c27e684ef
@@@ -821,26 -792,26 +792,26 @@@ interpret(struct f_inst *what
      break;
    case 'a':   /* rta access */
      {
+       ACCESS_RTE;
        struct rta *rta = (*f_rte)->attrs;
        res.type = what->aux;
-       switch(res.type) {
-       case T_IP:
-       res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
-       break;
-       case T_ENUM:
-       res.val.i = * ((char *) rta + what->a2.i);
-       break;
-       case T_STRING:  /* Warning: this is a special case for proto attribute */
-       res.val.s = rta->src->proto->name;
-       break;
-       case T_PREFIX:  /* Warning: this works only for prefix of network */
-       {
-         res.val.px.ip = (*f_rte)->net->n.prefix;
-         res.val.px.len = (*f_rte)->net->n.pxlen;
-         break;
-       }
+       switch (what->a2.i)
+       {
+       case SA_FROM:   res.val.px.ip = rta->from; break;
+       case SA_GW:     res.val.px.ip = rta->gw; break;
+       case SA_NET:    res.val.px.ip = (*f_rte)->net->n.prefix;
+                       res.val.px.len = (*f_rte)->net->n.pxlen; break;
 -      case SA_PROTO:  res.val.s = rta->proto->name; 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;
+       case SA_CAST:   res.val.i = rta->cast; break;
+       case SA_DEST:   res.val.i = rta->dest; break;
+       case SA_IFNAME: res.val.s = rta->iface ? rta->iface->name : ""; break;
+       case SA_IFINDEX:        res.val.i = rta->iface ? rta->iface->index : 0; break;
        default:
-       bug( "Invalid type for rta access (%x)", res.type );
+       bug("Invalid static attribute access (%x)", res.type);
        }
      }
      break;
      f_rta_cow();
      {
        struct rta *rta = (*f_rte)->attrs;
-       switch (what->aux) {
  
-       case T_IP:
-       * (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
+       switch (what->a2.i)
+       {
+       case SA_FROM:
+       rta->from = v1.val.px.ip;
        break;
  
-       case T_ENUM_SCOPE:
+       case SA_GW:
+       {
+         ip_addr ip = v1.val.px.ip;
 -        neighbor *n = neigh_find(rta->proto, &ip, 0);
++        neighbor *n = neigh_find(rta->src->proto, &ip, 0);
+         if (!n || (n->scope == SCOPE_HOST))
+           runtime( "Invalid gw address" );
+         rta->dest = RTD_ROUTER;
+         rta->gw = ip;
+         rta->iface = n->iface;
+         rta->nexthops = NULL;
+         rta->hostentry = NULL;
+       }
+       break;
+       case SA_SCOPE:
        rta->scope = v1.val.i;
        break;
  
diff --cc lib/string.h
Simple merge
diff --cc nest/proto.c
index 399c02e3c1d6e024d41b58b06e02ba5bc18b1a86,75ba10dd9c8852bbb00b6b372d83adeefb4dbb2d..019b846eddb59f2ea57226be9d1c659ce704d7a2
@@@ -798,9 -832,11 +836,12 @@@ proto_schedule_feed(struct proto *p, in
        p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
        p->main_ahook->in_filter = p->cf->in_filter;
        p->main_ahook->out_filter = p->cf->out_filter;
+       p->main_ahook->rx_limit = p->cf->rx_limit;
        p->main_ahook->in_limit = p->cf->in_limit;
        p->main_ahook->out_limit = p->cf->out_limit;
+       p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
 +
+       proto_reset_limit(p->main_ahook->rx_limit);
        proto_reset_limit(p->main_ahook->in_limit);
        proto_reset_limit(p->main_ahook->out_limit);
      }
diff --cc nest/protocol.h
Simple merge
diff --cc nest/route.h
index 3b65a85502c3ec83a08a0b1fcbd46103cd9ae0ce,e0b88551545b4c0ea3ed74365f17169b7c358b63..f00f8b2b0c350ecbe84a36adfc5e47804a79176b
@@@ -237,11 -251,12 +251,12 @@@ void rt_unlock_table(rtable *)
  void rt_setup(pool *, rtable *, char *, struct rtable_config *);
  static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
  static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
 -rte *rte_find(net *net, struct proto *p);
 +rte *rte_find(net *net, struct rte_src *src);
  rte *rte_get_temp(struct rta *);
 -void rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src);
 -static inline void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new) { rte_update2(p->main_ahook, net, new, src); }
 +void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src);
 +static inline void rte_update(struct proto *p, net *net, rte *new) { rte_update2(p->main_ahook, net, new, p->main_source); }
  void rte_discard(rtable *tab, rte *old);
+ int rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter);
  void rte_dump(rte *);
  void rte_free(rte *);
  rte *rte_do_cow(rte *);
diff --cc nest/rt-attr.c
index b2bb152f157e6a015d16e829d1f7b0e7485d4310,3f79ee5949639a0a41723d67c14f56827ed7cc74..0fb7c8204126dcbf047f5319983aaa8c4bb00e03
@@@ -74,178 -61,6 +74,178 @@@ static u32 src_hash_order, src_hash_siz
  
  struct protocol *attr_class_to_protocol[EAP_MAX];
  
-       src_ids = mb_realloc(rta_pool, src_ids, src_id_size * sizeof(u32));
 +
 +static void
 +rte_src_init(void)
 +{
 +  rte_src_slab = sl_new(rta_pool, sizeof(struct rte_src));
 +
 +  src_id_pos = 0;
 +  src_id_size = SRC_ID_SIZE_DEF;
 +  src_ids = mb_allocz(rta_pool, src_id_size * sizeof(u32));
 +
 + /* ID 0 is reserved */
 +  src_ids[0] = 1;
 +  src_id_used = 1;
 +
 +  src_hash_count = 0;
 +  src_hash_order = SRC_HASH_ORDER_DEF;
 +  src_hash_size = 1 << src_hash_order;
 +  src_table = mb_allocz(rta_pool, src_hash_size * sizeof(struct rte_src *));
 +}
 +
 +static inline int u32_cto(unsigned int x) { return ffs(~x) - 1; }
 +
 +static inline u32
 +rte_src_alloc_id(void)
 +{
 +  int i, j;
 +  for (i = src_id_pos; i < src_id_size; i++)
 +    if (src_ids[i] != 0xffffffff)
 +      goto found;
 +
 +  /* If we are at least 7/8 full, expand */
 +  if (src_id_used > (src_id_size * 28))
 +    {
 +      src_id_size *= 2;
++      src_ids = mb_realloc(src_ids, src_id_size * sizeof(u32));
 +      bzero(src_ids + i, (src_id_size - i) * sizeof(u32));
 +      goto found;
 +    }
 +
 +  for (i = 0; i < src_id_pos; i++)
 +    if (src_ids[i] != 0xffffffff)
 +      goto found;
 +
 +  ASSERT(0);
 +
 + found:
 +  ASSERT(i < 0x8000000);
 +
 +  src_id_pos = i;
 +  j = u32_cto(src_ids[i]);
 +
 +  src_ids[i] |= (1 << j);
 +  src_id_used++;
 +  return 32 * i + j;
 +}
 +
 +static inline void
 +rte_src_free_id(u32 id)
 +{
 +  int i = id / 32;
 +  int j = id % 32;
 +
 +  ASSERT((i < src_id_size) && (src_ids[i] & (1 << j)));
 +  src_ids[i] &= ~(1 << j);
 +  src_id_used--;
 +}
 +
 +static inline u32 rte_src_hash(struct proto *p, u32 x, u32 order)
 +{ return (x * 2902958171u) >> (32 - order); }
 +
 +static void
 +rte_src_rehash(int step)
 +{
 +  struct rte_src **old_tab, *src, *src_next;
 +  u32 old_size, hash, i;
 +
 +  old_tab = src_table;
 +  old_size = src_hash_size;
 +
 +  src_hash_order += step;
 +  src_hash_size = 1 << src_hash_order;
 +  src_table = mb_allocz(rta_pool, src_hash_size * sizeof(struct rte_src *));
 +  
 +  for (i = 0; i < old_size; i++)
 +    for (src = old_tab[i]; src; src = src_next)
 +      {
 +      src_next = src->next;
 +      hash = rte_src_hash(src->proto, src->private_id, src_hash_order);
 +      src->next = src_table[hash];
 +      src_table[hash] = src;
 +      }
 +
 +  mb_free(old_tab);
 +}
 +
 +struct rte_src *
 +rt_find_source(struct proto *p, u32 id)
 +{
 +  struct rte_src *src;
 +  u32 hash = rte_src_hash(p, id, src_hash_order);
 +
 +  for (src = src_table[hash]; src; src = src->next)
 +    if ((src->proto == p) && (src->private_id == id))
 +      return src;
 +
 +  return NULL;
 +}
 +
 +struct rte_src *
 +rt_get_source(struct proto *p, u32 id)
 +{
 +  struct rte_src *src;
 +  u32 hash = rte_src_hash(p, id, src_hash_order);
 +
 +  for (src = src_table[hash]; src; src = src->next)
 +    if ((src->proto == p) && (src->private_id == id))
 +      return src;
 +
 +  src = sl_alloc(rte_src_slab);
 +  src->proto = p;
 +  src->private_id = id;
 +  src->global_id = rte_src_alloc_id();
 +  src->uc = 0;
 +
 +  src->next = src_table[hash];
 +  src_table[hash] = src;
 +
 +  src_hash_count++;
 +  if ((src_hash_count > src_hash_size) && (src_hash_order < SRC_HASH_ORDER_MAX))
 +    rte_src_rehash(1);
 +
 +  return src;
 +}
 +
 +static inline void
 +rt_remove_source(struct rte_src **sp)
 +{
 +  struct rte_src *src = *sp;
 +
 +  *sp = src->next;
 +  rte_src_free_id(src->global_id);
 +  sl_free(rte_src_slab, src);
 +  src_hash_count--;
 +}
 +
 +void
 +rt_prune_sources(void)
 +{
 +  struct rte_src **sp;
 +  int i;
 +  
 +  for (i = 0; i < src_hash_size; i++)
 +    {
 +      sp = &src_table[i];
 +      while (*sp)
 +      {
 +        if ((*sp)->uc == 0)
 +          rt_remove_source(sp);
 +        else
 +          sp = &(*sp)->next;
 +      }
 +    }
 +
 +  while ((src_hash_count < (src_hash_size / 4)) && (src_hash_order > SRC_HASH_ORDER_MIN))
 +    rte_src_rehash(-1);
 +}
 +
 +
 +/*
 + *    Multipath Next Hop
 + */
 +
  static inline unsigned int
  mpnh_hash(struct mpnh *x)
  {
diff --cc nest/rt-dev.c
Simple merge
diff --cc nest/rt-table.c
index ecd6e324bb278ed38117807593c2b175831b8f63,fc55408146d81fcf7a42079f7dea65112daee10a..8c91ea0aaf6305c3b9bbf906db7184f543e15a11
@@@ -615,11 -625,13 +632,13 @@@ rte_same(rte *x, rte *y
      x->flags == y->flags &&
      x->pflags == y->pflags &&
      x->pref == y->pref &&
 -    (!x->attrs->proto->rte_same || x->attrs->proto->rte_same(x, y));
 +    (!x->attrs->src->proto->rte_same || x->attrs->src->proto->rte_same(x, y));
  }
  
+ static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); }
  static void
 -rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
 +rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct rte_src *src)
  {
    struct proto *p = ah->proto;
    struct rtable *table = ah->table;
@@@ -911,41 -995,47 +1002,54 @@@ rte_update2(struct announce_hook *ah, n
        {
          stats->imp_updates_filtered++;
          rte_trace_in(D_FILTERS, p, new, "filtered out");
-         goto drop;
-       }
  
-       tmpa = make_tmp_attrs(new, rte_update_pool);
-       if (filter)
+         if (! ah->in_keep_filtered)
+           goto drop;
+         /* new is a private copy, i could modify it */
+         new->flags |= REF_FILTERED;
+       }
+       else
        {
-         ea_list *old_tmpa = tmpa;
-         int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
-         if (fr > F_ACCEPT)
 -        if (src->make_tmp_attrs)
 -          tmpa = src->make_tmp_attrs(new, rte_update_pool);
++        tmpa = make_tmp_attrs(new, rte_update_pool);
+         if (filter && (filter != FILTER_REJECT))
            {
-             stats->imp_updates_filtered++;
-             rte_trace_in(D_FILTERS, p, new, "filtered out");
-             goto drop;
+             ea_list *old_tmpa = tmpa;
+             int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
+             if (fr > F_ACCEPT)
+               {
+                 stats->imp_updates_filtered++;
+                 rte_trace_in(D_FILTERS, p, new, "filtered out");
+                 if (! ah->in_keep_filtered)
+                   goto drop;
+                 new->flags |= REF_FILTERED;
+               }
 -            if (tmpa != old_tmpa && src->store_tmp_attrs)
 -              src->store_tmp_attrs(new, tmpa);
++            if (tmpa != old_tmpa && src->proto->store_tmp_attrs)
++              src->proto->store_tmp_attrs(new, tmpa);
            }
-         if (tmpa != old_tmpa && src->proto->store_tmp_attrs)
-           src->proto->store_tmp_attrs(new, tmpa);
        }
--
 -      if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
 +      if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
        new->attrs = rta_lookup(new->attrs);
        new->flags |= REF_COW;
      }
    else
 -    stats->imp_withdraws_received++;
 +    {
 +      stats->imp_withdraws_received++;
 +
 +      if (!net || !src)
 +      {
 +        stats->imp_withdraws_ignored++;
 +        rte_update_unlock();
 +        return;
 +      }
 +    }
  
+  recalc:
+   rte_hide_dummy_routes(net, &dummy);
    rte_recalculate(ah, net, new, tmpa, src);
+   rte_unhide_dummy_routes(net, &dummy);
    rte_update_unlock();
    return;
  
@@@ -976,6 -1069,34 +1081,33 @@@ rte_discard(rtable *t, rte *old)       /* Non
    rte_update_unlock();
  }
  
 -  struct proto *src = rt->attrs->proto;
 -  ea_list *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, rte_update_pool) : NULL;
+ /* Check rtable for best route to given net whether it would be exported do p */
+ int
+ rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter)
+ {
+   net *n = net_find(t, prefix, pxlen);
+   rte *rt = n ? n->routes : NULL;
+   if (!rte_is_valid(rt))
+     return 0;
+   rte_update_lock();
+   /* Rest is stripped down export_filter() */
++  ea_list *tmpa = make_tmp_attrs(rt, rte_update_pool);
+   int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0;
+   if (v == RIC_PROCESS)
+     v = (f_run(filter, &rt, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
+    /* Discard temporary rte */
+   if (rt != n->routes)
+     rte_free(rt);
+   rte_update_unlock();
+   return v > 0;
+ }
  /**
   * rte_dump - dump a route
   * @e: &rte to be dumped
@@@ -1189,8 -1297,8 +1311,8 @@@ again
  
      rescan:
        for (e=n->routes; e; e=e->next)
-       if (e->sender->proto->core_state != FS_HAPPY &&
-           e->sender->proto->core_state != FS_FEEDING)
+       if (e->sender->proto->flushing ||
 -          (step && e->attrs->proto->flushing))
++          (step && e->attrs->src->proto->flushing))
          {
            if (*max_feed <= 0)
              {
                return 0;
              }
  
 -                n->n.prefix, n->n.pxlen, e->attrs->proto->name, tab->name);
+           if (step)
+             log_rl(&rl_flush, L_WARN "Route %I/%d from %s still in %s after flush",
++                n->n.prefix, n->n.pxlen, e->attrs->src->proto->name, tab->name);
            rte_discard(tab, e);
            (*max_feed)--;
  
@@@ -2001,20 -2132,25 +2149,25 @@@ rt_show_net(struct cli *c, net *n, stru
    int ok;
  
    bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
-   if (n->routes)
-     d->net_counter++;
    for(e=n->routes; e; e=e->next)
      {
+       if (rte_is_filtered(e) != d->filtered)
+       continue;
        struct ea_list *tmpa;
 -      struct proto *p0 = e->attrs->proto;
 +      struct rte_src *src = e->attrs->src;
        struct proto *p1 = d->export_protocol;
        struct proto *p2 = d->show_protocol;
+       if (ia[0])
+       d->net_counter++;
        d->rt_counter++;
        ee = e;
        rte_update_lock();              /* We use the update buffer for filtering */
 -      tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
 +      tmpa = make_tmp_attrs(e, rte_update_pool);
-       ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
+       ok = f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT;
 -      if (p2 && p2 != p0) ok = 0;
 +      if (p2 && p2 != src->proto) ok = 0;
        if (ok && d->export_mode)
        {
          int ic;
Simple merge
diff --cc proto/bgp/bgp.c
Simple merge
diff --cc proto/bgp/bgp.h
index b87de46ed0d45aafeffe6951ac7865027cb8f290,b5e216b78ed1582456ab6e7b018cd2b3d603bc92..a35c362cbb377dfbc364ef2039e06a02406d4026
@@@ -43,7 -45,7 +45,8 @@@ struct bgp_config 
    int passive;                                /* Do not initiate outgoing connection */
    int interpret_communities;          /* Hardwired handling of well-known communities */
    int secondary;                      /* Accept also non-best routes (i.e. RA_ACCEPTED) */
 +  int add_path;                               /* Use ADD-PATH extension [draft] */
+   int allow_local_as;                 /* Allow that number of local ASNs in incoming AS_PATHs */
    unsigned connect_retry_time;
    unsigned hold_time, initial_hold_time;
    unsigned keepalive_time;
index 0b0963397f949603e66a86f861f4020314f1c085,185b1bda5189d3445f98c3f653c1ce3a70b43d9d..ab12fed5a4b9b640d36bd05a66fa2164e3ac50cf
@@@ -26,7 -26,7 +26,7 @@@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, H
        PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
        INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
        TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
-       SECONDARY, ADD, PATHS, RX, TX)
 -      SECONDARY, ALLOW, BFD)
++      SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX)
  
  CF_GRAMMAR
  
@@@ -107,11 -108,11 +108,14 @@@ bgp_proto
   | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
   | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
   | bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
 + | bgp_proto ADD PATHS RX ';' { BGP_CFG->add_path = ADD_PATH_RX; }
 + | bgp_proto ADD PATHS TX ';' { BGP_CFG->add_path = ADD_PATH_TX; }
 + | bgp_proto ADD PATHS bool ';' { BGP_CFG->add_path = $4 ? ADD_PATH_FULL : 0; }
+  | bgp_proto ALLOW LOCAL AS ';' { BGP_CFG->allow_local_as = -1; }
+  | bgp_proto ALLOW LOCAL AS expr ';' { BGP_CFG->allow_local_as = $5; }
   | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
   | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
+  | bgp_proto BFD bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
   ;
  
  CF_ADDTO(dynamic_attr, BGP_ORIGIN
Simple merge
Simple merge
diff --cc proto/ospf/rt.c
Simple merge
Simple merge
diff --cc proto/rip/rip.c
index 9f4f0856de24a3edcd96e5b81502745e9f94a52d,ad285bb3a7206c1757082b1625efd30b84d216ed..5cc40403f36a5bc58015734aca52f1907d194440
@@@ -948,9 -968,11 +960,11 @@@ rip_rte_insert(net *net UNUSED, rte *rt
  static void
  rip_rte_remove(net *net UNUSED, rte *rte)
  {
-   // struct proto *p = rte->attrs->proto;
+ #ifdef LOCAL_DEBUG
 -  struct proto *p = rte->attrs->proto;
++  struct proto *p = rte->attrs->src->proto;
    CHK_MAGIC;
    DBG( "rip_rte_remove: %p\n", rte );
+ #endif
    rem_node( &rte->u.rip.garbage );
  }
  
diff --cc proto/rip/rip.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge