Merge branch 'master' of ssh://git.nic.cz/bird
This commit is contained in:
commit
1f85226ecb
11 changed files with 132 additions and 72 deletions
|
@ -431,13 +431,19 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
|
||||||
<tag>export <m/filter/</tag> This is similar to the <cf>import</cf> keyword, except that it
|
<tag>export <m/filter/</tag> This is similar to the <cf>import</cf> keyword, except that it
|
||||||
works in the direction from the routing table to the protocol. Default: <cf/none/.
|
works in the direction from the routing table to the protocol. Default: <cf/none/.
|
||||||
|
|
||||||
<tag>import limit <m/number/ exceed warn | block | restart | disable</tag>
|
<tag>import limit <m/number/ [exceed warn | block | restart | disable]</tag>
|
||||||
Specify an import route limit and the action to be taken when
|
Specify an import route limit (a maximum number of routes
|
||||||
the limit is hit. Warn action just prints warning log
|
imported from the protocol) and optionally the action to be
|
||||||
message. Block action ignores new routes (and converts route
|
taken when the limit is hit. Warn action just prints warning
|
||||||
updates to withdraws) coming from the protocol. Restart and
|
log message. Block action ignores new routes coming from the
|
||||||
disable actions shut the protocol down like appropriate
|
protocol. Restart and disable actions shut the protocol down
|
||||||
commands. Default: <cf/none/.
|
like appropriate commands. Disable is the default action if an
|
||||||
|
action is not explicitly specified. Default: <cf/none/.
|
||||||
|
|
||||||
|
<tag>export limit <m/number/ [exceed warn | block | restart | disable]</tag>
|
||||||
|
Specify an export route limit, works similarly to
|
||||||
|
the <cf>import limit</cf> option, but for the routes exported
|
||||||
|
to the protocol. Default: <cf/none/.
|
||||||
|
|
||||||
<tag>description "<m/text/"</tag> This is an optional
|
<tag>description "<m/text/"</tag> This is an optional
|
||||||
description of the protocol. It is displayed as a part of the
|
description of the protocol. It is displayed as a part of the
|
||||||
|
|
|
@ -179,6 +179,7 @@ proto_item:
|
||||||
| IMPORT imexport { this_proto->in_filter = $2; }
|
| IMPORT imexport { this_proto->in_filter = $2; }
|
||||||
| 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; }
|
||||||
| TABLE rtable { this_proto->table = $2; }
|
| TABLE rtable { this_proto->table = $2; }
|
||||||
| ROUTER ID idval { this_proto->router_id = $3; }
|
| ROUTER ID idval { this_proto->router_id = $3; }
|
||||||
| DESCRIPTION TEXT { this_proto->dsc = $2; }
|
| DESCRIPTION TEXT { this_proto->dsc = $2; }
|
||||||
|
@ -192,17 +193,18 @@ imexport:
|
||||||
;
|
;
|
||||||
|
|
||||||
limit_action:
|
limit_action:
|
||||||
WARN { $$ = PLA_WARN; }
|
/* default */ { $$ = PLA_DISABLE; }
|
||||||
| BLOCK { $$ = PLA_BLOCK; }
|
| EXCEED WARN { $$ = PLA_WARN; }
|
||||||
| RESTART { $$ = PLA_RESTART; }
|
| EXCEED BLOCK { $$ = PLA_BLOCK; }
|
||||||
| DISABLE { $$ = PLA_DISABLE; }
|
| EXCEED RESTART { $$ = PLA_RESTART; }
|
||||||
|
| EXCEED DISABLE { $$ = PLA_DISABLE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
limit_spec:
|
limit_spec:
|
||||||
expr EXCEED limit_action {
|
expr limit_action {
|
||||||
struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
|
struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
|
||||||
l->limit = $1;
|
l->limit = $1;
|
||||||
l->action = $3;
|
l->action = $2;
|
||||||
$$ = l;
|
$$ = l;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
65
nest/proto.c
65
nest/proto.c
|
@ -406,13 +406,14 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
|
||||||
if (p->proto->multitable)
|
if (p->proto->multitable)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Update filters in the main announce hook */
|
/* Update filters and limits in the main announce hook
|
||||||
|
Note that this also resets limit state */
|
||||||
if (p->main_ahook)
|
if (p->main_ahook)
|
||||||
{
|
{
|
||||||
p->main_ahook->in_filter = nc->in_filter;
|
p->main_ahook->in_filter = nc->in_filter;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update routes when filters changed. If the protocol in not UP,
|
/* Update routes when filters changed. If the protocol in not UP,
|
||||||
|
@ -774,9 +775,16 @@ proto_schedule_feed(struct proto *p, int initial)
|
||||||
p->core_state = FS_FEEDING;
|
p->core_state = FS_FEEDING;
|
||||||
p->refeeding = !initial;
|
p->refeeding = !initial;
|
||||||
|
|
||||||
/* Hack: reset exp_routes during refeed, and do not decrease it later */
|
/* FIXME: This should be changed for better support of multitable protos */
|
||||||
if (!initial)
|
if (!initial)
|
||||||
|
{
|
||||||
|
struct announce_hook *ah;
|
||||||
|
for (ah = p->ahooks; ah; ah = ah->next)
|
||||||
|
proto_reset_limit(ah->out_limit);
|
||||||
|
|
||||||
|
/* Hack: reset exp_routes during refeed, and do not decrease it later */
|
||||||
p->stats.exp_routes = 0;
|
p->stats.exp_routes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Connect protocol to routing table */
|
/* Connect protocol to routing table */
|
||||||
if (initial && !p->proto->multitable)
|
if (initial && !p->proto->multitable)
|
||||||
|
@ -785,7 +793,9 @@ proto_schedule_feed(struct proto *p, int initial)
|
||||||
p->main_ahook->in_filter = p->cf->in_filter;
|
p->main_ahook->in_filter = p->cf->in_filter;
|
||||||
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;
|
||||||
|
proto_reset_limit(p->main_ahook->in_limit);
|
||||||
|
proto_reset_limit(p->main_ahook->out_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_relink(p);
|
proto_relink(p);
|
||||||
|
@ -870,6 +880,8 @@ proto_schedule_flush(struct proto *p)
|
||||||
proto_schedule_flush_loop();
|
proto_schedule_flush_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Temporary hack to propagate restart to BGP */
|
||||||
|
int proto_restart;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
proto_shutdown_loop(struct timer *t UNUSED)
|
proto_shutdown_loop(struct timer *t UNUSED)
|
||||||
|
@ -879,11 +891,11 @@ proto_shutdown_loop(struct timer *t UNUSED)
|
||||||
WALK_LIST_DELSAFE(p, p_next, active_proto_list)
|
WALK_LIST_DELSAFE(p, p_next, active_proto_list)
|
||||||
if (p->down_sched)
|
if (p->down_sched)
|
||||||
{
|
{
|
||||||
int restart = (p->down_sched == PDS_RESTART);
|
proto_restart = (p->down_sched == PDS_RESTART);
|
||||||
|
|
||||||
p->disabled = 1;
|
p->disabled = 1;
|
||||||
proto_rethink_goal(p);
|
proto_rethink_goal(p);
|
||||||
if (restart)
|
if (proto_restart)
|
||||||
{
|
{
|
||||||
p->disabled = 0;
|
p->disabled = 0;
|
||||||
proto_rethink_goal(p);
|
proto_rethink_goal(p);
|
||||||
|
@ -953,43 +965,43 @@ proto_limit_name(struct proto_limit *l)
|
||||||
* proto_notify_limit: notify about limit hit and take appropriate action
|
* proto_notify_limit: notify about limit hit and take appropriate action
|
||||||
* @ah: announce hook
|
* @ah: announce hook
|
||||||
* @l: limit being hit
|
* @l: limit being hit
|
||||||
|
* @rt_count: the number of routes
|
||||||
*
|
*
|
||||||
* The function is called by the route processing core when limit @l
|
* The function is called by the route processing core when limit @l
|
||||||
* is breached. It activates the limit and tooks appropriate action
|
* is breached. It activates the limit and tooks appropriate action
|
||||||
* according to @l->action. It also says what should be done with the
|
* according to @l->action.
|
||||||
* route that breached the limit.
|
|
||||||
*
|
|
||||||
* Returns 1 if the route should be freed, 0 otherwise.
|
|
||||||
*/
|
*/
|
||||||
int
|
void
|
||||||
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l)
|
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
|
||||||
{
|
{
|
||||||
struct proto *p = ah->proto;
|
struct proto *p = ah->proto;
|
||||||
int dir = (ah->in_limit == l);
|
int dir = (ah->in_limit == l);
|
||||||
|
|
||||||
if (l->active)
|
if (l->state == PLS_BLOCKED)
|
||||||
return (l->action != PLA_WARN);
|
return;
|
||||||
|
|
||||||
l->active = 1;
|
/* For warning action, we want the log message every time we hit the limit */
|
||||||
|
if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
|
||||||
log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
|
log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
|
||||||
p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
|
p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
|
||||||
|
|
||||||
switch (l->action)
|
switch (l->action)
|
||||||
{
|
{
|
||||||
case PLA_WARN:
|
case PLA_WARN:
|
||||||
return 0;
|
l->state = PLS_ACTIVE;
|
||||||
|
break;
|
||||||
|
|
||||||
case PLA_BLOCK:
|
case PLA_BLOCK:
|
||||||
return 1;
|
l->state = PLS_BLOCKED;
|
||||||
|
break;
|
||||||
|
|
||||||
case PLA_RESTART:
|
case PLA_RESTART:
|
||||||
case PLA_DISABLE:
|
case PLA_DISABLE:
|
||||||
|
l->state = PLS_BLOCKED;
|
||||||
proto_schedule_down(p, l->action == PLA_RESTART,
|
proto_schedule_down(p, l->action == PLA_RESTART,
|
||||||
dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
|
dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
|
||||||
return 1;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1101,9 +1113,11 @@ proto_show_stats(struct proto_stats *s)
|
||||||
void
|
void
|
||||||
proto_show_limit(struct proto_limit *l, const char *dsc)
|
proto_show_limit(struct proto_limit *l, const char *dsc)
|
||||||
{
|
{
|
||||||
if (l)
|
if (!l)
|
||||||
cli_msg(-1006, " %16s%d, action: %s%s", dsc, l->limit,
|
return;
|
||||||
proto_limit_name(l), l->active ? " [HIT]" : "");
|
|
||||||
|
cli_msg(-1006, " %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
|
||||||
|
cli_msg(-1006, " Action: %s", proto_limit_name(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1115,6 +1129,7 @@ proto_show_basic_info(struct proto *p)
|
||||||
cli_msg(-1006, " Output filter: %s", filter_name(p->cf->out_filter));
|
cli_msg(-1006, " Output filter: %s", filter_name(p->cf->out_filter));
|
||||||
|
|
||||||
proto_show_limit(p->cf->in_limit, "Import limit:");
|
proto_show_limit(p->cf->in_limit, "Import 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);
|
||||||
|
@ -1233,8 +1248,8 @@ proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
|
||||||
* Should be done before reload_routes() hook?
|
* Should be done before reload_routes() hook?
|
||||||
* Perhaps, but these hooks work asynchronously.
|
* Perhaps, but these hooks work asynchronously.
|
||||||
*/
|
*/
|
||||||
if (!p->proto->multitable && p->main_ahook->in_limit)
|
if (!p->proto->multitable)
|
||||||
p->main_ahook->in_limit->active = 0;
|
proto_reset_limit(p->main_ahook->in_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* re-exporting routes */
|
/* re-exporting routes */
|
||||||
|
|
|
@ -95,7 +95,7 @@ struct proto_config {
|
||||||
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 */
|
||||||
struct proto_limit *in_limit; /* Limit for importing routes from protocol */
|
struct proto_limit *in_limit; /* Limit for importing routes from protocol */
|
||||||
// struct proto_limit *out_limit; /* Limit for exporting routes to protocol */
|
struct proto_limit *out_limit; /* Limit for exporting routes to protocol */
|
||||||
|
|
||||||
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
|
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
|
||||||
|
|
||||||
|
@ -375,13 +375,24 @@ extern struct proto_config *cf_dev_proto;
|
||||||
#define PLA_RESTART 4 /* Force protocol restart */
|
#define PLA_RESTART 4 /* Force protocol restart */
|
||||||
#define PLA_DISABLE 5 /* Shutdown and disable protocol */
|
#define PLA_DISABLE 5 /* Shutdown and disable protocol */
|
||||||
|
|
||||||
|
#define PLS_INITIAL 0 /* Initial limit state after protocol start */
|
||||||
|
#define PLS_ACTIVE 1 /* Limit was hit */
|
||||||
|
#define PLS_BLOCKED 2 /* Limit is active and blocking new routes */
|
||||||
|
|
||||||
struct proto_limit {
|
struct proto_limit {
|
||||||
u32 limit; /* Maximum number of prefixes */
|
u32 limit; /* Maximum number of prefixes */
|
||||||
byte action; /* Action to take (PLA_*) */
|
byte action; /* Action to take (PLA_*) */
|
||||||
byte active; /* Limit is active */
|
byte state; /* State of limit (PLS_*) */
|
||||||
};
|
};
|
||||||
|
|
||||||
int proto_notify_limit(struct announce_hook *ah, struct proto_limit *l);
|
void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count);
|
||||||
|
|
||||||
|
static inline void proto_reset_limit(struct proto_limit *l)
|
||||||
|
{
|
||||||
|
if (l)
|
||||||
|
l->state = PLS_INITIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Route Announcement Hook
|
* Route Announcement Hook
|
||||||
|
@ -394,7 +405,7 @@ struct announce_hook {
|
||||||
struct filter *in_filter; /* Input filter */
|
struct filter *in_filter; /* Input filter */
|
||||||
struct filter *out_filter; /* Output filter */
|
struct filter *out_filter; /* Output filter */
|
||||||
struct proto_limit *in_limit; /* Input limit */
|
struct proto_limit *in_limit; /* Input limit */
|
||||||
// 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 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -273,6 +273,23 @@ do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, r
|
||||||
if (!new && !old)
|
if (!new && !old)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
struct proto_limit *l = ah->out_limit;
|
||||||
|
if (l && new && (!old || refeed))
|
||||||
|
{
|
||||||
|
if (stats->exp_routes >= l->limit)
|
||||||
|
proto_notify_limit(ah, l, stats->exp_routes);
|
||||||
|
|
||||||
|
if (l->state == PLS_BLOCKED)
|
||||||
|
{
|
||||||
|
/* Exported route counter ignores whether the route was
|
||||||
|
blocked by limit, to be consistent when limits change */
|
||||||
|
stats->exp_routes++;
|
||||||
|
stats->exp_updates_rejected++;
|
||||||
|
rte_trace_out(D_FILTERS, p, new, "rejected [limit]");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
stats->exp_updates_accepted++;
|
stats->exp_updates_accepted++;
|
||||||
else
|
else
|
||||||
|
@ -307,6 +324,8 @@ do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, r
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
|
p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
|
||||||
|
|
||||||
|
done:
|
||||||
if (new && new != new0) /* Discard temporary rte's */
|
if (new && new != new0) /* Discard temporary rte's */
|
||||||
rte_free(new);
|
rte_free(new);
|
||||||
if (old && old != old0)
|
if (old && old != old0)
|
||||||
|
@ -485,13 +504,19 @@ 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 && (stats->imp_routes >= l->limit) && proto_notify_limit(ah, l))
|
if (l && !old && new)
|
||||||
|
{
|
||||||
|
if (stats->imp_routes >= l->limit)
|
||||||
|
proto_notify_limit(ah, l, stats->imp_routes);
|
||||||
|
|
||||||
|
if (l->state == PLS_BLOCKED)
|
||||||
{
|
{
|
||||||
stats->imp_updates_ignored++;
|
stats->imp_updates_ignored++;
|
||||||
rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
|
rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
|
||||||
rte_free_quick(new);
|
rte_free_quick(new);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
stats->imp_updates_accepted++;
|
stats->imp_updates_accepted++;
|
||||||
|
|
|
@ -848,6 +848,8 @@ bgp_start(struct proto *P)
|
||||||
return PS_START;
|
return PS_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int proto_restart;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bgp_shutdown(struct proto *P)
|
bgp_shutdown(struct proto *P)
|
||||||
{
|
{
|
||||||
|
@ -877,10 +879,16 @@ bgp_shutdown(struct proto *P)
|
||||||
|
|
||||||
case PDC_IN_LIMIT_HIT:
|
case PDC_IN_LIMIT_HIT:
|
||||||
subcode = 1; // Errcode 6, 1 - max number of prefixes reached
|
subcode = 1; // Errcode 6, 1 - max number of prefixes reached
|
||||||
|
/* log message for compatibility */
|
||||||
log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
|
log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name);
|
||||||
|
goto limit;
|
||||||
|
|
||||||
|
case PDC_OUT_LIMIT_HIT:
|
||||||
|
subcode = proto_restart ? 4 : 2; // Administrative reset or shutdown
|
||||||
|
|
||||||
|
limit:
|
||||||
bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
|
bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED);
|
||||||
if (P->cf->in_limit->action == PLA_RESTART)
|
if (proto_restart)
|
||||||
bgp_update_startup_delay(p);
|
bgp_update_startup_delay(p);
|
||||||
else
|
else
|
||||||
p->startup_delay = 0;
|
p->startup_delay = 0;
|
||||||
|
@ -1165,9 +1173,9 @@ bgp_show_proto_info(struct proto *P)
|
||||||
p->rs_client ? " route-server" : "",
|
p->rs_client ? " route-server" : "",
|
||||||
p->as4_session ? " AS4" : "");
|
p->as4_session ? " AS4" : "");
|
||||||
cli_msg(-1006, " Source address: %I", p->source_addr);
|
cli_msg(-1006, " Source address: %I", p->source_addr);
|
||||||
if (p->cf->route_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->route_limit);
|
p->p.stats.imp_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",
|
||||||
|
|
|
@ -40,7 +40,6 @@ struct bgp_config {
|
||||||
int rr_client; /* Whether neighbor is RR client of me */
|
int rr_client; /* Whether neighbor is RR client of me */
|
||||||
int rs_client; /* Whether neighbor is RS client of me */
|
int rs_client; /* Whether neighbor is RS client of me */
|
||||||
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
|
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
|
||||||
u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */
|
|
||||||
int passive; /* Do not initiate outgoing connection */
|
int passive; /* Do not initiate outgoing connection */
|
||||||
int interpret_communities; /* Hardwired handling of well-known communities */
|
int interpret_communities; /* Hardwired handling of well-known communities */
|
||||||
unsigned connect_retry_time;
|
unsigned connect_retry_time;
|
||||||
|
|
|
@ -36,7 +36,6 @@ pipe_proto:
|
||||||
cf_error("Routing table name expected");
|
cf_error("Routing table name expected");
|
||||||
PIPE_CFG->peer = $4->def;
|
PIPE_CFG->peer = $4->def;
|
||||||
}
|
}
|
||||||
| pipe_proto EXPORT LIMIT limit_spec ';' { PIPE_CFG->out_limit = $4; }
|
|
||||||
| pipe_proto MODE OPAQUE ';' { PIPE_CFG->mode = PIPE_OPAQUE; }
|
| pipe_proto MODE OPAQUE ';' { PIPE_CFG->mode = PIPE_OPAQUE; }
|
||||||
| pipe_proto MODE TRANSPARENT ';' { PIPE_CFG->mode = PIPE_TRANSPARENT; }
|
| pipe_proto MODE TRANSPARENT ';' { PIPE_CFG->mode = PIPE_TRANSPARENT; }
|
||||||
;
|
;
|
||||||
|
|
|
@ -127,10 +127,8 @@ pipe_reload_routes(struct proto *P)
|
||||||
*/
|
*/
|
||||||
proto_request_feeding(P);
|
proto_request_feeding(P);
|
||||||
|
|
||||||
if (P->main_ahook->in_limit)
|
proto_reset_limit(P->main_ahook->in_limit);
|
||||||
P->main_ahook->in_limit->active = 0;
|
proto_reset_limit(p->peer_ahook->in_limit);
|
||||||
if (p->peer_ahook->in_limit)
|
|
||||||
p->peer_ahook->in_limit->active = 0;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -168,10 +166,12 @@ pipe_start(struct proto *P)
|
||||||
P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
|
P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
|
||||||
P->main_ahook->out_filter = cf->c.out_filter;
|
P->main_ahook->out_filter = cf->c.out_filter;
|
||||||
P->main_ahook->in_limit = cf->c.in_limit;
|
P->main_ahook->in_limit = cf->c.in_limit;
|
||||||
|
proto_reset_limit(P->main_ahook->in_limit);
|
||||||
|
|
||||||
p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
|
p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
|
||||||
p->peer_ahook->out_filter = cf->c.in_filter;
|
p->peer_ahook->out_filter = cf->c.in_filter;
|
||||||
p->peer_ahook->in_limit = cf->out_limit;
|
p->peer_ahook->in_limit = cf->c.out_limit;
|
||||||
|
proto_reset_limit(p->peer_ahook->in_limit);
|
||||||
|
|
||||||
return PS_UP;
|
return PS_UP;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
|
||||||
if (p->peer_ahook)
|
if (p->peer_ahook)
|
||||||
{
|
{
|
||||||
p->peer_ahook->out_filter = new->in_filter;
|
p->peer_ahook->out_filter = new->in_filter;
|
||||||
p->peer_ahook->in_limit = nc->out_limit;
|
p->peer_ahook->in_limit = new->out_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
|
if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
|
||||||
|
@ -311,7 +311,7 @@ pipe_show_proto_info(struct proto *P)
|
||||||
cli_msg(-1006, " Output filter: %s", filter_name(cf->c.out_filter));
|
cli_msg(-1006, " Output filter: %s", filter_name(cf->c.out_filter));
|
||||||
|
|
||||||
proto_show_limit(cf->c.in_limit, "Import limit:");
|
proto_show_limit(cf->c.in_limit, "Import limit:");
|
||||||
proto_show_limit(cf->out_limit, "Export limit:");
|
proto_show_limit(cf->c.out_limit, "Export limit:");
|
||||||
|
|
||||||
if (P->proto_state != PS_DOWN)
|
if (P->proto_state != PS_DOWN)
|
||||||
pipe_show_stats(p);
|
pipe_show_stats(p);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
struct pipe_config {
|
struct pipe_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
struct rtable_config *peer; /* Table we're connected to */
|
struct rtable_config *peer; /* Table we're connected to */
|
||||||
struct proto_limit *out_limit; /* Export route limit */
|
|
||||||
int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
|
int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -588,9 +588,9 @@ krt_capable(rte *e)
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_ROUTER:
|
case RTD_ROUTER:
|
||||||
if (ipa_has_link_scope(a->gw) && (a->iface == NULL))
|
|
||||||
return 0;
|
|
||||||
case RTD_DEVICE:
|
case RTD_DEVICE:
|
||||||
|
if (a->iface == NULL)
|
||||||
|
return 0;
|
||||||
case RTD_BLACKHOLE:
|
case RTD_BLACKHOLE:
|
||||||
case RTD_UNREACHABLE:
|
case RTD_UNREACHABLE:
|
||||||
case RTD_PROHIBIT:
|
case RTD_PROHIBIT:
|
||||||
|
@ -653,20 +653,16 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||||
if (ea = ea_find(eattrs, EA_KRT_REALM))
|
if (ea = ea_find(eattrs, EA_KRT_REALM))
|
||||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
|
||||||
|
|
||||||
|
/* a->iface != NULL checked in krt_capable() for router and device routes */
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_ROUTER:
|
case RTD_ROUTER:
|
||||||
r.r.rtm_type = RTN_UNICAST;
|
r.r.rtm_type = RTN_UNICAST;
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
|
|
||||||
|
|
||||||
/* a->iface != NULL checked in krt_capable() */
|
|
||||||
if (ipa_has_link_scope(a->gw))
|
|
||||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
||||||
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
|
||||||
break;
|
break;
|
||||||
case RTD_DEVICE:
|
case RTD_DEVICE:
|
||||||
if (!a->iface)
|
|
||||||
return -1;
|
|
||||||
r.r.rtm_type = RTN_UNICAST;
|
r.r.rtm_type = RTN_UNICAST;
|
||||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue