0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-11 03:21:53 +00:00

Merge commit 'c93c02088a026b83f452fbd260135ba4c8da7ecf' into integrated

This commit is contained in:
Ondrej Zajicek 2013-01-13 00:36:29 +01:00
commit c570200d39
14 changed files with 200 additions and 80 deletions

6
NEWS
View File

@ -1,3 +1,9 @@
Version 1.3.9 (2012-11-16)
o BIRD can be configured to keep and show filtered routes.
o Dragonfly BSD support.
o Fixed OSPFv3 vlinks.
o Several minor bugfixes.
Version 1.3.8 (2012-08-07) Version 1.3.8 (2012-08-07)
o Generalized import and export route limits. o Generalized import and export route limits.
o RDNSS and DNSSL support for RAdv. o RDNSS and DNSSL support for RAdv.

View File

@ -459,6 +459,14 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
works in the direction from the routing table to the protocol. works in the direction from the routing table to the protocol.
Default: <cf/none/. Default: <cf/none/.
<tag>import keep filtered <m/bool/</tag>
Usually, if an import filter rejects a route, the route is
forgotten. When this option is active, these routes are
kept in the routing table, but they are hidden and not
propagated to other protocols. But it is possible to show them
using <cf/show route filtered/. Note that this option does not
work for the pipe protocol. Default: off.
<tag>import limit <m/number/ [action warn | block | restart | disable]</tag> <tag>import limit <m/number/ [action warn | block | restart | disable]</tag>
Specify an import route limit (a maximum number of routes Specify an import route limit (a maximum number of routes
imported from the protocol) and optionally the action to be imported from the protocol) and optionally the action to be
@ -467,8 +475,11 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
protocol. Restart and disable actions shut the protocol down protocol. Restart and disable actions shut the protocol down
like appropriate commands. Disable is the default action if an like appropriate commands. Disable is the default action if an
action is not explicitly specified. Note that limits are reset action is not explicitly specified. Note that limits are reset
during protocol reconfigure, reload or restart. during protocol reconfigure, reload or restart. Also note that
Default: <cf/none/. if <cf/import keep filtered/ is active, filtered routes are
counted towards the limit and blocked routes are forgotten, as
the main purpose of the import limit is to protect routing
tables from overflow. Default: <cf/none/.
<tag>export limit <m/number/ [action warn | block | restart | disable]</tag> <tag>export limit <m/number/ [action warn | block | restart | disable]</tag>
Specify an export route limit, works similarly to Specify an export route limit, works similarly to
@ -661,6 +672,9 @@ This argument can be omitted if there exists only a single instance.
<p>You can also select just routes added by a specific protocol. <p>You can also select just routes added by a specific protocol.
<cf>protocol <m/p/</cf>. <cf>protocol <m/p/</cf>.
<p>If BIRD is configured to keep filtered routes (see </cf/import keep filtered/
option), you can show them instead of routes by using </cf/filtered/ switch.
<p>The <cf/stats/ switch requests showing of route statistics (the <p>The <cf/stats/ switch requests showing of route statistics (the
number of networks, number of routes before and after filtering). If number of networks, number of routes before and after filtering). If
you use <cf/count/ instead, only the statistics will be printed. you use <cf/count/ instead, only the statistics will be printed.
@ -1640,6 +1654,15 @@ use cases that use the direct protocol (like abusing eBGP as an IGP
routing protocol), in most cases it is not needed to have these device routing protocol), in most cases it is not needed to have these device
routes in BIRD routing table and to use the direct protocol. routes in BIRD routing table and to use the direct protocol.
<p>There is one notable case when you definitely want to use the
direct protocol -- running BIRD on BSD systems. Having high priority
device routes for directly connected networks from the direct protocol
protects kernel device routes from being overwritten or removed by IGP
routes during some transient network conditions, because a lower
priority IGP route for the same network is not exported to the kernel
routing table. This is an issue on BSD systems only, as on Linux
systems BIRD cannot change non-BIRD route in the kernel routing table.
<p>The only configurable thing about direct is what interfaces it watches: <p>The only configurable thing about direct is what interfaces it watches:
<p><descrip> <p><descrip>
@ -2460,13 +2483,13 @@ interface definitions, prefix definitions and DNS definitions:
router. 0 means do not use as a default router. Default: 3 * router. 0 means do not use as a default router. Default: 3 *
<cf/max ra interval/. <cf/max ra interval/.
<tag>rdnss local <m/bool/</tag> <tag>rdnss local <m/switch/</tag>
Use only local (interface-specific) RDNSS definitions for this Use only local (interface-specific) RDNSS definitions for this
interface. Otherwise, both global and local definitions are interface. Otherwise, both global and local definitions are
used. Could also be used to disable RDNSS for given interface used. Could also be used to disable RDNSS for given interface
if no local definitons are specified. Default: no. if no local definitons are specified. Default: no.
<tag>dnssl local <m/bool/</tag> <tag>dnssl local <m/switch/</tag>
Use only local DNSSL definitions for this interface. See Use only local DNSSL definitions for this interface. See
<cf/rdnss local/ option above. Default: no. <cf/rdnss local/ option above. Default: no.
</descrip> </descrip>

View File

@ -1,6 +1,6 @@
Summary: BIRD Internet Routing Daemon Summary: BIRD Internet Routing Daemon
Name: bird Name: bird
Version: 1.3.8 Version: 1.3.9
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Networking/Daemons Group: Networking/Daemons

View File

@ -45,7 +45,7 @@ CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6, MPLS) CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6, MPLS)
CF_KEYWORDS(LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE) CF_KEYWORDS(LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, AS, MAX, FLUSH) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, AS, MAX, FLUSH)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED) CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
@ -190,6 +190,7 @@ proto_item:
| EXPORT imexport { this_proto->out_filter = $2; } | EXPORT imexport { this_proto->out_filter = $2; }
| IMPORT LIMIT limit_spec { this_proto->in_limit = $3; } | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
| EXPORT LIMIT limit_spec { this_proto->out_limit = $3; } | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
| IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
| TABLE rtable { | TABLE rtable {
if (!rt_match($2->addr_type, this_proto->protocol->tables)) if (!rt_match($2->addr_type, this_proto->protocol->tables))
cf_error("Incompatible table class"); cf_error("Incompatible table class");
@ -412,7 +413,7 @@ CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
{ if_show_summary(); } ; { if_show_summary(); } ;
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]]) CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
CF_CLI(SHOW ROUTE, r_args, [[[<prefix>|for <prefix>|for <ip>] [table <t>] [filter <f>|where <cond>] [all] [primary] [(export|preexport) <p>] [protocol <p>] [stats|count]]], [[Show routing table]]) CF_CLI(SHOW ROUTE, r_args, [[[<prefix>|for <prefix>|for <ip>] [table <t>] [filter <f>|where <cond>] [all] [primary] [filtered] [(export|preexport) <p>] [protocol <p>] [stats|count]]], [[Show routing table]])
{ rt_show($3); } ; { rt_show($3); } ;
r_args: r_args:
@ -458,6 +459,10 @@ r_args:
$$ = $1; $$ = $1;
$$->primary_only = 1; $$->primary_only = 1;
} }
| r_args FILTERED {
$$ = $1;
$$->filtered = 1;
}
| r_args export_or_preexport SYM { | r_args export_or_preexport SYM {
struct proto_config *c = (struct proto_config *) $3->def; struct proto_config *c = (struct proto_config *) $3->def;
$$ = $1; $$ = $1;

View File

@ -414,6 +414,7 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
p->main_ahook->out_filter = nc->out_filter; p->main_ahook->out_filter = nc->out_filter;
p->main_ahook->in_limit = nc->in_limit; p->main_ahook->in_limit = nc->in_limit;
p->main_ahook->out_limit = nc->out_limit; p->main_ahook->out_limit = nc->out_limit;
p->main_ahook->in_keep_filtered = nc->in_keep_filtered;
} }
/* Update routes when filters changed. If the protocol in not UP, /* Update routes when filters changed. If the protocol in not UP,
@ -720,8 +721,9 @@ proto_fell_down(struct proto *p)
{ {
DBG("Protocol %s down\n", p->name); DBG("Protocol %s down\n", p->name);
if (p->stats.imp_routes != 0) u32 all_routes = p->stats.imp_routes + p->stats.filt_routes;
log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes); if (all_routes != 0)
log(L_ERR "Protocol %s is down but still has %d routes", p->name, all_routes);
bzero(&p->stats, sizeof(struct proto_stats)); bzero(&p->stats, sizeof(struct proto_stats));
proto_free_ahooks(p); proto_free_ahooks(p);
@ -797,6 +799,7 @@ proto_schedule_feed(struct proto *p, int initial)
p->main_ahook->out_filter = p->cf->out_filter; p->main_ahook->out_filter = p->cf->out_filter;
p->main_ahook->in_limit = p->cf->in_limit; p->main_ahook->in_limit = p->cf->in_limit;
p->main_ahook->out_limit = p->cf->out_limit; p->main_ahook->out_limit = p->cf->out_limit;
p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
proto_reset_limit(p->main_ahook->in_limit); proto_reset_limit(p->main_ahook->in_limit);
proto_reset_limit(p->main_ahook->out_limit); proto_reset_limit(p->main_ahook->out_limit);
} }
@ -1094,10 +1097,15 @@ proto_state_name(struct proto *p)
} }
static void static void
proto_show_stats(struct proto_stats *s) proto_show_stats(struct proto_stats *s, int in_keep_filtered)
{ {
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred", if (in_keep_filtered)
s->imp_routes, s->exp_routes, s->pref_routes); cli_msg(-1006, " Routes: %u imported, %u filtered, %u exported, %u preferred",
s->imp_routes, s->filt_routes, s->exp_routes, s->pref_routes);
else
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
s->imp_routes, s->exp_routes, s->pref_routes);
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted"); cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u", cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
s->imp_updates_received, s->imp_updates_invalid, s->imp_updates_received, s->imp_updates_invalid,
@ -1135,7 +1143,7 @@ proto_show_basic_info(struct proto *p)
proto_show_limit(p->cf->out_limit, "Export limit:"); proto_show_limit(p->cf->out_limit, "Export limit:");
if (p->proto_state != PS_DOWN) if (p->proto_state != PS_DOWN)
proto_show_stats(&p->stats); proto_show_stats(&p->stats, p->cf->in_keep_filtered);
} }
void void

View File

@ -92,6 +92,7 @@ struct proto_config {
int class; /* SYM_PROTO or SYM_TEMPLATE */ int class; /* SYM_PROTO or SYM_TEMPLATE */
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */ u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
unsigned preference, disabled; /* Generic parameters */ unsigned preference, disabled; /* Generic parameters */
int in_keep_filtered; /* Routes rejected in import filter are kept */
u32 router_id; /* Protocol specific router ID */ u32 router_id; /* Protocol specific router ID */
struct rtable_config *table; /* Table we're attached to */ struct rtable_config *table; /* Table we're attached to */
struct filter *in_filter, *out_filter; /* Attached filters */ struct filter *in_filter, *out_filter; /* Attached filters */
@ -107,7 +108,8 @@ struct proto_config {
struct proto_stats { struct proto_stats {
/* Import - from protocol to core */ /* Import - from protocol to core */
u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */ u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */
u32 pref_routes; /* Number of routes that are preferred, sum over all routing table */ u32 filt_routes; /* Number of routes rejected in import filter but kept in the routing table */
u32 pref_routes; /* Number of routes that are preferred, sum over all routing tables */
u32 imp_updates_received; /* Number of route updates received */ u32 imp_updates_received; /* Number of route updates received */
u32 imp_updates_invalid; /* Number of route updates rejected as invalid */ u32 imp_updates_invalid; /* Number of route updates rejected as invalid */
u32 imp_updates_filtered; /* Number of route updates rejected by filters */ u32 imp_updates_filtered; /* Number of route updates rejected by filters */
@ -411,6 +413,7 @@ struct announce_hook {
struct proto_limit *out_limit; /* Output limit */ struct proto_limit *out_limit; /* Output limit */
struct proto_stats *stats; /* Per-table protocol statistics */ struct proto_stats *stats; /* Per-table protocol statistics */
struct announce_hook *next; /* Next hook for the same protocol */ struct announce_hook *next; /* Next hook for the same protocol */
int in_keep_filtered; /* Routes rejected in import filter are kept */
}; };
struct announce_hook *proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats); struct announce_hook *proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats);

View File

@ -241,6 +241,14 @@ typedef struct rte {
} rte; } rte;
#define REF_COW 1 /* Copy this rte on write */ #define REF_COW 1 /* Copy this rte on write */
#define REF_FILTERED 2 /* Route is rejected by import filter */
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
/* Route just has REF_FILTERED flag */
static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); }
/* Types of routing tables/entries */ /* Types of routing tables/entries */
#define RT_IPV4 1 #define RT_IPV4 1
@ -308,7 +316,7 @@ struct rt_show_data {
struct fib_iterator fit; struct fib_iterator fit;
struct proto *show_protocol; struct proto *show_protocol;
struct proto *export_protocol; struct proto *export_protocol;
int export_mode, primary_only; int export_mode, primary_only, filtered;
struct config *running_on_config; struct config *running_on_config;
int net_counter, rt_counter, show_counter; int net_counter, rt_counter, show_counter;
int stats, show_for; int stats, show_for;

View File

@ -72,7 +72,7 @@ net_route(rtable *tab, ip_addr a, int len)
{ {
a0 = ipa_and(a, ipa_mkmask(len)); a0 = ipa_and(a, ipa_mkmask(len));
n = fib_find(&tab->fib, &a0, len); n = fib_find(&tab->fib, &a0, len);
if (n && n->routes) if (n && rte_is_valid(n->routes))
return n; return n;
len--; len--;
} }
@ -142,8 +142,11 @@ rte_better(rte *new, rte *old)
{ {
int (*better)(rte *, rte *); int (*better)(rte *, rte *);
if (!old) if (!rte_is_valid(old))
return 1; return 1;
if (!rte_is_valid(new))
return 0;
if (new->pref > old->pref) if (new->pref > old->pref)
return 1; return 1;
if (new->pref < old->pref) if (new->pref < old->pref)
@ -402,9 +405,13 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
rte *old_free = NULL; rte *old_free = NULL;
rte *r; rte *r;
/* Used to track whether we met old_changed position. If it is NULL /* Used to track whether we met old_changed position. If before_old is NULL
it was the first and met it implicitly before current best route. */ old_changed was the first and we met it implicitly before current best route. */
int old_meet = (old_changed && !before_old) ? 1 : 0; int old_meet = old_changed && !before_old;
/* Note that before_old is either NULL or valid (not rejected) route.
If old_changed is valid, before_old have to be too. If old changed route
was not valid, caller must use NULL for both old_changed and before_old. */
if (new_changed) if (new_changed)
stats->exp_updates_received++; stats->exp_updates_received++;
@ -412,7 +419,7 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
stats->exp_withdraws_received++; stats->exp_withdraws_received++;
/* First, find the new_best route - first accepted by filters */ /* First, find the new_best route - first accepted by filters */
for (r=net->routes; r; r=r->next) for (r=net->routes; rte_is_valid(r); r=r->next)
{ {
if (new_best = export_filter(ah, r, &new_free, &tmpa, 0)) if (new_best = export_filter(ah, r, &new_free, &tmpa, 0))
break; break;
@ -431,7 +438,8 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
if (feed) if (feed)
{ {
if (feed == 2) /* refeed */ if (feed == 2) /* refeed */
old_best = new_best ? new_best : net->routes; old_best = new_best ? new_best :
(rte_is_valid(net->routes) ? net->routes : NULL);
else else
old_best = NULL; old_best = NULL;
@ -480,7 +488,7 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
} }
/* Fourth case */ /* Fourth case */
for (r=r->next; r; r=r->next) for (r=r->next; rte_is_valid(r); r=r->next)
{ {
if (old_best = export_filter(ah, r, &old_free, NULL, 1)) if (old_best = export_filter(ah, r, &old_free, NULL, 1))
goto found; goto found;
@ -534,7 +542,14 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
static void static void
rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *before_old, ea_list *tmpa) rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *before_old, ea_list *tmpa)
{ {
struct announce_hook *a; if (!rte_is_valid(old))
old = before_old = NULL;
if (!rte_is_valid(new))
new = NULL;
if (!old && !new)
return;
if (type == RA_OPTIMAL) if (type == RA_OPTIMAL)
{ {
@ -547,6 +562,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *befo
rt_notify_hostcache(tab, net); rt_notify_hostcache(tab, net);
} }
struct announce_hook *a;
WALK_LIST(a, tab->hooks) WALK_LIST(a, tab->hooks)
{ {
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING); ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
@ -618,6 +634,8 @@ rte_same(rte *x, rte *y)
(!x->attrs->proto->rte_same || x->attrs->proto->rte_same(x, y)); (!x->attrs->proto->rte_same || x->attrs->proto->rte_same(x, y));
} }
static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); }
static void static void
rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src) rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
{ {
@ -657,8 +675,13 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
if (new && rte_same(old, new)) if (new && rte_same(old, new))
{ {
/* No changes, ignore the new route */ /* No changes, ignore the new route */
stats->imp_updates_ignored++;
rte_trace_in(D_ROUTES, p, new, "ignored"); if (!rte_is_filtered(new))
{
stats->imp_updates_ignored++;
rte_trace_in(D_ROUTES, p, new, "ignored");
}
rte_free_quick(new); rte_free_quick(new);
#ifdef CONFIG_RIP #ifdef CONFIG_RIP
/* lastmod is used internally by RIP as the last time /* lastmod is used internally by RIP as the last time
@ -688,8 +711,10 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
struct proto_limit *l = ah->in_limit; struct proto_limit *l = ah->in_limit;
if (l && !old && new) if (l && !old && new)
{ {
if (stats->imp_routes >= l->limit) u32 all_routes = stats->imp_routes + stats->filt_routes;
proto_notify_limit(ah, l, stats->imp_routes);
if (all_routes >= l->limit)
proto_notify_limit(ah, l, all_routes);
if (l->state == PLS_BLOCKED) if (l->state == PLS_BLOCKED)
{ {
@ -700,15 +725,20 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
} }
} }
if (new) int new_ok = rte_is_ok(new);
int old_ok = rte_is_ok(old);
if (new_ok)
stats->imp_updates_accepted++; stats->imp_updates_accepted++;
else else if (old_ok)
stats->imp_withdraws_accepted++; stats->imp_withdraws_accepted++;
else
stats->imp_withdraws_ignored++;
if (new) if (new)
stats->imp_routes++; rte_is_filtered(new) ? stats->filt_routes++ : stats->imp_routes++;
if (old) if (old)
stats->imp_routes--; rte_is_filtered(old) ? stats->filt_routes-- : stats->imp_routes--;
if (table->config->sorted) if (table->config->sorted)
{ {
@ -793,17 +823,19 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
new->lastmod = now; new->lastmod = now;
/* Log the route change */ /* Log the route change */
if (new) if (p->debug & D_ROUTES)
rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");
if (!new && (p->debug & D_ROUTES))
{ {
if (old != old_best) if (new_ok)
rte_trace_in(D_ROUTES, p, old, "removed"); rte_trace(p, new, '>', new == net->routes ? "added [best]" : "added");
else if (net->routes) else if (old_ok)
rte_trace_in(D_ROUTES, p, old, "removed [replaced]"); {
else if (old != old_best)
rte_trace_in(D_ROUTES, p, old, "removed [sole]"); rte_trace(p, old, '>', "removed");
else if (rte_is_ok(net->routes))
rte_trace(p, old, '>', "removed [replaced]");
else
rte_trace(p, old, '>', "removed [sole]");
}
} }
/* Propagate the route change */ /* Propagate the route change */
@ -818,17 +850,13 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
(table->gc_time + table->config->gc_min_time <= now)) (table->gc_time + table->config->gc_min_time <= now))
rt_schedule_gc(table); rt_schedule_gc(table);
if (old_ok && p->rte_remove)
p->rte_remove(net, old);
if (new_ok && p->rte_insert)
p->rte_insert(net, new);
if (old) if (old)
{ rte_free_quick(old);
if (p->rte_remove)
p->rte_remove(net, old);
rte_free_quick(old);
}
if (new)
{
if (p->rte_insert)
p->rte_insert(net, new);
}
} }
static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */ static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */
@ -908,27 +936,41 @@ rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src)
stats->imp_updates_invalid++; stats->imp_updates_invalid++;
goto drop; goto drop;
} }
if (filter == FILTER_REJECT) if (filter == FILTER_REJECT)
{ {
stats->imp_updates_filtered++; stats->imp_updates_filtered++;
rte_trace_in(D_FILTERS, p, new, "filtered out"); rte_trace_in(D_FILTERS, p, new, "filtered out");
goto drop;
if (! ah->in_keep_filtered)
goto drop;
/* new is a private copy, i could modify it */
new->flags |= REF_FILTERED;
} }
if (src->make_tmp_attrs) else
tmpa = src->make_tmp_attrs(new, rte_update_pool);
if (filter)
{ {
ea_list *old_tmpa = tmpa; if (src->make_tmp_attrs)
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0); tmpa = src->make_tmp_attrs(new, rte_update_pool);
if (fr > F_ACCEPT) if (filter && (filter != FILTER_REJECT))
{ {
stats->imp_updates_filtered++; ea_list *old_tmpa = tmpa;
rte_trace_in(D_FILTERS, p, new, "filtered out"); int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
goto drop; if (fr > F_ACCEPT)
{
stats->imp_updates_filtered++;
rte_trace_in(D_FILTERS, p, new, "filtered out");
if (! ah->in_keep_filtered)
goto drop;
new->flags |= REF_FILTERED;
}
if (tmpa != old_tmpa && src->store_tmp_attrs)
src->store_tmp_attrs(new, tmpa);
} }
if (tmpa != old_tmpa && src->store_tmp_attrs)
src->store_tmp_attrs(new, tmpa);
} }
if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */ if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
new->attrs = rta_lookup(new->attrs); new->attrs = rta_lookup(new->attrs);
new->flags |= REF_COW; new->flags |= REF_COW;
@ -1618,9 +1660,11 @@ again:
return 0; return 0;
} }
/* XXXX perhaps we should change feed for RA_ACCEPTED to not use 'new' */
if ((p->accept_ra_types == RA_OPTIMAL) || if ((p->accept_ra_types == RA_OPTIMAL) ||
(p->accept_ra_types == RA_ACCEPTED)) (p->accept_ra_types == RA_ACCEPTED))
if (e) if (rte_is_valid(e))
{ {
if (p->core_state != FS_FEEDING) if (p->core_state != FS_FEEDING)
return 1; /* In the meantime, the protocol fell down. */ return 1; /* In the meantime, the protocol fell down. */
@ -1629,7 +1673,7 @@ again:
} }
if (p->accept_ra_types == RA_ANY) if (p->accept_ra_types == RA_ANY)
for(e = n->routes; e != NULL; e = e->next) for(e = n->routes; rte_is_valid(e); e = e->next)
{ {
if (p->core_state != FS_FEEDING) if (p->core_state != FS_FEEDING)
return 1; /* In the meantime, the protocol fell down. */ return 1; /* In the meantime, the protocol fell down. */
@ -1884,7 +1928,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH); net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
if (n) if (n)
{ {
rta *a = n->routes->attrs; rte *e = n->routes;
rta *a = e->attrs;
pxlen = n->n.pxlen; pxlen = n->n.pxlen;
if (a->hostentry) if (a->hostentry)
@ -1917,7 +1962,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
} }
he->src = rta_clone(a); he->src = rta_clone(a);
he->igp_metric = rt_get_igp_metric(n->routes); he->igp_metric = rt_get_igp_metric(e);
} }
done: done:
@ -2061,14 +2106,19 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
int ok; int ok;
fn_print(prefix, sizeof(prefix), &n->n); fn_print(prefix, sizeof(prefix), &n->n);
if (n->routes)
d->net_counter++;
for(e=n->routes; e; e=e->next) for(e=n->routes; e; e=e->next)
{ {
if (rte_is_filtered(e) != d->filtered)
continue;
struct ea_list *tmpa; struct ea_list *tmpa;
struct proto *p0 = e->attrs->proto; struct proto *p0 = e->attrs->proto;
struct proto *p1 = d->export_protocol; struct proto *p1 = d->export_protocol;
struct proto *p2 = d->show_protocol; struct proto *p2 = d->show_protocol;
if (prefix[0])
d->net_counter++;
d->rt_counter++; d->rt_counter++;
ee = e; ee = e;
rte_update_lock(); /* We use the update buffer for filtering */ rte_update_lock(); /* We use the update buffer for filtering */

View File

@ -238,7 +238,7 @@ bgp_format_aggregator(eattr *a, byte *buf, int buflen UNUSED)
as = get_u32(data); as = get_u32(data);
data += 4; data += 4;
bsprintf(buf, "%d.%d.%d.%d AS%d", data[0], data[1], data[2], data[3], as); bsprintf(buf, "%d.%d.%d.%d AS%u", data[0], data[1], data[2], data[3], as);
} }
static int static int
@ -1346,7 +1346,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
/* The default case - find a new best-in-group route */ /* The default case - find a new best-in-group route */
r = new; /* new may not be in the list */ r = new; /* new may not be in the list */
for (s=net->routes; s; s=s->next) for (s=net->routes; rte_is_valid(s); s=s->next)
if (use_deterministic_med(s) && same_group(s, lpref, lasn)) if (use_deterministic_med(s) && same_group(s, lpref, lasn))
{ {
s->u.bgp.suppressed = 1; s->u.bgp.suppressed = 1;

View File

@ -1188,7 +1188,7 @@ bgp_show_proto_info(struct proto *P)
cli_msg(-1006, " Source address: %I", p->source_addr); cli_msg(-1006, " Source address: %I", p->source_addr);
if (P->cf->in_limit) if (P->cf->in_limit)
cli_msg(-1006, " Route limit: %d/%d", cli_msg(-1006, " Route limit: %d/%d",
p->p.stats.imp_routes, P->cf->in_limit->limit); p->p.stats.imp_routes + p->p.stats.filt_routes, P->cf->in_limit->limit);
cli_msg(-1006, " Hold timer: %d/%d", cli_msg(-1006, " Hold timer: %d/%d",
tm_remains(c->hold_timer), c->hold_time); tm_remains(c->hold_timer), c->hold_time);
cli_msg(-1006, " Keepalive timer: %d/%d", cli_msg(-1006, " Keepalive timer: %d/%d",

View File

@ -973,6 +973,10 @@ ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
struct ifa *a; struct ifa *a;
WALK_LIST(iface, iface_list) WALK_LIST(iface, iface_list)
{
if (! (iface->flags & IF_UP))
continue;
WALK_LIST(a, iface->addrs) WALK_LIST(a, iface->addrs)
{ {
if (a->flags & IA_SECONDARY) if (a->flags & IA_SECONDARY)
@ -998,6 +1002,7 @@ ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
ospf_iface_new(oa, a, ip); ospf_iface_new(oa, a, ip);
} }
} }
}
} }
static void static void
@ -1008,6 +1013,10 @@ ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
struct ifa *a; struct ifa *a;
WALK_LIST(iface, iface_list) WALK_LIST(iface, iface_list)
{
if (! (iface->flags & IF_UP))
continue;
WALK_LIST(a, iface->addrs) WALK_LIST(a, iface->addrs)
{ {
if (a->flags & IA_SECONDARY) if (a->flags & IA_SECONDARY)
@ -1036,6 +1045,7 @@ ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
ospf_iface_new(oa, a, ip); ospf_iface_new(oa, a, ip);
} }
} }
}
} }
void void

View File

@ -262,8 +262,15 @@ originate_rt2_lsa_body(struct ospf_area *oa, u16 *length)
WALK_LIST(neigh, ifa->neigh_list) WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL) if (neigh->state == NEIGHBOR_FULL)
{ {
u32 data = (ifa->addr->flags & IA_PEER) ? ifa->iface_id : ipa_to_u32(ifa->addr->ip); /*
add_rt2_lsa_link(po, LSART_PTP, neigh->rid, data, ifa->cost); * ln->data should be ifa->iface_id in case of no/ptp
* address (ifa->addr->flags & IA_PEER) on PTP link (see
* RFC 2328 12.4.1.1.), but the iface ID value has no use,
* while using IP address even in this case is here for
* compatibility with some broken implementations that use
* this address as a next-hop.
*/
add_rt2_lsa_link(po, LSART_PTP, neigh->rid, ipa_to_u32(ifa->addr->ip), ifa->cost);
i++; i++;
} }
break; break;
@ -294,7 +301,7 @@ originate_rt2_lsa_body(struct ospf_area *oa, u16 *length)
/* Now we will originate stub area if there is no primary */ /* Now we will originate stub area if there is no primary */
if (net_lsa || if (net_lsa ||
(ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_VLINK) ||
(ifa->addr->flags & IA_PEER) || ((ifa->addr->flags & IA_PEER) && ! ifa->cf->stub) ||
configured_stubnet(oa, ifa->addr)) configured_stubnet(oa, ifa->addr))
continue; continue;

View File

@ -7,7 +7,7 @@
#define _BIRD_CONFIG_H_ #define _BIRD_CONFIG_H_
/* BIRD version */ /* BIRD version */
#define BIRD_VERSION "1.3.8" #define BIRD_VERSION "1.3.9"
// XXXX temporary define // XXXX temporary define
#define IPV1 1 #define IPV1 1

View File

@ -581,7 +581,7 @@ krt_flush_routes(struct krt_proto *p)
{ {
net *n = (net *) f; net *n = (net *) f;
rte *e = n->routes; rte *e = n->routes;
if (e && (n->n.flags & KRF_INSTALLED)) if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
{ {
/* FIXME: this does not work if gw is changed in export filter */ /* FIXME: this does not work if gw is changed in export filter */
krt_replace_rte(p, e->net, NULL, e, NULL); krt_replace_rte(p, e->net, NULL, e, NULL);
@ -657,7 +657,7 @@ krt_got_route(struct krt_proto *p, rte *e)
} }
old = net->routes; old = net->routes;
if ((net->n.flags & KRF_INSTALLED) && old) if ((net->n.flags & KRF_INSTALLED) && rte_is_valid(old))
{ {
/* There may be changes in route attributes, we ignore that. /* There may be changes in route attributes, we ignore that.
Also, this does not work well if gw is changed in export filter */ Also, this does not work well if gw is changed in export filter */