Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Aug 2012 16:40:14 +0000 (UTC)
From:      Sergey Matveychuk <sem@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r302586 - in head/net: bird bird/files bird6 bird6/files
Message-ID:  <201208151640.q7FGeEUB080947@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sem
Date: Wed Aug 15 16:40:13 2012
New Revision: 302586
URL: http://svn.freebsd.org/changeset/ports/302586

Log:
  - Update to 1.3.8
  
  Submitted by:	maintainer

Added:
  head/net/bird/files/patch-rtrid.diff   (contents, props changed)
Modified:
  head/net/bird/Makefile
  head/net/bird/distinfo
  head/net/bird/files/agg_support.patch
  head/net/bird/files/fibs.diff
  head/net/bird/files/firewall_support.patch
  head/net/bird/files/patch-tools-Makefile.in
  head/net/bird6/Makefile
  head/net/bird6/distinfo
  head/net/bird6/files/patch-tools-Makefile.in

Modified: head/net/bird/Makefile
==============================================================================
--- head/net/bird/Makefile	Wed Aug 15 16:39:39 2012	(r302585)
+++ head/net/bird/Makefile	Wed Aug 15 16:40:13 2012	(r302586)
@@ -6,7 +6,7 @@
 #
 
 PORTNAME=	bird
-PORTVERSION=	1.3.7
+PORTVERSION=	1.3.8
 CATEGORIES=	net
 MASTER_SITES=	ftp://bird.network.cz/pub/bird/
 

Modified: head/net/bird/distinfo
==============================================================================
--- head/net/bird/distinfo	Wed Aug 15 16:39:39 2012	(r302585)
+++ head/net/bird/distinfo	Wed Aug 15 16:40:13 2012	(r302586)
@@ -1,2 +1,2 @@
-SHA256 (bird-1.3.7.tar.gz) = d047ed945ef759ac3037c43bf3ffa28988a2ca1ace07d244571e9ee0994191ff
-SIZE (bird-1.3.7.tar.gz) = 875787
+SHA256 (bird-1.3.8.tar.gz) = 9d07799a434dbf2f679b84aba57fde91fcb9e61e17db64aa1af8372bb4149ae4
+SIZE (bird-1.3.8.tar.gz) = 890487

Modified: head/net/bird/files/agg_support.patch
==============================================================================
--- head/net/bird/files/agg_support.patch	Wed Aug 15 16:39:39 2012	(r302585)
+++ head/net/bird/files/agg_support.patch	Wed Aug 15 16:40:13 2012	(r302586)
@@ -1,28 +1,29 @@
-From 6178c758c99bf6b1d9402489e8974ee3598675cf Mon Sep 17 00:00:00 2001
+From 79ef76d5538871a08ecec829f2332bd0e4399cbd Mon Sep 17 00:00:00 2001
 From: Alexander V. Chernikov <melifaro@ipfw.ru>
-Date: Thu, 22 Mar 2012 15:28:02 +0000
-Subject: [PATCH 1/1] * Implement general aggregation protocol, v5
+Date: Wed, 15 Aug 2012 08:32:08 +0000
+Subject: [PATCH 1/1] Implement general aggregation protocol,v6
 
 ---
  configure.in          |    4 +-
  doc/bird.conf.example |    9 +
+ doc/bird.sgml         |   56 +++
  filter/config.Y       |    2 +-
  filter/filter.h       |    7 +-
- filter/trie.c         |  111 +++++++-
+ filter/trie.c         |  111 +++++-
  nest/proto-hooks.c    |   11 +
  nest/proto.c          |    3 +
- nest/protocol.h       |    9 +-
+ nest/protocol.h       |   10 +-
  nest/rt-table.c       |   19 +-
  proto/agg/Doc         |    1 +
  proto/agg/Makefile    |    6 +
- proto/agg/agg.c       |  720 +++++++++++++++++++++++++++++++++++++++++++++++
- proto/agg/agg.h       |   87 ++++++
- proto/agg/config.Y    |  108 +++++++
- proto/bgp/attrs.c     |  748 +++++++++++++++++++++++++++++++++++++++++++++++++
- proto/bgp/bgp.c       |    7 +-
- proto/bgp/bgp.h       |    2 +
+ proto/agg/agg.c       |  847 +++++++++++++++++++++++++++++++++++++++
+ proto/agg/agg.h       |  123 ++++++
+ proto/agg/config.Y    |  117 ++++++
+ proto/bgp/attrs.c     | 1057 +++++++++++++++++++++++++++++++++++++++++++++++++
+ proto/bgp/bgp.c       |    8 +-
+ proto/bgp/bgp.h       |    5 +
  sysdep/autoconf.h.in  |    1 +
- 18 files changed, 1831 insertions(+), 24 deletions(-)
+ 19 files changed, 2373 insertions(+), 24 deletions(-)
  create mode 100644 proto/agg/Doc
  create mode 100644 proto/agg/Makefile
  create mode 100644 proto/agg/agg.c
@@ -30,23 +31,23 @@ Subject: [PATCH 1/1] * Implement general
  create mode 100644 proto/agg/config.Y
 
 diff --git a/configure.in b/configure.in
-index 46a6ecd..aff445a 100644
+index dd57ab5..ca9d72d 100644
 --- configure.in
 +++ configure.in
-@@ -43,11 +43,11 @@ AC_SUBST(srcdir_rel_mf)
+@@ -47,11 +47,11 @@ AC_SUBST(runtimedir)
  if test "$enable_ipv6" = yes ; then
  	ip=ipv6
- 	SUFFIX6=6
+ 	SUFFIX=6
 -	all_protocols=bgp,ospf,pipe,radv,rip,static
 +	all_protocols=bgp,ospf,pipe,radv,rip,static,agg
  else
  	ip=ipv4
- 	SUFFIX6=""
+ 	SUFFIX=""
 -	all_protocols=bgp,ospf,pipe,rip,static
 +	all_protocols=bgp,ospf,pipe,rip,static,agg
  fi
  
- if test "$with_protocols" = all ; then
+ if test "$given_suffix" = yes ; then
 diff --git a/doc/bird.conf.example b/doc/bird.conf.example
 index 5e07ab5..2cab8be 100644
 --- doc/bird.conf.example
@@ -67,8 +68,75 @@ index 5e07ab5..2cab8be 100644
  
  #protocol bgp {
  #	disabled;
+diff --git a/doc/bird.sgml b/doc/bird.sgml
+index 087a4eb..4be00c8 100644
+--- doc/bird.sgml
++++ doc/bird.sgml
+@@ -1115,6 +1115,62 @@ undefined value is regarded as empty clist for most purposes.
+ 
+ <chapt>Protocols
+ 
++<sect>Aggregator
++
++<p>Aggregator protocol is not a real routing protocol. It generates summary routes of
++given protocol type. Currently the only supported protocol is BGP.
++
++<sect1>Configuration
++
++<p>Main part of configuration contains one or more definitions of
++BGP ID and AS to generate summarized routes.
++
++<p> Nested aggregation routes are supported with the following limitations:
++Routes are always aggregated into longest-match summary route only. Summary routes
++does not aggregate more specific summary routes within the same protocol. If you need
++complex nested aggregation scenario you have to use several aggregation protocol instances
++to achieve this.
++
++
++<code>
++protocol aggregator &lt;name&gt; {
++	bgp id &lt;id&gt; as &lt;as&lt; {
++		aggregate address &lt;prefix&gt;;
++		aggregate address &lt;prefix&lt; mandatory list {
++			&lt;prefix&lt;,
++			&lt;prefix&lt;,
++			&lt;prefix&lt;
++			};
++		aggregate address &lt;prefix&gt; save attributes;
++	};
++}
++
++<p><descrip>
++	<tag>bgp id <M>id</M> as <m/number/</tag>
++	 This defines BGP route base attributes to use in summary routes.
++	 Note that protocol can aggregate routes with different local AS and
++	 BGP router id by default.
++
++	<tag>aggregate address <m/prefix/</tag> Announce given prefix if any
++	of more specific routes exists. Additionally, you can specify
++	<cf/save attributes/ to save maximum information from every route.
++	Turning this flag on makes BGP aggregate AS-PATH per RFC 4271.
++	Another option that can be used is <cf/mandatory list { }/
++	Prefix is announced IFF all of the mandatory prefixes currently exists
++	in route table.
++</descrip>
++
++<p>Example configuration looks like this:
++
++<p><code>
++protocol aggregator {
++	bgp id 198.51.100.130 as 65000 {
++		aggregate address 198.51.100.0/24;
++		aggregate address 192.168.0.0/16 mandatory list { 192.168.1.1/32 };
++	}
++}
++</code>
++
+ <sect>BGP
+ 
+ <p>The Border Gateway Protocol is the routing protocol used for backbone
 diff --git a/filter/config.Y b/filter/config.Y
-index 2e8b522..a13f33c 100644
+index 0eeb2ce..7aff013 100644
 --- filter/config.Y
 +++ filter/config.Y
 @@ -558,7 +558,7 @@ fprefix:
@@ -109,7 +177,7 @@ index 2386fc9..f2a5d06 100644
  };
  
 diff --git a/filter/trie.c b/filter/trie.c
-index 581332c..12d7755 100644
+index 581332c..17ac896 100644
 --- filter/trie.c
 +++ filter/trie.c
 @@ -75,23 +75,24 @@
@@ -205,8 +273,8 @@ index 581332c..12d7755 100644
 + * @plen: prefix length
 + *
 + * Tries to find a matching prefix pattern in the trie such that
-+ * prefix @px/@plen matches that prefix pattern. Returns 1 if there
-+ * is such prefix pattern in the trie.
++ * prefix @px/@plen matches that prefix pattern. Returns prefix pointer
++ * or NULL.
 + */
 +void *
 +trie_match_longest_prefix(struct f_trie *t, ip_addr px, int plen)
@@ -242,7 +310,7 @@ index 581332c..12d7755 100644
 +  /*
 +   * parent is either
 +   * 1) NULL (if the first non-null node does not exist oris out of path)
-+   * or 
++   * or
 +   * 2) points to the last entry that match
 +   *
 +   * In former case we check if catch-all prefix really exists and return
@@ -262,7 +330,7 @@ index 581332c..12d7755 100644
 +
 +  if (n->c[0])
 +    trie_walk_call(n->c[0], func, data);
-+ 
++
 +  if (n->c[1])
 +    trie_walk_call(n->c[1], func, data);
 +}
@@ -285,10 +353,10 @@ index 581332c..12d7755 100644
  trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
  {
 diff --git a/nest/proto-hooks.c b/nest/proto-hooks.c
-index 2582c48..1b59fbb 100644
+index e80f87e..22f22ca 100644
 --- nest/proto-hooks.c
 +++ nest/proto-hooks.c
-@@ -150,6 +150,17 @@ int get_attr(eattr *a, byte *buf, int buflen)
+@@ -161,6 +161,17 @@ int get_attr(eattr *a, byte *buf, int buflen)
  { DUMMY; }
  
  /**
@@ -307,10 +375,10 @@ index 2582c48..1b59fbb 100644
   * @p: protocol instance
   * @flags: interface change flags
 diff --git a/nest/proto.c b/nest/proto.c
-index 0fc72ce..a48656c 100644
+index 887d3e5..4ebc9d6 100644
 --- nest/proto.c
 +++ nest/proto.c
-@@ -633,6 +633,9 @@ protos_build(void)
+@@ -705,6 +705,9 @@ protos_build(void)
  #ifdef CONFIG_BGP
    proto_build(&proto_bgp);
  #endif
@@ -319,9 +387,9 @@ index 0fc72ce..a48656c 100644
 +#endif
    proto_pool = rp_new(&root_pool, "Protocols");
    proto_flush_event = ev_new(proto_pool);
-   proto_flush_event->hook = proto_flush_all;
+   proto_flush_event->hook = proto_flush_loop;
 diff --git a/nest/protocol.h b/nest/protocol.h
-index a83c4ff..e61b8d3 100644
+index 8a63271..0a0d8f7 100644
 --- nest/protocol.h
 +++ nest/protocol.h
 @@ -28,6 +28,10 @@ struct event;
@@ -335,19 +403,20 @@ index a83c4ff..e61b8d3 100644
  
  /*
   *	Routing Protocol
-@@ -53,8 +57,11 @@ struct protocol {
+@@ -54,8 +58,12 @@ struct protocol {
    void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
    void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
    int (*get_attr)(struct eattr *, byte *buf, int buflen);	/* ASCIIfy dynamic attribute (returns GA_*) */
 +  void (*create_sumroute)(struct agg_proto *, struct agg_sumroute *);	/* Create summary route */
 +  void (*update_sumroute)(struct agg_proto *, struct agg_sumroute *, struct agg_route *, struct rta *, struct rta *);	/* Update summary route */
++  int (*check_sumroute)(struct agg_proto *, struct agg_sumroute *, struct agg_sumroute *);	/* Check sumroute parameters  */
    void (*show_proto_info)(struct proto *);	/* Show protocol info (for `show protocols all' command) */
    void (*copy_config)(struct proto_config *, struct proto_config *);	/* Copy config from given protocol instance */
 +  void (*get_route_ainfo)(struct cli *, int, struct rte *); /* Print additional information (for `show route' command) */
  };
  
  void protos_build(void);
-@@ -74,7 +81,7 @@ void protos_dump_all(void);
+@@ -75,7 +83,7 @@ void protos_dump_all(void);
  
  extern struct protocol
    proto_device, proto_radv, proto_rip, proto_static,
@@ -357,10 +426,10 @@ index a83c4ff..e61b8d3 100644
  /*
   *	Routing Protocol Instance
 diff --git a/nest/rt-table.c b/nest/rt-table.c
-index 377687d..4709544 100644
+index 165f42b..f224cc4 100644
 --- nest/rt-table.c
 +++ nest/rt-table.c
-@@ -1440,7 +1440,7 @@ rt_init_hostcache(rtable *tab)
+@@ -1719,7 +1719,7 @@ rt_init_hostcache(rtable *tab)
    hc->slab = sl_new(rt_table_pool, sizeof(struct hostentry));
  
    hc->lp = lp_new(rt_table_pool, 1008);
@@ -369,7 +438,7 @@ index 377687d..4709544 100644
  
    tab->hostcache = hc;
  }
-@@ -1587,7 +1587,7 @@ rt_update_hostcache(rtable *tab)
+@@ -1866,7 +1866,7 @@ rt_update_hostcache(rtable *tab)
  
    /* Reset the trie */
    lp_flush(hc->lp);
@@ -378,7 +447,7 @@ index 377687d..4709544 100644
  
    WALK_LIST_DELSAFE(n, x, hc->hostentries)
      {
-@@ -1634,7 +1634,7 @@ rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_add
+@@ -1913,7 +1913,7 @@ rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_add
   *  CLI commands
   */
  
@@ -387,7 +456,7 @@ index 377687d..4709544 100644
  rt_format_via(rte *e, byte *via)
  {
    rta *a = e->attrs;
-@@ -1660,6 +1660,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
+@@ -1939,6 +1939,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
    int primary = (e->net->routes == e);
    int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
    struct mpnh *nh;
@@ -395,7 +464,7 @@ index 377687d..4709544 100644
  
    rt_format_via(e, via);
    tm_format_datetime(tm, &config->tf_route, e->lastmod);
-@@ -1667,7 +1668,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
+@@ -1946,7 +1947,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
      bsprintf(from, " from %I", a->from);
    else
      from[0] = 0;
@@ -404,7 +473,7 @@ index 377687d..4709544 100644
      {
        /* Need to normalize the extended attributes */
        ea_list *t = tmpa;
-@@ -1676,8 +1677,8 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
+@@ -1955,8 +1956,8 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
        ea_merge(t, tmpa);
        ea_sort(tmpa);
      }
@@ -415,7 +484,7 @@ index 377687d..4709544 100644
    else
      bsprintf(info, " (%d)", e->pref);
    cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
-@@ -1685,7 +1686,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
+@@ -1964,7 +1965,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
    for (nh = a->nexthops; nh; nh = nh->next)
      cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1);
    if (d->verbose)
@@ -449,12 +518,12 @@ index 0000000..3039207
 +
 diff --git a/proto/agg/agg.c b/proto/agg/agg.c
 new file mode 100644
-index 0000000..5b9cae1
+index 0000000..8b6fc2e
 --- /dev/null
 +++ proto/agg/agg.c
-@@ -0,0 +1,720 @@
+@@ -0,0 +1,847 @@
 +/*
-+ *	BIRD -- BGP route aggregation
++ *	BIRD -- Generic route aggregation
 + *
 + *	(c) 2012 Yandex LLC
 + *	(c) 2012 Alexander V. Chernikov <melifaro@yandex-team.ru>
@@ -465,13 +534,12 @@ index 0000000..5b9cae1
 +/**
 + * DOC: Route aggregation
 + *
-+ * Firewall protocol is very simple. It adds or removes exported routes to given firewall
-+ * table with zero (or filter-specified) value. Table can be flushed on startup to
-+ * avoid error messages on bird restart.
++ * Aggregation protocol provides general protocol-independent api for
++ * summarizing routes based on config-file defined criteria.
 + */
 +
 +
-+#undef LOCAL_DEBUG
++#define LOCAL_DEBUG
 +
 +#include "nest/bird.h"
 +#include "nest/iface.h"
@@ -495,7 +563,7 @@ index 0000000..5b9cae1
 +static int
 +agg_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
 +{
-+  struct proto *pp = (*ee)->sender;
++  struct proto *pp = (*ee)->sender->proto;
 +
 +  if (pp == P)
 +    return -1;	/* Avoid local loops automatically */
@@ -508,42 +576,43 @@ index 0000000..5b9cae1
 +  return 1;
 +}
 +
++/*
++ * FIB callback on new route creation
++ */
 +static void
 +agg_initroute(struct fib_node *fn)
 +{
 +  struct agg_route *ar = (struct agg_route *)fn;
 +
 +  memset((byte *)ar + sizeof(struct fib_node), 0, sizeof(struct agg_route) - sizeof(struct fib_node));
-+  ar->flags = AGG_FLAG_NEW;
++  /* Init various lists */
++  init_list(&ar->membership_list);
 +}
 +
 +static int
 +agg_can_announce(struct agg_sumroute *asr)
 +{
-+  return (asr->mandatory_current == asr->mandatory_total);
++  return ((asr->mandatory_current == asr->mandatory_total) && (!(asr->flags & AGG_FLAG_DELETED)));
 +}
 +
 +/*
-+ * agg_make_route - create new route
-+ * @p: protocol instance
-+ * @addr: pointer to network address
-+ * @plen: prefix length
-+ *
-+ * Adds mandatory route to fib and links it to 
++ * Delete route if it is not used in any role
 + */
-+static struct agg_route *
-+agg_make_route(struct agg_proto *p, ip_addr *addr, int plen)
++static void
++agg_try_gc_route(struct agg_proto *p, struct agg_route *ar)
 +{
-+  struct agg_route *ar = fib_get(&p->route_fib, addr, plen);
++  if (AGG_IS_USED(ar))
++    return;
 +
-+  if (ar->flags & AGG_FLAG_NEW)
++  if (ar->attrs)
 +    {
-+      /* New route. Do init */
-+      init_list(&ar->sum_membership);
-+      ar->flags &= ~AGG_FLAG_NEW;
++      /* Remove cloned rta */
++      rta_free(ar->attrs);
 +    }
 +
-+  return ar;
++  //ADBG("GC route %I/%d", ar->fn.prefix, ar->fn.pxlen);
++
++  fib_delete(&p->route_fib, ar);
 +}
 +
 +static void
@@ -557,10 +626,13 @@ index 0000000..5b9cae1
 +
 +  ADBG("Linking mandatory route %I/%d to summary %I/%d", ar->fn.prefix, ar->fn.pxlen, asr->tn.addr, asr->tn.plen);
 +
-+  add_tail(&ar->sum_membership, &ms->n_mandatory);
++  add_tail(&ar->membership_list, &ms->n_route);
 +  add_tail(&asr->mandatory_list, &ms->n_sumroute);
 +}
 +
++/*
++ * Unlink membership structure from summary route. Mandatory route is checked for validness after that.
++ */
 +static void
 +agg_unlink_mroute(struct agg_proto *p, struct agg_membership *ms)
 +{
@@ -568,63 +640,53 @@ index 0000000..5b9cae1
 +
 +  ADBG("Unlinking mandatory route %I/%d from summary %I/%d", ar->fn.prefix, ar->fn.pxlen, ms->asr->tn.addr, ms->asr->tn.plen);
 +
-+  rem_node(&ms->n_mandatory);
++  rem_node(&ms->n_route);
 +  rem_node(&ms->n_sumroute);
 +  mb_free(ms);
 +
 +  /* Check if we need to free route iself */
-+  if (!EMPTY_LIST(ar->sum_membership))
++  if (!EMPTY_LIST(ar->membership_list))
 +    return;
 +
-+  if (ar->attrs)
-+    return;
++  /* No membership structures. Unset mandatory role and check if route can be deleted */
++  AGG_UNSET_MANDATORY(ar);
 +
-+  /* No other mandatory routes, no route entry. We can safely free node */
-+  fib_delete(&p->route_fib, ar);
++  agg_try_gc_route(p, ar);
 +}
 +
 +static void
-+agg_walk_sumroutes_initial(struct f_trie_node *n, void *data)
++agg_link_childroute(struct agg_proto *p, struct agg_sumroute *asr, struct agg_route *ar)
 +{
-+  struct agg_sumroute *asr = (struct agg_sumroute *)n;
-+  struct agg_proto *p = (struct agg_proto *)data;
-+
-+  if (!(asr->flags & AGG_FLAG_PREPARED))
-+    return;
-+
-+  agg_init_sumroute(p, asr);
++  ar->asr = asr;
++  add_tail(&asr->routes, &ar->n_sumroute);
 +}
 +
-+static int
-+agg_start(struct proto *P)
++/*
++ * Remove child role from route
++ */
++static void
++agg_remove_childrole(struct agg_proto *p, struct agg_route *ar)
 +{
-+  struct agg_proto *p = (struct agg_proto *)P;
-+  struct agg_config *cf = (struct agg_config *)P->cf;
-+
-+  fib_init(&p->route_fib, P->pool, sizeof(struct agg_route), 0, agg_initroute);
-+  p->summary_trie = cf->summary_trie;
-+
-+  /* Import mandatory routes if any */
-+  trie_walk(p->summary_trie, agg_walk_sumroutes_initial, p);
-+
-+  /* Allocate by 16k blocks (while BGP requests 1k block) */
-+  p->lp = lp_new(P->pool, 16384 - 16);
++  ar->asr = NULL;
++  AGG_UNSET_CHILD(ar);
 +
-+  return PS_UP;
++  agg_try_gc_route(p, ar);
 +}
 +
 +/*
-+ * Mark given summary route as deleted
++ * Trie callback function.
++ * Init newly-created summary routes.
 + */
 +static void
-+agg_mark_sumroute(struct f_trie_node *n, void *data UNUSED)
++agg_walk_sumroutes_initial(struct f_trie_node *n, void *data)
 +{
 +  struct agg_sumroute *asr = (struct agg_sumroute *)n;
++  struct agg_proto *p = (struct agg_proto *)data;
 +
-+  if (!(asr->flags & AGG_FLAG_PREPARED))
++  if (!AGG_VALID_NODE(asr))
 +    return;
 +
-+  asr->flags |= AGG_FLAG_DELETED;
++  agg_init_sumroute(p, asr);
 +}
 +
 +/*
@@ -649,26 +711,23 @@ index 0000000..5b9cae1
 +      asr->mandatory_total++;
 +
 +      /* Get or create new route entry */
-+      ar = agg_make_route(p, &cr->px.addr, cr->px.len);
++      ar = fib_get(&p->route_fib, &cr->px.addr, cr->px.len);
 +
 +      /* Increate current counter IFF we have real best rte associated with entry */
-+      if (ar->attrs)
-+	{
++      if (AGG_IS_INSTALLED(ar))
 +	  asr->mandatory_current++;
-+	  /* Set installed flag */
-+	  ar->flags |= AGG_FLAG_INSTALLED;
-+	}
 +
 +      /* Add link */
 +      agg_link_mroute(p, asr, ar);
 +  }
++
++  /* Indicate we need refeeed to populate this route */
++  p->need_refeed = 1;
 +}
 +
 +static void
 +agg_announce_sumroute(struct agg_proto *p, struct agg_sumroute *asr)
 +{
-+  //net *n;
-+
 +  if (!agg_can_announce(asr))
 +    return;
 +
@@ -676,14 +735,7 @@ index 0000000..5b9cae1
 +    return;
 +
 +  /* Generate summary route */
-+  switch (asr->route_src)
-+    {
-+#ifdef CONFIG_BGP
-+    case RTS_BGP:
-+      proto_bgp.create_sumroute(p, asr);
-+      break;
-+#endif
-+    }
++  asr->proto->create_sumroute(p, asr);
 +}
 +
 +static void
@@ -707,17 +759,26 @@ index 0000000..5b9cae1
 +static void
 +agg_update_sumroute(struct agg_proto *p, struct agg_sumroute *asr, struct agg_route *ar, rta *old, rta *new)
 +{
-+  switch (asr->route_src)
-+    {
-+#ifdef CONFIG_BGP
-+    case RTS_BGP:
-+      proto_bgp.update_sumroute(p, asr, ar, old, new);
-+      break;
-+#endif
-+    }
++  asr->proto->update_sumroute(p, asr, ar, old, new);
++}
++
++/*
++ * Trie callback function.
++ * Mark given summary route as deleted
++ */
++static void
++agg_mark_sumroute(struct f_trie_node *n, void *data UNUSED)
++{
++  struct agg_sumroute *asr = (struct agg_sumroute *)n;
++
++  if (!AGG_VALID_NODE(asr))
++    return;
++
++  asr->flags |= AGG_FLAG_DELETED;
 +}
 +
 +/*
++ * Trie callback function.
 + * Remove non-config data associated with summary route
 + */
 +static void
@@ -725,11 +786,12 @@ index 0000000..5b9cae1
 +{
 +  struct agg_proto *p = (struct agg_proto *)P;
 +  struct agg_sumroute *asr = (struct agg_sumroute *)tn;
++  struct agg_sumroute *asr_n = NULL;
 +  struct agg_membership *ms;
 +  struct agg_route *ar;
 +  node *n, *n_next;
 +
-+  if (!(asr->flags & AGG_FLAG_PREPARED))
++  if (!AGG_VALID_NODE(asr))
 +    return;
 +
 +  if (!(asr->flags & AGG_FLAG_DELETED))
@@ -743,28 +805,62 @@ index 0000000..5b9cae1
 +      agg_unlink_mroute(p, ms);
 +    }
 +
++  asr->mandatory_total = 0;
++  asr->mandatory_current = 0;
++
++  /*
++   * Check if we have some nested aggregation routes.
++   * E.g:
++   * 192.168.0.0/16
++   *   192.168.0.0/17 (Removed)
++   *
++   * Or even
++   * 192.168.0.0/16
++   *   192.168.0.0/17 (Removed)
++   *     192.168.0.0/18 (Removed) (*)
++   *
++   * Here we simply find the most specific route matching
++   * our current aggregated route and move all child routes
++   * to the new location.
++   *
++   * Use this logic IFF we're not shutting down (e.g. summary_trie is
++   * pointing to the new configuration).
++   */
++  if ((!p->going_down) && (asr->tn.plen))
++    asr_n = trie_match_longest_prefix(p->summary_trie, asr->tn.addr, asr->tn.plen - 1);
++
 +  WALK_LIST_DELSAFE(n, n_next, asr->routes)
 +    {
 +      ar = SKIP_BACK(struct agg_route, n_sumroute, n);
-+
++      /* Unlink from old summary */
 +      rem_node(&ar->n_sumroute);
 +
-+      if (ar->attrs)
-+	rta_free(ar->attrs);
-+      ar->attrs = NULL;
-+      ar->asr = NULL;
-+
-+      /* Check if we can delete route */
-+      if (!EMPTY_LIST(ar->sum_membership))
-+	continue;
-+
-+      /* Node can be safely deleted */
-+      fib_delete(&p->route_fib, ar);
++      /* Re-link child route to the new summary if exists */
++      if (asr_n)
++	{
++	  agg_link_childroute(p, asr_n, ar);
++	  ADBG("Moving child route %I/%d from summary %I/%d to %I/%d",
++		ar->fn.prefix, ar->fn.pxlen,
++		asr->tn.addr, asr->tn.plen,
++		asr_n->tn.addr, asr_n->tn.plen);
++	  /* Call route update */
++	  if (agg_can_announce(asr_n))
++	    agg_update_sumroute(p, asr_n, ar, NULL, ar->attrs);
++	}
++      else
++	agg_remove_childrole(p, ar);
 +    }
 +
 +  agg_withdraw_sumroute(p, asr);
++
++  /* Unset deleted flag to make the route exactly as at the beginning */
++  asr->flags &= ~AGG_FLAG_DELETED;
 +}
 +
++/*
++ * Trie callback function.
++ * Reconfigures summary route
++ */
 +static void
 +agg_reconfig_sumroute(struct f_trie_node *tn, void *P)
 +{
@@ -777,7 +873,7 @@ index 0000000..5b9cae1
 +  node *nn, *nn_next;
 +  int found;
 +
-+  if (!(asr->flags & AGG_FLAG_PREPARED))
++  if (!AGG_VALID_NODE(asr))
 +    return;
 +
 +  /* Find old corresponding route */
@@ -786,21 +882,30 @@ index 0000000..5b9cae1
 +  if ((!asr_o) || (!ipa_equal(asr_o->tn.addr, asr->tn.addr)) || (asr_o->tn.plen != asr->tn.plen) || 
 +	(asr_o->route_src != asr->route_src))
 +    {
-+      /* New summary route */
++      /*
++       * Old route is either not found (no candidate, different prefix) or has different type.
++       * Ignore and create new summary.
++       */
 +      agg_init_sumroute(p, asr);
 +      return;      
 +    }
 +
-+  /* Should we move this to protocol-specific hook? */
-+  switch (asr->route_src)
++  /*
++   * Route found. Let's check if generic and protocol-dependent data has changed:
++   */
++  if (((asr->flags & AGG_CONFIG_FLAGS) != (asr_o->flags & AGG_CONFIG_FLAGS)) ||
++	(asr->route_src != asr_o->route_src) || (asr->proto != asr_o->proto))
 +    {
-+    case RTS_BGP:
-+      if ((asr_o->u.bgp.local_id != asr->u.bgp.local_id) || (asr_o->u.bgp.local_as != asr->u.bgp.local_as))
-+	{
-+	  agg_init_sumroute(p, asr);
-+	  return;
-+	}
-+      break;
++      /* Reinit route due to changed config flags */
++      agg_init_sumroute(p, asr);
++      return;
++    }
++
++  /* Check if protocol-specific data has changed */
++  if (!asr->proto->check_sumroute(p, asr_o, asr))
++    {
++      agg_init_sumroute(p, asr);
++      return;
 +    }
 +
 +  ADBG("Reconfiguring summary route %I/%d", asr->tn.addr, asr->tn.plen);
@@ -810,31 +915,24 @@ index 0000000..5b9cae1
 +   * 1) remove DELETED flag
 +   * 2) move every route to new list
 +   * 3) compare mandatory routes
++   * 4) save announced route pointer if any
 +   */
 +
 +  asr_o->flags &= ~AGG_FLAG_DELETED;
 +
 +  /* 
-+   * Move usual routes to new list.
++   * Move child routes to new list.
 +   * Update ther pointer to summary route
 +   */
-+
 +  WALK_LIST_DELSAFE(n, n_next, asr_o->routes)
 +    {
 +      ar = SKIP_BACK(struct agg_route, n_sumroute, n);
 +
 +      ar->asr = asr;
++      rem_node(&ar->n_sumroute);
 +      add_tail(&asr->routes, &ar->n_sumroute);
 +    }
 +
-+  /* Mark old mandatory routes (instead of membership structurs) as deleted */
-+  WALK_LIST_DELSAFE(n, n_next, asr_o->mandatory_list)
-+    {
-+      ms = SKIP_BACK(struct agg_membership, n_sumroute, n);
-+      ar = ms->ar;
-+      ar->flags |= AGG_FLAG_DELETED;
-+    }
-+
 +  /* Walk all new mandatory routes */
 +  WALK_LIST_DELSAFE(n, n_next, asr->cf_routes)
 +    {
@@ -847,17 +945,27 @@ index 0000000..5b9cae1
 +      ar = fib_find(&p->route_fib, &cr->px.addr, cr->px.len);
 +
 +      if (!ar)
-+	  ar = agg_make_route(p, &cr->px.addr, cr->px.len);
++	{
++	  ar = fib_get(&p->route_fib, &cr->px.addr, cr->px.len);
++	  /*
++	   * FIXME: Use some direcct method (like applying protocol 
++	   * filter and import control to the best route)
++	   */
++	  p->need_refeed = 1;
++	}
 +
 +      /* Increate current counter IFF we have real best rte associated with entry */
-+      if (ar->attrs)
++      if (AGG_IS_INSTALLED(ar))
 +	{
 +	  asr->mandatory_current++;
-+	  ar->flags |= AGG_FLAG_INSTALLED;
++	  ADBG("Mandatory route %I/%d [re]marked as used", ar->fn.prefix, ar->fn.pxlen);
 +	}
 +
++      /* Indicate that this route is used as mandatory */
++      AGG_SET_MANDATORY(ar);
++
 +      /*
-+       * Check if we have summary membership with current asr (e.g.
++       * Check if we have summary membership with current (old) asr (e.g.
 +       * if we already are mandatory route for this asr). In this case
 +       * we have to update asr pointer.
 +       *
@@ -866,17 +974,18 @@ index 0000000..5b9cae1
 +       */
 +
 +      found = 0;
-+      WALK_LIST_DELSAFE(nn, nn_next, ar->sum_membership)
++      WALK_LIST_DELSAFE(nn, nn_next, ar->membership_list)
 +	{
-+	  ms = SKIP_BACK(struct agg_membership, n_mandatory, nn);
++	  ms = SKIP_BACK(struct agg_membership, n_route, nn);
 +	  if (ms->asr != asr_o)
 +	    continue;
 +
 +	  ADBG("Mandatory route %I/%d remains as is, removing deleted flag", ar->fn.prefix, ar->fn.pxlen);
 +	  /* Update pointers and relink */
 +	  ms->asr = asr;
++	  rem_node(&ms->n_sumroute);
 +	  add_tail(&asr->mandatory_list, &ms->n_sumroute);
-+	  ar->flags &= ~AGG_FLAG_DELETED;
++	  ms->flags &= ~AGG_FLAG_DELETED;
 +	  found = 1;
 +	  break;
 +	}
@@ -888,24 +997,15 @@ index 0000000..5b9cae1
 +      agg_link_mroute(p, asr, ar);
 +    }
 +
-+  /* Delete old mandatory routes */
++  /* Delete remaining membership structures */
 +  WALK_LIST_DELSAFE(n, n_next, asr_o->mandatory_list)
 +    {
 +      ms = SKIP_BACK(struct agg_membership, n_sumroute, n);
-+      ar = ms->ar;
-+      if (!(ar->flags & AGG_FLAG_DELETED))
-+	continue;
-+
-+      /* 
-+       * This route is not mandatory for new asr.
-+       * No need to update old configuration so
-+       * we need to unlink node from ar and free it
-+       */
-+
 +      agg_unlink_mroute(p, ms);
 +    }
 +
-+  /* XXX: we can possibly check new mandatory routes */
++  /* Finally, save pointer to announced rta */
++  asr->attrs = asr_o->attrs;
 +}
 +
 +static int
@@ -914,7 +1014,6 @@ index 0000000..5b9cae1
 +  struct agg_config *o = (struct agg_config *)P->cf;
 +  struct agg_config *n = (struct agg_config *)new;
 +  struct agg_proto *p = (struct agg_proto *)P;
-+  //struct agg_sumroute *;
 +
 +  ADBG("Reconfiguting..");
 +
@@ -924,27 +1023,52 @@ index 0000000..5b9cae1
 +  /* Walk new trie */
 +  trie_walk(n->summary_trie, agg_reconfig_sumroute, p);
 +
++  /*
++   * Update trie pointer. We need new summary trie pointer
++   * since agg_clear_sumroute() can possibly move child
++   * routes to new summary route. On the other way,
++   * agg_reconfig_sumroute() needs old pointer to find
++   * old summary route corresponding to new.
++   */
++  p->summary_trie = n->summary_trie;
++
 +  /* Cleanup all old summary routes */
 +  trie_walk(o->summary_trie, agg_clear_sumroute, p);
 +
-+  /* 
-+   * XXX: we possibly have to determine if summary routes configuration
-+   * is changed and we hate to request refeeding
-+   */
-+
-+  /* Update trie pointer */
-+  p->summary_trie = n->summary_trie;
++  /* Request feeding if some new summary routes appeared */
++  if (p->need_refeed)
++    {
++      ADBG("Refeeding due to new summary routes configured");
++      proto_request_feeding(P);
++      p->need_refeed = 0;
++    }
 +
 +  return 1;
 +}
 +
++static void
++agg_unlink_childroute(struct agg_proto *p, struct agg_sumroute *asr, struct agg_route *ar)
++{
++  /* Delete item from summary route child list */
++  rem_node(&ar->n_sumroute);
++
++  /* Update or withdraw summary route */
++  if (agg_can_announce(asr))
++    {
++      if (!EMPTY_LIST(asr->routes))
++	agg_update_sumroute(p, asr, ar, ar->attrs, NULL);
++      else
++	agg_withdraw_sumroute(p, asr);
++    }
++}
++
 +
 +static void
 +agg_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs)
 +{
 +  struct agg_proto *p = (struct agg_proto *) P;
 +  struct agg_sumroute *asr;
-+  struct agg_route *ar;
++  struct agg_route *ar = NULL, *ar_child = NULL;
 +  struct agg_membership *ms;
 +  node *nn, *nn_next;
 +  rta *old_rta = NULL, *new_rta;
@@ -965,9 +1089,10 @@ index 0000000..5b9cae1
 +   * Search trie to determine summary route.
 +   * We use 1 bit less specific prefix to deal with the following 2 cases:
 +   * 1) if announced X/Y prefix is the same as summary route this is clearly not the case for summarization
-+   * 2) if nested summary routes are congigured and 1) is in action we got wrong asr pointer.
++   * 2) if nested summary routes are configured and 1) is in action we got wrong asr pointer.
 +   *
-+   * We skip 0/0 and :: due to it can'be summarized
++   * We skip 0/0 and :: due to it can'be summarized.
++   * We also assume trie_match() to normalize address with network mask
 +   */
 +  if ((n->n.pxlen) && ((asr = trie_match_longest_prefix(p->summary_trie, n->n.prefix, n->n.pxlen - 1))))
 +    {
@@ -979,7 +1104,7 @@ index 0000000..5b9cae1
 +	ADBG("Found matched summary route %I/%d", asr->tn.addr, asr->tn.plen);
 +      
 +	/* Summary route found. Let's find/create route node */
-+	ar = agg_make_route(p, &n->n.prefix, n->n.pxlen);
++	ar = fib_get(&p->route_fib, &n->n.prefix, n->n.pxlen);
 +      
 +	/* (new route, route update) */
 +	if (new)
@@ -1015,78 +1140,120 @@ index 0000000..5b9cae1
 +		new_rta->aflags = 0;
 +		ar->attrs = rta_clone(rta_lookup(new_rta));
 +	      }
++
++	    /*
++	     * We can't mark ar as installed since this can interfere with mandatory routes
++	     * checking later. We save ar into new pointer and set installed flag in the end
++	     * instead.
++	     */
++	    ar_child = ar;
 +      
 +	    /* Add link to summary route if route is new */
-+	    if (!ar->asr)
++	    if (!AGG_IS_CHILD(ar))
 +	      {
-+		ar->asr = asr;
-+		add_tail(&asr->routes, &ar->n_sumroute);
++		AGG_SET_CHILD(ar);
++		agg_link_childroute(p, asr, ar);
 +	      }
++	    else if (ar->asr != asr)
++	    {
++	      /*
++	       * Route is a child of different summary route.
++	       * Let's make withdraw for the old summary
++	       * and send route update to the new one
++	       */
++	      ADBG("Moving route %I/%d from %I/%d to %I/%d", n->n.prefix, n->n.pxlen,
++		ar->asr->tn.addr, ar->asr->tn.plen, asr->tn.addr, asr->tn.plen);
++	      agg_unlink_childroute(p, ar->asr, ar);
++	      agg_link_childroute(p, asr, ar);
++

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208151640.q7FGeEUB080947>