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 <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@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>