Merge remote-tracking branch 'origin/master' into soft-int
This commit is contained in:
commit
78342404ff
35 changed files with 281 additions and 102 deletions
14
NEWS
14
NEWS
|
@ -1,3 +1,17 @@
|
|||
Version 1.4.5 (2014-10-06)
|
||||
o New 'show route noexport' command option.
|
||||
o Port option for BGP sessions.
|
||||
o Better constant handling in set literals.
|
||||
o Better rate filtering of log messages.
|
||||
o Several minor bugfixes.
|
||||
|
||||
Version 1.4.4 (2014-07-09)
|
||||
o Extended OSPF multipath support.
|
||||
o Default router preference for RAdv.
|
||||
o Significant changes in socket layer.
|
||||
o Important bugfix in BGP.
|
||||
o Several minor bugfixes.
|
||||
|
||||
Version 1.4.3 (2014-04-14)
|
||||
o Important bugfix in IPv6 BGP.
|
||||
|
||||
|
|
|
@ -646,7 +646,7 @@ cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos)
|
|||
char *
|
||||
cf_symbol_class_name(struct symbol *sym)
|
||||
{
|
||||
if ((sym->class & 0xff00) == SYM_CONSTANT)
|
||||
if (cf_symbol_is_constant(sym))
|
||||
return "constant";
|
||||
|
||||
switch (sym->class)
|
||||
|
|
|
@ -149,6 +149,10 @@ void cf_pop_scope(void);
|
|||
struct symbol *cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos);
|
||||
char *cf_symbol_class_name(struct symbol *sym);
|
||||
|
||||
static inline int cf_symbol_is_constant(struct symbol *sym)
|
||||
{ return (sym->class & 0xff00) == SYM_CONSTANT; }
|
||||
|
||||
|
||||
/* Parser */
|
||||
|
||||
int cf_parse(void);
|
||||
|
|
|
@ -72,7 +72,7 @@ CF_DECLS
|
|||
%token <t> TEXT
|
||||
%type <iface> ipa_scope
|
||||
|
||||
%type <i> expr bool pxlen
|
||||
%type <i> expr bool pxlen ipa_port
|
||||
%type <i32> expr_us
|
||||
%type <time> datetime
|
||||
%type <a> ipa
|
||||
|
@ -88,7 +88,7 @@ CF_DECLS
|
|||
%left '!'
|
||||
%nonassoc '.'
|
||||
|
||||
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US)
|
||||
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
|
@ -161,6 +161,14 @@ ipa_scope:
|
|||
| '%' SYM { $$ = if_get_by_name($2->name); }
|
||||
;
|
||||
|
||||
ipa_port:
|
||||
/* empty */ { $$ = 0; }
|
||||
| PORT expr {
|
||||
if (($2 < 1) || ($2 > 65535)) cf_error("Invalid port number");
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
prefix:
|
||||
ipa pxlen {
|
||||
if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix");
|
||||
|
|
|
@ -318,7 +318,7 @@ protocol rip {
|
|||
<p><descrip>
|
||||
<tag>include "<m/filename/"</tag>
|
||||
This statement causes inclusion of a new file. <m/Filename/ could also
|
||||
be a wildcard. The maximal depth is 5. Note that this statement could be
|
||||
be a wildcard. The maximal depth is 8. Note that this statement could be
|
||||
used anywhere in the config file, not just as a top-level option.
|
||||
|
||||
<tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
|
||||
|
@ -735,7 +735,7 @@ This argument can be omitted if there exists only a single instance.
|
|||
Show the list of symbols defined in the configuration (names of
|
||||
protocols, routing tables etc.).
|
||||
|
||||
<tag>show route [[for] <m/prefix/|<m/IP/] [table <m/sym/] [filter <m/f/|where <m/c/] [(export|preexport) <m/p/] [protocol <m/p/] [<m/options/]</tag>
|
||||
<tag>show route [[for] <m/prefix/|<m/IP/] [table <m/sym/] [filter <m/f/|where <m/c/] [(export|preexport|noexport) <m/p/] [protocol <m/p/] [<m/options/]</tag>
|
||||
Show contents of a routing table (by default of the main one or the
|
||||
table attached to a respective protocol), that is routes, their metrics
|
||||
and (in case the <cf/all/ switch is given) all their attributes.
|
||||
|
@ -750,9 +750,14 @@ This argument can be omitted if there exists only a single instance.
|
|||
<p>You can also ask for printing only routes processed and accepted by
|
||||
a given filter (<cf>filter <m/name/</cf> or <cf>filter { <m/filter/ }
|
||||
</cf> or matching a given condition (<cf>where <m/condition/</cf>).
|
||||
The <cf/export/ and <cf/preexport/ switches ask for printing of entries
|
||||
that are exported to the specified protocol. With <cf/preexport/, the
|
||||
export filter of the protocol is skipped.
|
||||
|
||||
The <cf/export/, <cf/preexport/ and <cf/noexport/ switches ask for
|
||||
printing of routes that are exported to the specified protocol.
|
||||
With <cf/preexport/, the export filter of the protocol is skipped.
|
||||
With <cf/noexport/, routes rejected by the export filter are printed
|
||||
instead. Note that routes not exported to the protocol for other reasons
|
||||
(e.g. secondary routes or routes imported from that protocol) are not
|
||||
printed even with <cf/noexport/.
|
||||
|
||||
<p>You can also select just routes added by a specific protocol.
|
||||
<cf>protocol <m/p/</cf>.
|
||||
|
@ -1004,7 +1009,6 @@ foot).
|
|||
So <cf>1.2.0.0/16.pxlen = 16</cf> is true.
|
||||
|
||||
<tag/ec/
|
||||
|
||||
This is a specialized type used to represent BGP extended community
|
||||
values. It is essentially a 64bit value, literals of this type are
|
||||
usually written as <cf>(<m/kind/, <m/key/, <m/value/)</cf>, where
|
||||
|
@ -1616,7 +1620,7 @@ using the following configuration parameters:
|
|||
address, equivalent to the <cf/source address/ option (see below). This
|
||||
parameter is mandatory.
|
||||
|
||||
<tag>neighbor <m/ip/ as <m/number/</tag>
|
||||
<tag>neighbor <m/ip/ [port <m/number/] as <m/number/</tag>
|
||||
Define neighboring router this instance will be talking to and what AS
|
||||
it's located in. In case the neighbor is in the same AS as we are, we
|
||||
automatically switch to iBGP. This parameter is mandatory.
|
||||
|
@ -3036,6 +3040,10 @@ definitions, prefix definitions and DNS definitions:
|
|||
as a default router. For <cf/sensitive/ option, see <ref id="dsc-trigger" name="trigger">.
|
||||
Default: 3 * <cf/max ra interval/, <cf/sensitive/ yes.
|
||||
|
||||
<tag>default preference low|medium|high</tag>
|
||||
This option specifies the Default Router Preference value to advertise
|
||||
to hosts. Default: medium.
|
||||
|
||||
<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
|
||||
|
|
|
@ -25,6 +25,23 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
|
|||
* to the last item in a list (right ptr). For convenience, even items
|
||||
* are handled as one-item lists. Lists are merged by f_merge_items().
|
||||
*/
|
||||
static int
|
||||
f_valid_set_type(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T_INT:
|
||||
case T_PAIR:
|
||||
case T_QUAD:
|
||||
case T_ENUM:
|
||||
case T_IP:
|
||||
case T_EC:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct f_tree *
|
||||
f_new_item(struct f_val from, struct f_val to)
|
||||
|
@ -473,10 +490,19 @@ fipa:
|
|||
*/
|
||||
|
||||
set_atom:
|
||||
expr { $$.type = T_INT; $$.val.i = $1; }
|
||||
NUM { $$.type = T_INT; $$.val.i = $1; }
|
||||
| RTRID { $$.type = T_QUAD; $$.val.i = $1; }
|
||||
| fipa { $$ = $1; }
|
||||
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
||||
| '(' term ')' {
|
||||
$$ = f_eval($2, cfg_mem);
|
||||
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
|
||||
}
|
||||
| SYM {
|
||||
if (!cf_symbol_is_constant($1)) cf_error("%s: constant expected", $1->name);
|
||||
if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
|
||||
$$ = *(struct f_val *)($1->def);
|
||||
}
|
||||
;
|
||||
|
||||
switch_atom:
|
||||
|
|
|
@ -493,7 +493,7 @@ f_rta_cow(void)
|
|||
}
|
||||
}
|
||||
|
||||
static struct rate_limit rl_runtime_err;
|
||||
static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
#define runtime(x) do { \
|
||||
log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
|
||||
|
@ -1492,7 +1492,7 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
|||
|
||||
|
||||
if (res.type != T_RETURN) {
|
||||
log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
|
||||
log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
|
||||
return F_ERROR;
|
||||
}
|
||||
DBG( "done (%u)\n", res.val.i );
|
||||
|
|
|
@ -13,6 +13,9 @@ define '1a-a1' = (20+10);
|
|||
define one = 1;
|
||||
define ten = 10;
|
||||
|
||||
define p23 = (2, 3);
|
||||
define ip1222 = 1.2.2.2;
|
||||
|
||||
function onef(int a)
|
||||
{
|
||||
return 1;
|
||||
|
@ -78,7 +81,7 @@ function test_roa()
|
|||
" ", roa_check(rl, 10.130.130.0/24, 3000) = ROA_VALID;
|
||||
}
|
||||
|
||||
function paths()
|
||||
function path_test()
|
||||
bgpmask pm1;
|
||||
bgpmask pm2;
|
||||
bgppath p2;
|
||||
|
@ -98,7 +101,7 @@ eclist el2;
|
|||
print "Should be true: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 3 ~ p2, " ", p2 ~ [2, 10..20], " ", p2 ~ [4, 10..20];
|
||||
print "4 = ", p2.len;
|
||||
p2 = prepend( p2, 5 );
|
||||
print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, 10..20],;
|
||||
print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)];
|
||||
print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /;
|
||||
print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =];
|
||||
print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4);
|
||||
|
@ -124,7 +127,7 @@ eclist el2;
|
|||
print "Should be always true: ", l ~ [(*,*)];
|
||||
l = add( l, (2,one+2) );
|
||||
print "Community list (1,2) (2,3) ", l;
|
||||
print "Should be true: ", (2,3) ~ l, " ", l ~ [(1,*)], " ", l ~ [(2,3)]," ", l ~ [(2,2..3)], " ", l ~ [(1,1..2)], " ", l ~ [(1,1)..(1,2)];
|
||||
print "Should be true: ", (2,3) ~ l, " ", l ~ [(1,*)], " ", l ~ [p23]," ", l ~ [(2,2..3)], " ", l ~ [(1,1..2)], " ", l ~ [(1,1)..(1,2)];
|
||||
l = add( l, (2,5) );
|
||||
l = add( l, (5,one) );
|
||||
l = add( l, (6,one) );
|
||||
|
@ -361,7 +364,7 @@ string st;
|
|||
if ( b = true ) then print "Testing bool comparison b = true: ", b;
|
||||
else { print "*** FAIL: TRUE test failed" ; quitbird; }
|
||||
|
||||
ips = [ 1.1.1.0 .. 1.1.1.255, 1.2.2.2];
|
||||
ips = [ 1.1.1.0 .. 1.1.1.255, ip1222];
|
||||
print "Testing IP sets: ";
|
||||
print ips;
|
||||
print " must be true: ", 1.1.1.0 ~ ips, ",", 1.1.1.100 ~ ips, ",", 1.2.2.2 ~ ips;
|
||||
|
@ -389,7 +392,7 @@ string st;
|
|||
i = fifteen();
|
||||
print "Testing function calls: 15 = ", i;
|
||||
|
||||
paths();
|
||||
path_test();
|
||||
|
||||
print "1.2.3.4 = ", onetwo;
|
||||
|
||||
|
|
2
lib/Doc
2
lib/Doc
|
@ -1,7 +1,7 @@
|
|||
H Library functions
|
||||
S ip.c ipv4.c ipv6.c
|
||||
S lists.c
|
||||
S checksum.c bitops.c patmatch.c printf.c xmalloc.c
|
||||
S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c
|
||||
D resource.sgml
|
||||
S resource.c
|
||||
S mempool.c
|
||||
|
|
|
@ -19,6 +19,7 @@ resource.c
|
|||
resource.h
|
||||
slab.c
|
||||
socket.h
|
||||
tbf.c
|
||||
unaligned.h
|
||||
xmalloc.c
|
||||
printf.c
|
||||
|
|
|
@ -74,6 +74,38 @@ typedef s64 btime;
|
|||
#endif
|
||||
|
||||
|
||||
/* Rate limiting */
|
||||
|
||||
struct tbf {
|
||||
bird_clock_t timestamp; /* Last update */
|
||||
u16 count; /* Available tokens */
|
||||
u16 burst; /* Max number of tokens */
|
||||
u16 rate; /* Rate of replenishment */
|
||||
u16 mark; /* Whether last op was limited */
|
||||
};
|
||||
|
||||
/* Default TBF values for rate limiting log messages */
|
||||
#define TBF_DEFAULT_LOG_LIMITS { .rate = 1, .burst = 5 }
|
||||
|
||||
void tbf_update(struct tbf *f);
|
||||
|
||||
static inline int
|
||||
tbf_limit(struct tbf *f)
|
||||
{
|
||||
tbf_update(f);
|
||||
|
||||
if (!f->count)
|
||||
{
|
||||
f->mark = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
f->count--;
|
||||
f->mark = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Logging and dying */
|
||||
|
||||
typedef struct buffer {
|
||||
|
@ -94,16 +126,10 @@ typedef struct buffer {
|
|||
|
||||
#define LOG_BUFFER_SIZE 1024
|
||||
|
||||
|
||||
struct rate_limit {
|
||||
bird_clock_t timestamp;
|
||||
int count;
|
||||
};
|
||||
|
||||
#define log log_msg
|
||||
void log_commit(int class, buffer *buf);
|
||||
void log_msg(char *msg, ...);
|
||||
void log_rl(struct rate_limit *rl, char *msg, ...);
|
||||
void log_rl(struct tbf *rl, char *msg, ...);
|
||||
void die(char *msg, ...) NORET;
|
||||
void bug(char *msg, ...) NORET;
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ static size_t
|
|||
slab_memsize(resource *r)
|
||||
{
|
||||
slab *s = (slab *) r;
|
||||
int cnt = 0;
|
||||
size_t cnt = 0;
|
||||
struct sl_obj *o;
|
||||
|
||||
WALK_LIST(o, s->objs)
|
||||
|
@ -346,7 +346,7 @@ static size_t
|
|||
slab_memsize(resource *r)
|
||||
{
|
||||
slab *s = (slab *) r;
|
||||
int heads = 0;
|
||||
size_t heads = 0;
|
||||
struct sl_head *h;
|
||||
|
||||
WALK_LIST(h, s->empty_heads)
|
||||
|
|
29
lib/tbf.c
Normal file
29
lib/tbf.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* BIRD Library -- Token Bucket Filter
|
||||
*
|
||||
* (c) 2014 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2014 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include "nest/bird.h"
|
||||
|
||||
void
|
||||
tbf_update(struct tbf *f)
|
||||
{
|
||||
bird_clock_t delta = now - f->timestamp;
|
||||
|
||||
if (delta == 0)
|
||||
return;
|
||||
|
||||
f->timestamp = now;
|
||||
|
||||
if ((0 < delta) && (delta < f->burst))
|
||||
{
|
||||
u32 next = f->count + delta * f->rate;
|
||||
f->count = MIN(next, f->burst);
|
||||
}
|
||||
else
|
||||
f->count = f->burst;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
Summary: BIRD Internet Routing Daemon
|
||||
Name: bird
|
||||
Version: 1.4.3
|
||||
Version: 1.4.5
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Networking/Daemons
|
||||
|
|
|
@ -57,10 +57,10 @@ CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OF
|
|||
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
||||
CF_KEYWORDS(RECEIVE, 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, MAX, FLUSH, AS)
|
||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
|
||||
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
|
||||
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
|
||||
CF_KEYWORDS(GRACEFUL, RESTART, WAIT)
|
||||
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
|
||||
|
||||
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
||||
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
|
||||
|
@ -77,7 +77,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
|
|||
%type <ro> roa_args
|
||||
%type <rot> roa_table_arg
|
||||
%type <sd> sym_args
|
||||
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport roa_mode limit_action tab_sorted tos
|
||||
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos
|
||||
%type <ps> proto_patt proto_patt2
|
||||
%type <g> limit_spec
|
||||
|
||||
|
@ -443,7 +443,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] [filtered] [(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|noexport) <p>] [protocol <p>] [stats|count]]], [[Show routing table]])
|
||||
{ rt_show($3); } ;
|
||||
|
||||
r_args:
|
||||
|
@ -492,7 +492,7 @@ r_args:
|
|||
$$ = $1;
|
||||
$$->filtered = 1;
|
||||
}
|
||||
| r_args export_or_preexport SYM {
|
||||
| r_args export_mode SYM {
|
||||
struct proto_config *c = (struct proto_config *) $3->def;
|
||||
$$ = $1;
|
||||
if ($$->export_mode) cf_error("Protocol specified twice");
|
||||
|
@ -519,9 +519,10 @@ r_args:
|
|||
}
|
||||
;
|
||||
|
||||
export_or_preexport:
|
||||
PREEXPORT { $$ = 1; }
|
||||
| EXPORT { $$ = 2; }
|
||||
export_mode:
|
||||
PREEXPORT { $$ = RSEM_PREEXPORT; }
|
||||
| EXPORT { $$ = RSEM_EXPORT; }
|
||||
| NOEXPORT { $$ = RSEM_NOEXPORT; }
|
||||
;
|
||||
|
||||
|
||||
|
|
|
@ -301,6 +301,12 @@ struct rt_show_data {
|
|||
};
|
||||
void rt_show(struct rt_show_data *);
|
||||
|
||||
/* Value of export_mode in struct rt_show_data */
|
||||
#define RSEM_NONE 0 /* Export mode not used */
|
||||
#define RSEM_PREEXPORT 1 /* Routes ready for export, before filtering */
|
||||
#define RSEM_EXPORT 2 /* Routes accepted by export filter */
|
||||
#define RSEM_NOEXPORT 3 /* Routes rejected by export filter */
|
||||
|
||||
/*
|
||||
* Route Attributes
|
||||
*
|
||||
|
|
|
@ -815,7 +815,7 @@ rta_alloc_hash(void)
|
|||
static inline unsigned int
|
||||
rta_hash(rta *a)
|
||||
{
|
||||
return (((unsigned) a->src) ^ ipa_hash(a->gw) ^
|
||||
return (((uint) (uintptr_t) a->src) ^ ipa_hash(a->gw) ^
|
||||
mpnh_hash(a->nexthops) ^ ea_hash(a->eattrs)) & 0xffff;
|
||||
}
|
||||
|
||||
|
|
|
@ -645,7 +645,7 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
|
|||
struct proto *p = ah->proto;
|
||||
struct rtable *table = ah->table;
|
||||
struct proto_stats *stats = ah->stats;
|
||||
static struct rate_limit rl_pipe;
|
||||
static struct tbf rl_pipe = TBF_DEFAULT_LOG_LIMITS;
|
||||
rte *before_old = NULL;
|
||||
rte *old_best = net->routes;
|
||||
rte *old = NULL;
|
||||
|
@ -1367,7 +1367,7 @@ rt_init(void)
|
|||
static int
|
||||
rt_prune_step(rtable *tab, int step, int *limit)
|
||||
{
|
||||
static struct rate_limit rl_flush;
|
||||
static struct tbf rl_flush = TBF_DEFAULT_LOG_LIMITS;
|
||||
struct fib_iterator *fit = &tab->prune_fit;
|
||||
|
||||
DBG("Pruning route table %s\n", tab->name);
|
||||
|
@ -2255,6 +2255,9 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||
|
||||
if (d->export_mode)
|
||||
{
|
||||
if (! d->export_protocol->rt_notify)
|
||||
return;
|
||||
|
||||
a = proto_find_announce_hook(d->export_protocol, d->table);
|
||||
if (!a)
|
||||
return;
|
||||
|
@ -2287,18 +2290,20 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||
if (ic < 0)
|
||||
goto skip;
|
||||
|
||||
if (d->export_mode > 1)
|
||||
if (d->export_mode > RSEM_PREEXPORT)
|
||||
{
|
||||
/*
|
||||
* FIXME - This shows what should be exported according to current
|
||||
* filters, but not what was really exported. 'configure soft'
|
||||
* command may change the export filter and do not update routes.
|
||||
*/
|
||||
int do_export = (ic > 0) ||
|
||||
(f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
|
||||
|
||||
if (!ic && (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
|
||||
if (do_export != (d->export_mode == RSEM_EXPORT))
|
||||
goto skip;
|
||||
|
||||
if (ep->accept_ra_types == RA_ACCEPTED)
|
||||
if ((d->export_mode == RSEM_EXPORT) && (ep->accept_ra_types == RA_ACCEPTED))
|
||||
pass = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1071,7 +1071,7 @@ bfd_show_sessions(struct proto *P)
|
|||
{
|
||||
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
||||
struct bfd_proto *p = (struct bfd_proto *) P;
|
||||
uint state, diag;
|
||||
uint state, diag UNUSED;
|
||||
u32 tx_int, timeout;
|
||||
const char *ifname;
|
||||
|
||||
|
|
|
@ -680,8 +680,8 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
|
|||
s->type = SK_TCP_ACTIVE;
|
||||
s->saddr = p->source_addr;
|
||||
s->daddr = p->cf->remote_ip;
|
||||
s->dport = p->cf->remote_port;
|
||||
s->iface = p->neigh ? p->neigh->iface : NULL;
|
||||
s->dport = BGP_PORT;
|
||||
s->ttl = p->cf->ttl_security ? 255 : hops;
|
||||
s->rbsize = BGP_RX_BUFFER_SIZE;
|
||||
s->tbsize = BGP_TX_BUFFER_SIZE;
|
||||
|
@ -1016,9 +1016,9 @@ bgp_start(struct proto *P)
|
|||
|
||||
lock = p->lock = olock_new(P->pool);
|
||||
lock->addr = p->cf->remote_ip;
|
||||
lock->port = p->cf->remote_port;
|
||||
lock->iface = p->cf->iface;
|
||||
lock->type = OBJLOCK_TCP;
|
||||
lock->port = BGP_PORT;
|
||||
lock->hook = bgp_start_locked;
|
||||
lock->data = p;
|
||||
olock_acquire(lock);
|
||||
|
|
|
@ -23,6 +23,7 @@ struct bgp_config {
|
|||
ip_addr remote_ip;
|
||||
ip_addr source_addr; /* Source address to use */
|
||||
struct iface *iface; /* Interface for link-local addresses */
|
||||
u16 remote_port; /* Neighbor destination port */
|
||||
int multihop; /* Number of hops if multihop */
|
||||
int ttl_security; /* Enable TTL security [RFC5082] */
|
||||
int next_hop_self; /* Always set next hop to local IP address */
|
||||
|
|
|
@ -60,7 +60,7 @@ bgp_proto:
|
|||
| bgp_proto proto_item ';'
|
||||
| bgp_proto LOCAL AS expr ';' { BGP_CFG->local_as = $4; }
|
||||
| bgp_proto LOCAL ipa AS expr ';' { BGP_CFG->source_addr = $3; BGP_CFG->local_as = $5; }
|
||||
| bgp_proto NEIGHBOR ipa ipa_scope AS expr ';' {
|
||||
| bgp_proto NEIGHBOR ipa ipa_scope ipa_port AS expr ';' {
|
||||
if (ipa_nonzero(BGP_CFG->remote_ip))
|
||||
cf_error("Only one neighbor per BGP instance is allowed");
|
||||
if (!ipa_has_link_scope($3) != !$4)
|
||||
|
@ -68,7 +68,8 @@ bgp_proto:
|
|||
|
||||
BGP_CFG->remote_ip = $3;
|
||||
BGP_CFG->iface = $4;
|
||||
BGP_CFG->remote_as = $6;
|
||||
BGP_CFG->remote_port = ($5 > 0) ? $5 : BGP_PORT;
|
||||
BGP_CFG->remote_as = $7;
|
||||
}
|
||||
| bgp_proto RR CLUSTER ID idval ';' { BGP_CFG->rr_cluster_id = $5; }
|
||||
| bgp_proto RR CLIENT ';' { BGP_CFG->rr_client = 1; }
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
|
||||
#include "bgp.h"
|
||||
|
||||
static struct rate_limit rl_rcv_update, rl_snd_update;
|
||||
static struct tbf rl_rcv_update = TBF_DEFAULT_LOG_LIMITS;
|
||||
static struct tbf rl_snd_update = TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
/* Table for state -> RFC 6608 FSM error subcodes */
|
||||
static byte fsm_err_subcode[BS_MAX] = {
|
||||
|
|
|
@ -30,9 +30,9 @@ CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
|
|||
MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
|
||||
TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
|
||||
LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
|
||||
LOCAL, TRIGGER, SENSITIVE)
|
||||
LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH)
|
||||
|
||||
%type<i> radv_mult radv_sensitive
|
||||
%type<i> radv_mult radv_sensitive radv_preference
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
|
@ -84,6 +84,7 @@ radv_iface_start:
|
|||
RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
|
||||
RADV_IFACE->default_lifetime = -1;
|
||||
RADV_IFACE->default_lifetime_sensitive = 1;
|
||||
RADV_IFACE->default_preference = RA_PREF_MEDIUM;
|
||||
};
|
||||
|
||||
radv_iface_item:
|
||||
|
@ -101,6 +102,7 @@ radv_iface_item:
|
|||
if (($3 < 0) || ($3 > 9000)) cf_error("Default lifetime must be in range 0-9000");
|
||||
if ($4 != -1) RADV_IFACE->default_lifetime_sensitive = $4;
|
||||
}
|
||||
| DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; }
|
||||
| PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
|
||||
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
|
||||
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
|
||||
|
@ -108,6 +110,11 @@ radv_iface_item:
|
|||
| DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
|
||||
;
|
||||
|
||||
radv_preference:
|
||||
LOW { $$ = RA_PREF_LOW; }
|
||||
| MEDIUM { $$ = RA_PREF_MEDIUM; }
|
||||
| HIGH { $$ = RA_PREF_HIGH; }
|
||||
|
||||
radv_iface_finish:
|
||||
{
|
||||
struct radv_iface_config *ic = RADV_IFACE;
|
||||
|
|
|
@ -251,10 +251,11 @@ radv_prepare_ra(struct radv_iface *ifa)
|
|||
pkt->code = 0;
|
||||
pkt->checksum = 0;
|
||||
pkt->current_hop_limit = ic->current_hop_limit;
|
||||
pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
|
||||
(ic->other_config ? OPT_RA_OTHER_CFG : 0);
|
||||
pkt->router_lifetime = (ra->active || !ic->default_lifetime_sensitive) ?
|
||||
htons(ic->default_lifetime) : 0;
|
||||
pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
|
||||
(ic->other_config ? OPT_RA_OTHER_CFG : 0) |
|
||||
(pkt->router_lifetime ? ic->default_preference : 0);
|
||||
pkt->reachable_time = htonl(ic->reachable_time);
|
||||
pkt->retrans_timer = htonl(ic->retrans_timer);
|
||||
buf += sizeof(*pkt);
|
||||
|
@ -330,10 +331,15 @@ radv_send_ra(struct radv_iface *ifa, int shutdown)
|
|||
|
||||
if (shutdown)
|
||||
{
|
||||
/* Modify router lifetime to 0, it is not restored because
|
||||
we suppose that the iface will be removed */
|
||||
/*
|
||||
* Modify router lifetime to 0, it is not restored because we suppose that
|
||||
* the iface will be removed. The preference value also has to be zeroed.
|
||||
* (RFC 4191 2.2: If router lifetime is 0, the preference value must be 0.)
|
||||
*/
|
||||
|
||||
struct radv_ra_packet *pkt = (void *) ifa->sk->tbuf;
|
||||
pkt->router_lifetime = 0;
|
||||
pkt->flags &= ~RA_PREF_MASK;
|
||||
}
|
||||
|
||||
RADV_TRACE(D_PACKETS, "Sending RA via %s", ifa->iface->name);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
* Supported standards:
|
||||
* - RFC 4861 - main RA standard
|
||||
* - RFC 6106 - DNS extensions (RDDNS, DNSSL)
|
||||
* - RFC 4191 (partial) - Default Router Preference
|
||||
*/
|
||||
|
||||
static void
|
||||
|
|
|
@ -80,6 +80,7 @@ struct radv_iface_config
|
|||
u32 current_hop_limit;
|
||||
u32 default_lifetime;
|
||||
u8 default_lifetime_sensitive; /* Whether default_lifetime depends on trigger */
|
||||
u8 default_preference; /* Default Router Preference (RFC 4191) */
|
||||
};
|
||||
|
||||
struct radv_prefix_config
|
||||
|
@ -144,6 +145,11 @@ struct radv_iface
|
|||
#define RA_EV_CHANGE 2 /* Change of options or prefixes */
|
||||
#define RA_EV_RS 3 /* Received RS */
|
||||
|
||||
/* Default Router Preferences (RFC 4191) */
|
||||
#define RA_PREF_LOW 0x18
|
||||
#define RA_PREF_MEDIUM 0x00
|
||||
#define RA_PREF_HIGH 0x08
|
||||
#define RA_PREF_MASK 0x18
|
||||
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
|
|
|
@ -261,6 +261,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
|||
msg.rtm.rtm_flags |= RTF_GATEWAY;
|
||||
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||
break;
|
||||
|
||||
#ifdef RTF_REJECT
|
||||
case RTD_UNREACHABLE:
|
||||
#endif
|
||||
|
@ -280,7 +281,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
|||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_fill(&dst, BIRD_AF, i->addr->ip, NULL, 0);
|
||||
sockaddr_fill(&gate, BIRD_AF, i->addr->ip, NULL, 0);
|
||||
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -141,6 +141,7 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
#ifdef IP_SENDSRCADDR
|
||||
struct cmsghdr *cm;
|
||||
struct in_addr *sa;
|
||||
int controllen = 0;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
@ -149,11 +150,12 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
cm->cmsg_level = IPPROTO_IP;
|
||||
cm->cmsg_type = IP_SENDSRCADDR;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*sa));
|
||||
controllen += CMSG_SPACE(sizeof(*sa));
|
||||
|
||||
sa = (struct in_addr *) CMSG_DATA(cm);
|
||||
*sa = ipa_to_in4(s->saddr);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
msg->msg_controllen = controllen;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#define _BIRD_CONFIG_H_
|
||||
|
||||
/* BIRD version */
|
||||
#define BIRD_VERSION "1.4.3"
|
||||
#define BIRD_VERSION "1.4.5"
|
||||
|
||||
/* Include parameters determined by configure script */
|
||||
#include "sysdep/autoconf.h"
|
||||
|
|
|
@ -151,7 +151,7 @@ nl_get_reply(struct nl_sock *nl)
|
|||
}
|
||||
}
|
||||
|
||||
static struct rate_limit rl_netlink_err;
|
||||
static struct tbf rl_netlink_err = TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
static int
|
||||
nl_error(struct nlmsghdr *h)
|
||||
|
|
|
@ -154,6 +154,7 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in_pktinfo *pi;
|
||||
int controllen = 0;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
@ -162,13 +163,14 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
cm->cmsg_level = SOL_IP;
|
||||
cm->cmsg_type = IP_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
|
||||
controllen += CMSG_SPACE(sizeof(*pi));
|
||||
|
||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
pi->ipi_ifindex = s->iface ? s->iface->index : 0;
|
||||
pi->ipi_spec_dst = ipa_to_in4(s->saddr);
|
||||
pi->ipi_addr = ipa_to_in4(IPA_NONE);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
msg->msg_controllen = controllen;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -705,6 +705,7 @@ sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo *pi;
|
||||
int controllen = 0;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
@ -713,12 +714,13 @@ sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||
cm->cmsg_level = SOL_IPV6;
|
||||
cm->cmsg_type = IPV6_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
|
||||
controllen += CMSG_SPACE(sizeof(*pi));
|
||||
|
||||
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
|
||||
pi->ipi6_addr = ipa_to_in6(s->saddr);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
msg->msg_controllen = controllen;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1965,7 +1967,7 @@ io_loop(void)
|
|||
while (current_sock && count < MAX_RX_STEPS)
|
||||
{
|
||||
sock *s = current_sock;
|
||||
int e;
|
||||
int e UNUSED;
|
||||
|
||||
if ((s->type < SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook)
|
||||
{
|
||||
|
|
|
@ -300,10 +300,10 @@ krt_trace_in(struct krt_proto *p, rte *e, char *msg)
|
|||
}
|
||||
|
||||
static inline void
|
||||
krt_trace_in_rl(struct rate_limit *rl, struct krt_proto *p, rte *e, char *msg)
|
||||
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
|
||||
{
|
||||
if (p->p.debug & D_PACKETS)
|
||||
log_rl(rl, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
|
||||
log_rl(f, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -312,7 +312,7 @@ krt_trace_in_rl(struct rate_limit *rl, struct krt_proto *p, rte *e, char *msg)
|
|||
|
||||
#ifdef KRT_ALLOW_LEARN
|
||||
|
||||
static struct rate_limit rl_alien_seen, rl_alien_updated, rl_alien_created, rl_alien_ignored;
|
||||
static struct tbf rl_alien = TBF_DEFAULT_LOG_LIMITS;
|
||||
|
||||
/*
|
||||
* krt_same_key() specifies what (aside from the net) is the key in
|
||||
|
@ -378,20 +378,20 @@ krt_learn_scan(struct krt_proto *p, rte *e)
|
|||
{
|
||||
if (krt_uptodate(m, e))
|
||||
{
|
||||
krt_trace_in_rl(&rl_alien_seen, p, e, "[alien] seen");
|
||||
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
|
||||
rte_free(e);
|
||||
m->u.krt.seen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
krt_trace_in_rl(&rl_alien_updated, p, e, "[alien] updated");
|
||||
krt_trace_in(p, e, "[alien] updated");
|
||||
*mm = m->next;
|
||||
rte_free(m);
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
krt_trace_in_rl(&rl_alien_created, p, e, "[alien] created");
|
||||
krt_trace_in(p, e, "[alien] created");
|
||||
if (!m)
|
||||
{
|
||||
e->next = n->routes;
|
||||
|
@ -637,7 +637,7 @@ krt_got_route(struct krt_proto *p, rte *e)
|
|||
krt_learn_scan(p, e);
|
||||
else
|
||||
{
|
||||
krt_trace_in_rl(&rl_alien_ignored, p, e, "[alien] ignored");
|
||||
krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored");
|
||||
rte_free(e);
|
||||
}
|
||||
return;
|
||||
|
@ -910,7 +910,7 @@ krt_scan_timer_stop(struct krt_proto *p)
|
|||
}
|
||||
|
||||
static void
|
||||
krt_scan_timer_kick(struct krt_proto *p UNUSED)
|
||||
krt_scan_timer_kick(struct krt_proto *p)
|
||||
{
|
||||
tm_start(p->scan_timer, 0);
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
|
|||
}
|
||||
|
||||
static void
|
||||
krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
|
||||
krt_rt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
|
||||
rte *new, rte *old, struct ea_list *eattrs)
|
||||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
@ -991,6 +991,36 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
|
|||
krt_replace_rte(p, net, new, old, eattrs);
|
||||
}
|
||||
|
||||
static void
|
||||
krt_if_notify(struct proto *P, uint flags, struct iface *iface UNUSED)
|
||||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
||||
/*
|
||||
* When interface went down, we should remove routes to it. In the ideal world,
|
||||
* OS kernel would send us route removal notifications in such cases, but we
|
||||
* cannot rely on it as it is often not true. E.g. Linux kernel removes related
|
||||
* routes when an interface went down, but it does not notify userspace about
|
||||
* that. To be sure, we just schedule a scan to ensure synchronization.
|
||||
*/
|
||||
|
||||
if ((flags & IF_CHANGE_DOWN) && KRT_CF->learn)
|
||||
krt_scan_timer_kick(p);
|
||||
}
|
||||
|
||||
static int
|
||||
krt_reload_routes(struct proto *P)
|
||||
{
|
||||
struct krt_proto *p = (struct krt_proto *) P;
|
||||
|
||||
/* Although we keep learned routes in krt_table, we rather schedule a scan */
|
||||
|
||||
if (KRT_CF->learn)
|
||||
krt_scan_timer_kick(p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
krt_feed_done(struct proto *P)
|
||||
{
|
||||
|
@ -1022,7 +1052,9 @@ krt_init(struct proto_config *c)
|
|||
|
||||
p->p.accept_ra_types = RA_OPTIMAL;
|
||||
p->p.import_control = krt_import_control;
|
||||
p->p.rt_notify = krt_notify;
|
||||
p->p.rt_notify = krt_rt_notify;
|
||||
p->p.if_notify = krt_if_notify;
|
||||
p->p.reload_routes = krt_reload_routes;
|
||||
p->p.feed_done = krt_feed_done;
|
||||
p->p.make_tmp_attrs = krt_make_tmp_attrs;
|
||||
p->p.store_tmp_attrs = krt_store_tmp_attrs;
|
||||
|
|
|
@ -32,9 +32,6 @@ static FILE *dbgf;
|
|||
static list *current_log_list;
|
||||
static char *current_syslog_name; /* NULL -> syslog closed */
|
||||
|
||||
static const bird_clock_t rate_limit_time = 5;
|
||||
static const int rate_limit_count = 5;
|
||||
|
||||
|
||||
#ifdef USE_PTHREADS
|
||||
|
||||
|
@ -154,7 +151,6 @@ vlog(int class, const char *msg, va_list args)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* log - log a message
|
||||
* @msg: printf-like formatting string with message class information
|
||||
|
@ -180,31 +176,21 @@ log_msg(char *msg, ...)
|
|||
}
|
||||
|
||||
void
|
||||
log_rl(struct rate_limit *rl, char *msg, ...)
|
||||
log_rl(struct tbf *f, char *msg, ...)
|
||||
{
|
||||
int last_hit = f->mark;
|
||||
int class = 1;
|
||||
va_list args;
|
||||
|
||||
bird_clock_t delta = now - rl->timestamp;
|
||||
if ((0 <= delta) && (delta < rate_limit_time))
|
||||
{
|
||||
rl->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
rl->timestamp = now;
|
||||
rl->count = 1;
|
||||
}
|
||||
|
||||
if (rl->count > rate_limit_count)
|
||||
/* Rate limiting is a bit tricky here as it also logs '...' during the first hit */
|
||||
if (tbf_limit(f) && last_hit)
|
||||
return;
|
||||
|
||||
va_start(args, msg);
|
||||
if (*msg >= 1 && *msg <= 8)
|
||||
class = *msg++;
|
||||
vlog(class, msg, args);
|
||||
if (rl->count == rate_limit_count)
|
||||
vlog(class, "...", args);
|
||||
|
||||
va_start(args, msg);
|
||||
vlog(class, (f->mark ? "..." : msg), args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue