mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 10:11:53 +00:00
Merge commit 'c93c02088a026b83f452fbd260135ba4c8da7ecf' into integrated
This commit is contained in:
commit
c570200d39
6
NEWS
6
NEWS
@ -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)
|
||||
o Generalized import and export route limits.
|
||||
o RDNSS and DNSSL support for RAdv.
|
||||
|
@ -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.
|
||||
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>
|
||||
Specify an import route limit (a maximum number of routes
|
||||
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
|
||||
like appropriate commands. Disable is the default action if an
|
||||
action is not explicitly specified. Note that limits are reset
|
||||
during protocol reconfigure, reload or restart.
|
||||
Default: <cf/none/.
|
||||
during protocol reconfigure, reload or restart. Also note that
|
||||
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>
|
||||
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.
|
||||
<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
|
||||
number of networks, number of routes before and after filtering). If
|
||||
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
|
||||
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><descrip>
|
||||
@ -2460,13 +2483,13 @@ interface definitions, prefix definitions and DNS definitions:
|
||||
router. 0 means do not use as a default router. Default: 3 *
|
||||
<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
|
||||
interface. Otherwise, both global and local definitions are
|
||||
used. Could also be used to disable RDNSS for given interface
|
||||
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
|
||||
<cf/rdnss local/ option above. Default: no.
|
||||
</descrip>
|
||||
|
@ -1,6 +1,6 @@
|
||||
Summary: BIRD Internet Routing Daemon
|
||||
Name: bird
|
||||
Version: 1.3.8
|
||||
Version: 1.3.9
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Networking/Daemons
|
||||
|
@ -45,7 +45,7 @@ CF_DECLS
|
||||
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(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(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, AS, MAX, FLUSH)
|
||||
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
|
||||
@ -190,6 +190,7 @@ proto_item:
|
||||
| EXPORT imexport { this_proto->out_filter = $2; }
|
||||
| IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
|
||||
| EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
|
||||
| IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
|
||||
| TABLE rtable {
|
||||
if (!rt_match($2->addr_type, this_proto->protocol->tables))
|
||||
cf_error("Incompatible table class");
|
||||
@ -412,7 +413,7 @@ CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
|
||||
{ if_show_summary(); } ;
|
||||
|
||||
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); } ;
|
||||
|
||||
r_args:
|
||||
@ -458,6 +459,10 @@ r_args:
|
||||
$$ = $1;
|
||||
$$->primary_only = 1;
|
||||
}
|
||||
| r_args FILTERED {
|
||||
$$ = $1;
|
||||
$$->filtered = 1;
|
||||
}
|
||||
| r_args export_or_preexport SYM {
|
||||
struct proto_config *c = (struct proto_config *) $3->def;
|
||||
$$ = $1;
|
||||
|
20
nest/proto.c
20
nest/proto.c
@ -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->in_limit = nc->in_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,
|
||||
@ -720,8 +721,9 @@ proto_fell_down(struct proto *p)
|
||||
{
|
||||
DBG("Protocol %s down\n", p->name);
|
||||
|
||||
if (p->stats.imp_routes != 0)
|
||||
log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes);
|
||||
u32 all_routes = p->stats.imp_routes + p->stats.filt_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));
|
||||
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->in_limit = p->cf->in_limit;
|
||||
p->main_ahook->out_limit = p->cf->out_limit;
|
||||
p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
|
||||
proto_reset_limit(p->main_ahook->in_limit);
|
||||
proto_reset_limit(p->main_ahook->out_limit);
|
||||
}
|
||||
@ -1094,10 +1097,15 @@ proto_state_name(struct proto *p)
|
||||
}
|
||||
|
||||
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",
|
||||
s->imp_routes, s->exp_routes, s->pref_routes);
|
||||
if (in_keep_filtered)
|
||||
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, " Import updates: %10u %10u %10u %10u %10u",
|
||||
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:");
|
||||
|
||||
if (p->proto_state != PS_DOWN)
|
||||
proto_show_stats(&p->stats);
|
||||
proto_show_stats(&p->stats, p->cf->in_keep_filtered);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -92,6 +92,7 @@ struct proto_config {
|
||||
int class; /* SYM_PROTO or SYM_TEMPLATE */
|
||||
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
||||
unsigned preference, disabled; /* Generic parameters */
|
||||
int in_keep_filtered; /* Routes rejected in import filter are kept */
|
||||
u32 router_id; /* Protocol specific router ID */
|
||||
struct rtable_config *table; /* Table we're attached to */
|
||||
struct filter *in_filter, *out_filter; /* Attached filters */
|
||||
@ -107,7 +108,8 @@ struct proto_config {
|
||||
struct proto_stats {
|
||||
/* Import - from protocol to core */
|
||||
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_invalid; /* Number of route updates rejected as invalid */
|
||||
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_stats *stats; /* Per-table protocol statistics */
|
||||
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);
|
||||
|
10
nest/route.h
10
nest/route.h
@ -241,6 +241,14 @@ typedef struct rte {
|
||||
} rte;
|
||||
|
||||
#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 */
|
||||
#define RT_IPV4 1
|
||||
@ -308,7 +316,7 @@ struct rt_show_data {
|
||||
struct fib_iterator fit;
|
||||
struct proto *show_protocol;
|
||||
struct proto *export_protocol;
|
||||
int export_mode, primary_only;
|
||||
int export_mode, primary_only, filtered;
|
||||
struct config *running_on_config;
|
||||
int net_counter, rt_counter, show_counter;
|
||||
int stats, show_for;
|
||||
|
160
nest/rt-table.c
160
nest/rt-table.c
@ -72,7 +72,7 @@ net_route(rtable *tab, ip_addr a, int len)
|
||||
{
|
||||
a0 = ipa_and(a, ipa_mkmask(len));
|
||||
n = fib_find(&tab->fib, &a0, len);
|
||||
if (n && n->routes)
|
||||
if (n && rte_is_valid(n->routes))
|
||||
return n;
|
||||
len--;
|
||||
}
|
||||
@ -142,8 +142,11 @@ rte_better(rte *new, rte *old)
|
||||
{
|
||||
int (*better)(rte *, rte *);
|
||||
|
||||
if (!old)
|
||||
if (!rte_is_valid(old))
|
||||
return 1;
|
||||
if (!rte_is_valid(new))
|
||||
return 0;
|
||||
|
||||
if (new->pref > old->pref)
|
||||
return 1;
|
||||
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 *r;
|
||||
|
||||
/* Used to track whether we met old_changed position. If it is NULL
|
||||
it was the first and met it implicitly before current best route. */
|
||||
int old_meet = (old_changed && !before_old) ? 1 : 0;
|
||||
/* Used to track whether we met old_changed position. If before_old is NULL
|
||||
old_changed was the first and we met it implicitly before current best route. */
|
||||
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)
|
||||
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++;
|
||||
|
||||
/* 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))
|
||||
break;
|
||||
@ -431,7 +438,8 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
|
||||
if (feed)
|
||||
{
|
||||
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
|
||||
old_best = NULL;
|
||||
|
||||
@ -480,7 +488,7 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
|
||||
}
|
||||
|
||||
/* 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))
|
||||
goto found;
|
||||
@ -534,7 +542,14 @@ rt_notify_accepted(struct announce_hook *ah, net *net, rte *new_changed, rte *ol
|
||||
static void
|
||||
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)
|
||||
{
|
||||
@ -547,6 +562,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *befo
|
||||
rt_notify_hostcache(tab, net);
|
||||
}
|
||||
|
||||
struct announce_hook *a;
|
||||
WALK_LIST(a, tab->hooks)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); }
|
||||
|
||||
static void
|
||||
rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
|
||||
{
|
||||
@ -657,8 +675,13 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
|
||||
if (new && rte_same(old, new))
|
||||
{
|
||||
/* 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);
|
||||
#ifdef CONFIG_RIP
|
||||
/* 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;
|
||||
if (l && !old && new)
|
||||
{
|
||||
if (stats->imp_routes >= l->limit)
|
||||
proto_notify_limit(ah, l, stats->imp_routes);
|
||||
u32 all_routes = stats->imp_routes + stats->filt_routes;
|
||||
|
||||
if (all_routes >= l->limit)
|
||||
proto_notify_limit(ah, l, all_routes);
|
||||
|
||||
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++;
|
||||
else
|
||||
else if (old_ok)
|
||||
stats->imp_withdraws_accepted++;
|
||||
else
|
||||
stats->imp_withdraws_ignored++;
|
||||
|
||||
if (new)
|
||||
stats->imp_routes++;
|
||||
rte_is_filtered(new) ? stats->filt_routes++ : stats->imp_routes++;
|
||||
if (old)
|
||||
stats->imp_routes--;
|
||||
rte_is_filtered(old) ? stats->filt_routes-- : stats->imp_routes--;
|
||||
|
||||
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;
|
||||
|
||||
/* Log the route change */
|
||||
if (new)
|
||||
rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");
|
||||
|
||||
if (!new && (p->debug & D_ROUTES))
|
||||
if (p->debug & D_ROUTES)
|
||||
{
|
||||
if (old != old_best)
|
||||
rte_trace_in(D_ROUTES, p, old, "removed");
|
||||
else if (net->routes)
|
||||
rte_trace_in(D_ROUTES, p, old, "removed [replaced]");
|
||||
else
|
||||
rte_trace_in(D_ROUTES, p, old, "removed [sole]");
|
||||
if (new_ok)
|
||||
rte_trace(p, new, '>', new == net->routes ? "added [best]" : "added");
|
||||
else if (old_ok)
|
||||
{
|
||||
if (old != old_best)
|
||||
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 */
|
||||
@ -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))
|
||||
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 (p->rte_remove)
|
||||
p->rte_remove(net, old);
|
||||
rte_free_quick(old);
|
||||
}
|
||||
if (new)
|
||||
{
|
||||
if (p->rte_insert)
|
||||
p->rte_insert(net, new);
|
||||
}
|
||||
rte_free_quick(old);
|
||||
}
|
||||
|
||||
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++;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (filter == FILTER_REJECT)
|
||||
{
|
||||
stats->imp_updates_filtered++;
|
||||
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)
|
||||
tmpa = src->make_tmp_attrs(new, rte_update_pool);
|
||||
if (filter)
|
||||
else
|
||||
{
|
||||
ea_list *old_tmpa = tmpa;
|
||||
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
|
||||
if (fr > F_ACCEPT)
|
||||
if (src->make_tmp_attrs)
|
||||
tmpa = src->make_tmp_attrs(new, rte_update_pool);
|
||||
if (filter && (filter != FILTER_REJECT))
|
||||
{
|
||||
stats->imp_updates_filtered++;
|
||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||
goto drop;
|
||||
ea_list *old_tmpa = tmpa;
|
||||
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
|
||||
if (fr > F_ACCEPT)
|
||||
{
|
||||
stats->imp_updates_filtered++;
|
||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||
|
||||
if (! ah->in_keep_filtered)
|
||||
goto drop;
|
||||
|
||||
new->flags |= REF_FILTERED;
|
||||
}
|
||||
if (tmpa != old_tmpa && src->store_tmp_attrs)
|
||||
src->store_tmp_attrs(new, tmpa);
|
||||
}
|
||||
if (tmpa != old_tmpa && src->store_tmp_attrs)
|
||||
src->store_tmp_attrs(new, tmpa);
|
||||
}
|
||||
|
||||
if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
|
||||
new->attrs = rta_lookup(new->attrs);
|
||||
new->flags |= REF_COW;
|
||||
@ -1618,9 +1660,11 @@ again:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXXX perhaps we should change feed for RA_ACCEPTED to not use 'new' */
|
||||
|
||||
if ((p->accept_ra_types == RA_OPTIMAL) ||
|
||||
(p->accept_ra_types == RA_ACCEPTED))
|
||||
if (e)
|
||||
if (rte_is_valid(e))
|
||||
{
|
||||
if (p->core_state != FS_FEEDING)
|
||||
return 1; /* In the meantime, the protocol fell down. */
|
||||
@ -1629,7 +1673,7 @@ again:
|
||||
}
|
||||
|
||||
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)
|
||||
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);
|
||||
if (n)
|
||||
{
|
||||
rta *a = n->routes->attrs;
|
||||
rte *e = n->routes;
|
||||
rta *a = e->attrs;
|
||||
pxlen = n->n.pxlen;
|
||||
|
||||
if (a->hostentry)
|
||||
@ -1917,7 +1962,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
|
||||
}
|
||||
|
||||
he->src = rta_clone(a);
|
||||
he->igp_metric = rt_get_igp_metric(n->routes);
|
||||
he->igp_metric = rt_get_igp_metric(e);
|
||||
}
|
||||
|
||||
done:
|
||||
@ -2061,14 +2106,19 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||
int ok;
|
||||
|
||||
fn_print(prefix, sizeof(prefix), &n->n);
|
||||
if (n->routes)
|
||||
d->net_counter++;
|
||||
|
||||
for(e=n->routes; e; e=e->next)
|
||||
{
|
||||
if (rte_is_filtered(e) != d->filtered)
|
||||
continue;
|
||||
|
||||
struct ea_list *tmpa;
|
||||
struct proto *p0 = e->attrs->proto;
|
||||
struct proto *p1 = d->export_protocol;
|
||||
struct proto *p2 = d->show_protocol;
|
||||
|
||||
if (prefix[0])
|
||||
d->net_counter++;
|
||||
d->rt_counter++;
|
||||
ee = e;
|
||||
rte_update_lock(); /* We use the update buffer for filtering */
|
||||
|
@ -238,7 +238,7 @@ bgp_format_aggregator(eattr *a, byte *buf, int buflen UNUSED)
|
||||
as = get_u32(data);
|
||||
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
|
||||
@ -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 */
|
||||
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))
|
||||
{
|
||||
s->u.bgp.suppressed = 1;
|
||||
|
@ -1188,7 +1188,7 @@ bgp_show_proto_info(struct proto *P)
|
||||
cli_msg(-1006, " Source address: %I", p->source_addr);
|
||||
if (P->cf->in_limit)
|
||||
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",
|
||||
tm_remains(c->hold_timer), c->hold_time);
|
||||
cli_msg(-1006, " Keepalive timer: %d/%d",
|
||||
|
@ -973,6 +973,10 @@ ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
struct ifa *a;
|
||||
|
||||
WALK_LIST(iface, iface_list)
|
||||
{
|
||||
if (! (iface->flags & IF_UP))
|
||||
continue;
|
||||
|
||||
WALK_LIST(a, iface->addrs)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1008,6 +1013,10 @@ ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
struct ifa *a;
|
||||
|
||||
WALK_LIST(iface, iface_list)
|
||||
{
|
||||
if (! (iface->flags & IF_UP))
|
||||
continue;
|
||||
|
||||
WALK_LIST(a, iface->addrs)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -262,8 +262,15 @@ originate_rt2_lsa_body(struct ospf_area *oa, u16 *length)
|
||||
WALK_LIST(neigh, ifa->neigh_list)
|
||||
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++;
|
||||
}
|
||||
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 */
|
||||
if (net_lsa ||
|
||||
(ifa->type == OSPF_IT_VLINK) ||
|
||||
(ifa->addr->flags & IA_PEER) ||
|
||||
((ifa->addr->flags & IA_PEER) && ! ifa->cf->stub) ||
|
||||
configured_stubnet(oa, ifa->addr))
|
||||
continue;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define _BIRD_CONFIG_H_
|
||||
|
||||
/* BIRD version */
|
||||
#define BIRD_VERSION "1.3.8"
|
||||
#define BIRD_VERSION "1.3.9"
|
||||
|
||||
// XXXX temporary define
|
||||
#define IPV1 1
|
||||
|
@ -581,7 +581,7 @@ krt_flush_routes(struct krt_proto *p)
|
||||
{
|
||||
net *n = (net *) f;
|
||||
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 */
|
||||
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;
|
||||
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.
|
||||
Also, this does not work well if gw is changed in export filter */
|
||||
|
Loading…
Reference in New Issue
Block a user