svn commit: r302586 - in head/net: bird bird/files bird6 bird6/files
Sergey Matveychuk
sem at FreeBSD.org
Wed Aug 15 16:40:14 UTC 2012
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 at 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 <name> {
++ bgp id <id> as <as< {
++ aggregate address <prefix>;
++ aggregate address <prefix< mandatory list {
++ <prefix<,
++ <prefix<,
++ <prefix<
++ };
++ aggregate address <prefix> 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 at 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 ***
More information about the svn-ports-head
mailing list