diff --git a/conf/confbase.Y b/conf/confbase.Y index ed3c1e6e..b29abf4c 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -95,11 +95,15 @@ CF_DECLS btime time; struct f_prefix px; struct proto_spec ps; + struct table_spec ts; struct channel_limit cl; struct timeformat *tf; mpls_label_stack *mls; const struct adata *bs; struct aggr_item_node *ai; + struct logging_rate_targets *lrt; + struct tbf_config *tc; + enum tbf_targets tt; } %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT diff --git a/lib/birdlib.h b/lib/birdlib.h index b7226411..8fba8ae4 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -108,16 +108,46 @@ typedef s64 btime; /* Rate limiting */ +struct tbf_config { + u16 burst; /* Max number of tokens */ + u16 rate; /* Rate of replenishment (tokens / sec) */ + }; + struct tbf { btime timestamp; /* Last update */ u64 count; /* Available micro-tokens */ - u16 burst; /* Max number of tokens */ - u16 rate; /* Rate of replenishment (tokens / sec) */ u32 drop; /* Number of failed request since last successful */ + struct tbf_config cf; /* Configuration */ +}; + +enum tbf_targets { + TBF_INVALID = 0, + TBF_OSPF_PKT, + TBF_OSPF_LSA, + TBF_RIP_PKT, + TBF_RIP_RTE, + TBF_BABEL_PKT, + TBF_ALL +}; + +struct logging_rate_targets { + enum tbf_targets target; + struct logging_rate_targets *next; +}; + +struct cmd_logging_rate_info { + struct tbf_config *tbfc; + struct logging_rate_targets *targets; +}; + + +struct table_spec { + const void *ptr; + int patt; }; /* Default TBF values for rate limiting log messages */ -#define TBF_DEFAULT_LOG_LIMITS { .rate = 1, .burst = 5 } +#define TBF_DEFAULT_LOG_LIMITS { .cf.rate = 1, .cf.burst = 5 } int tbf_limit(struct tbf *f); diff --git a/lib/tbf.c b/lib/tbf.c index e6e84b4f..7e1cfabf 100644 --- a/lib/tbf.c +++ b/lib/tbf.c @@ -17,8 +17,8 @@ tbf_limit(struct tbf *f) if (delta > 0) { - u64 next = f->count + delta * f->rate; - u64 burst = (u64) f->burst << 20; + u64 next = f->count + delta * f->cf.rate; + u64 burst = (u64) f->cf.burst << 20; f->count = MIN(next, burst); f->timestamp += delta; } diff --git a/nest/config.Y b/nest/config.Y index 20186ece..a89509c9 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -15,6 +15,7 @@ CF_HDR #include "nest/mpls.h" #include "lib/lists.h" #include "lib/mac.h" +#include "lib/birdlib.h" CF_DEFINES @@ -128,6 +129,9 @@ CF_KEYWORDS(MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE) CF_KEYWORDS(CHECK, LINK) CF_KEYWORDS(SORTED, TRIE, MIN, MAX, SETTLE, TIME, GC, THRESHOLD, PERIOD) CF_KEYWORDS(MPLS_LABEL, MPLS_POLICY, MPLS_CLASS) +CF_KEYWORDS(ASPA_PROVIDERS) +CF_KEYWORDS(LOGGING, RATE) +CF_KEYWORDS( OSPF_PKT, OSPF_LSA, RIP_PKT, RIP_RTE, BABEL_PKT) /* For r_args_channel */ CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC) @@ -149,12 +153,16 @@ CF_ENUM(T_ENUM_MPLS_POLICY, MPLS_POLICY_, NONE, STATIC, PREFIX, AGGREGATE, VRF) %type sym_args %type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type net_type_base tos password_algorithm %type proto_patt proto_patt2 +%type table_patt %type channel_start proto_channel %type limit_spec %type r_args_for_val %type r_args_for %type channel_sym %type channel_arg +%type logging_rate_targets +%type logging_rate +%type tbf_target CF_GRAMMAR @@ -220,6 +228,8 @@ table: table_start table_sorted table_opt_list ; table_start: net_type TABLE symbol { this_table = rt_new_table($3, $1); + this_table->log_tbf_cf.rate = 1; + this_table->log_tbf_cf.burst = 5; } ; @@ -240,6 +250,7 @@ table_opt: | MAX SETTLE TIME expr_us { this_table->max_settle_time = $4; } | GC THRESHOLD expr { this_table->gc_threshold = $3; } | GC PERIOD expr_us { this_table->gc_period = (uint) $3; if ($3 > 3600 S_) cf_error("GC period must be at most 3600 s"); } + | LOGGING RATE expr expr { this_table->log_tbf_cf.rate = $3; this_table->log_tbf_cf.burst = $4; } ; table_opts: @@ -937,6 +948,49 @@ CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]]) CF_CLI(DEBUG, debug_args, ( | | \"\" | all) (all | off | { states|routes|filters|interfaces|events|packets [, ...] }), [[Control protocol debugging via BIRD logs]]) { /* Done in debug_args */ }; +logging_rate_target: PIPE ; + +tbf_target: + OSPF_PKT { $$ = TBF_OSPF_PKT; } + |OSPF_LSA { $$ = TBF_OSPF_LSA; } + |RIP_PKT { $$ = TBF_RIP_PKT; } + |RIP_RTE { $$ = TBF_RIP_RTE; } + |BABEL_PKT { $$ = TBF_BABEL_PKT; } + |ALL { $$ = TBF_ALL; } + +logging_rate_targets: + logging_rate_targets tbf_target { + $$ = (struct logging_rate_targets *) cfg_allocz(sizeof(struct logging_rate_targets)); + $$->next = $1; + $$->target = $2; + } | tbf_target { + $$ = cfg_allocz(sizeof(struct logging_rate_targets)); + $$->next = NULL; + $$->target = $1; + }; + +logging_rate: expr expr +{ + $$ = cfg_allocz(sizeof(struct tbf_config)); + $$->rate = $1; + $$->burst = $2; +}; + +CF_CLI(LOGGING RATE PROTOCOL, proto_patt logging_rate_targets logging_rate, ( | \"\" | all) targets , [[Set logging rate for given protocols and targets]]) +{ + struct cmd_logging_rate_info info = { + .tbfc = $6, + .targets = $5, + }; + proto_apply_cmd($4, proto_cmd_logging_rate, 1, (uintptr_t) &info); +}; + +CF_CLI(LOGGING RATE TABLE, table_patt logging_rate, ( | \"\" | all) , [[Set logging rate for given tables and targets]]) +{ + table_logging_cmd($4, $5); +}; + + CF_CLI_OPT(DEBUG ALL) CF_CLI_OPT(DEBUG OFF) CF_CLI_OPT(DEBUG STATES) @@ -970,6 +1024,12 @@ proto_patt2: | TEXT { $$.ptr = $1; $$.patt = 1; } ; +table_patt: + CF_SYM_KNOWN { cf_assert_symbol($1, SYM_TABLE); $$.ptr = $1; $$.patt = 0; } + | ALL { $$.ptr = NULL; $$.patt = 1; } + | TEXT { $$.ptr = $1; $$.patt = 1; } + ; + dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); } ; dynamic_attr: MPLS_LABEL { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_MPLS_LABEL); } ; diff --git a/nest/proto.c b/nest/proto.c index 88f4813e..a2eb56a9 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -2280,6 +2280,15 @@ proto_cmd_mrtdump(struct proto *p, uintptr_t mask, int cnt UNUSED) p->mrtdump = mask; } +void +proto_cmd_logging_rate(struct proto *p, uintptr_t arg, int cnt UNUSED) +{ + if (p->set_logging_rate) + p->set_logging_rate(p, arg); + else + cli_msg(9002, "protocol %s does not support logging rate changes", p->name); +} + static void proto_apply_cmd_symbol(const struct symbol *s, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg) { diff --git a/nest/protocol.h b/nest/protocol.h index c87d3814..9e70fefb 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -243,6 +243,7 @@ struct proto { void (*rte_insert)(struct network *, struct rte *); void (*rte_remove)(struct network *, struct rte *); u32 (*rte_igp_metric)(struct rte *); + void (*set_logging_rate)(struct proto *P, uintptr_t arg); /* Hic sunt protocol-specific data */ }; @@ -293,6 +294,7 @@ void proto_cmd_restart(struct proto *, uintptr_t, int); void proto_cmd_reload(struct proto *, uintptr_t, int); void proto_cmd_debug(struct proto *, uintptr_t, int); void proto_cmd_mrtdump(struct proto *, uintptr_t, int); +void proto_cmd_logging_rate(struct proto *, uintptr_t, int); void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg); struct proto *proto_get_named(struct symbol *, struct protocol *); diff --git a/nest/route.h b/nest/route.h index 12e85006..53bccdd4 100644 --- a/nest/route.h +++ b/nest/route.h @@ -156,6 +156,7 @@ struct rtable_config { byte trie_used; /* Rtable has attached trie */ btime min_settle_time; /* Minimum settle time for notifications */ btime max_settle_time; /* Maximum settle time for notifications */ + struct tbf_config log_tbf_cf; /* Config logging rate for rtable */ }; typedef struct rtable { @@ -203,6 +204,7 @@ typedef struct rtable { list flowspec_links; /* List of flowspec links, src for NET_IPx and dst for NET_FLOWx */ struct f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */ // struct mpls_domain *mpls_domain; /* Label allocator for MPLS */ + struct tbf log_tbf; /* Actual logging rate for rtable (might be changed in cmd) */ } rtable; struct rt_subscription { @@ -719,6 +721,8 @@ void rta_dump(rta *); void rta_dump_all(void); void rta_show(struct cli *, rta *); +void table_logging_cmd(struct table_spec ts, struct tbf_config *rate); + u32 rt_get_igp_metric(rte *rt); struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep); void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls); diff --git a/nest/rt-table.c b/nest/rt-table.c index 1b30e7dc..81104673 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -110,6 +110,7 @@ #include "lib/string.h" #include "lib/alloca.h" #include "lib/flowspec.h" +#include "nest/cli.h" #ifdef CONFIG_BGP #include "proto/bgp/bgp.h" @@ -1029,7 +1030,6 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) struct proto *p = c->proto; struct rtable *table = c->table; struct proto_stats *stats = &c->stats; - static struct tbf rl_pipe = TBF_DEFAULT_LOG_LIMITS; rte *before_old = NULL; rte *old_best = net->routes; rte *old = NULL; @@ -1053,7 +1053,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) { if (new) { - log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %N to table %s", + log_rl(&table->log_tbf, L_ERR "Pipe collision detected when sending %N to table %s", net->n.addr, table->name); rte_free_quick(new); } @@ -1960,6 +1960,8 @@ rt_setup(pool *pp, struct rtable_config *cf) t->config = cf; t->addr_type = cf->addr_type; t->debug = cf->debug; + t->log_tbf.cf.rate = cf->log_tbf_cf.rate; + t->log_tbf.cf.burst = cf->log_tbf_cf.burst; fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL); @@ -2731,6 +2733,8 @@ rt_reconfigure(rtable *tab, struct rtable_config *new, struct rtable_config *old tab->name = new->name; tab->config = new; tab->debug = new->debug; + tab->log_tbf.cf.rate = new->log_tbf_cf.rate; + tab->log_tbf.cf.burst = new->log_tbf_cf.burst; return 1; } @@ -3482,6 +3486,47 @@ rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep) return he; } +void +cmd_logging_rate(rtable *table, struct tbf_config *rate) +{ + table->log_tbf.cf.rate = rate->rate; + table->log_tbf.cf.burst = rate->burst; +} + +void +table_logging_cmd(struct table_spec ts, struct tbf_config *rate) +{ + if (ts.patt) + { + const char *patt = (void *) ts.ptr; + int cnt = 0; + rtable *t; + node *n; + + WALK_LIST2(t, n, routing_tables, n) + if (!ts.ptr || patmatch(patt, t->name)) + { + cmd_logging_rate(t, rate); + cnt++; + } + + if (!cnt) + cli_msg(8003, "No tables match"); + else + cli_msg(0, ""); + } + else + { + const struct symbol *s = (struct symbol*) ts.ptr; + if (s->table->table) + { + cmd_logging_rate(s->table->table, rate); + cli_msg(0, ""); + } + else + cli_msg(9002, "%s does not exist", s->name); + } +} /* * Documentation for functions declared inline in route.h diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 4187d258..7508a5e6 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2582,7 +2582,8 @@ babel_start(struct proto *P) p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node)); p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request)); - p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 }; + P->set_logging_rate = babel_set_logging_rate; + p->log_pkt_tbf = (struct tbf){ .cf.rate = cf->log_pkt_tbf.rate, .cf.burst = cf->log_pkt_tbf.burst }; return PS_UP; } @@ -2634,6 +2635,8 @@ babel_reconfigure(struct proto *P, struct proto_config *CF) p->p.cf = CF; babel_reconfigure_ifaces(p, new); + p->log_pkt_tbf.cf.rate = new->log_pkt_tbf.rate; + p->log_pkt_tbf.cf.burst = new->log_pkt_tbf.burst; babel_trigger_update(p); babel_kick_timer(p); @@ -2641,6 +2644,26 @@ babel_reconfigure(struct proto *P, struct proto_config *CF) return 1; } +void +babel_set_logging_rate(struct proto *P, uintptr_t arg) +{ + struct babel_proto *p = (void *) P; + struct cmd_logging_rate_info *info = (struct cmd_logging_rate_info*) arg; + struct logging_rate_targets *targets = info->targets; + while (targets) + { + if (targets->target == TBF_BABEL_PKT || targets->target == TBF_ALL) + { + p->log_pkt_tbf.cf.rate = info->tbfc->rate; + p->log_pkt_tbf.cf.burst = info->tbfc->burst; + } + else + cli_msg(9002, "protocol %s: wrong logging rate change type for babel protocol", P->name); + targets = targets->next; + } +} + + struct protocol proto_babel = { .name = "Babel", diff --git a/proto/babel/babel.h b/proto/babel/babel.h index edde4cab..65e9c903 100644 --- a/proto/babel/babel.h +++ b/proto/babel/babel.h @@ -136,6 +136,8 @@ struct babel_config { struct channel_config *ip4_channel; struct channel_config *ip6_channel; + + struct tbf_config log_pkt_tbf; }; struct babel_iface_config { @@ -455,6 +457,7 @@ void babel_show_routes(struct proto *P); void babel_auth_reset_index(struct babel_iface *ifa); int babel_auth_check_pc(struct babel_iface *ifa, struct babel_msg_auth *msg); +void babel_set_logging_rate(struct proto *P, uintptr_t arg); /* packets.c */ void babel_enqueue(union babel_msg *msg, struct babel_iface *ifa); diff --git a/proto/babel/config.Y b/proto/babel/config.Y index d412a54b..23fd7f79 100644 --- a/proto/babel/config.Y +++ b/proto/babel/config.Y @@ -26,7 +26,8 @@ CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT, TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK, NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS, ENTRIES, RANDOMIZE, ROUTER, ID, AUTHENTICATION, NONE, MAC, PERMISSIVE, - EXTENDED, TUNNEL, RTT, MIN, MAX, DECAY, SEND, TIMESTAMPS, COST, DELAY) + EXTENDED, TUNNEL, RTT, MIN, MAX, DECAY, SEND, TIMESTAMPS, COST, DELAY, + PKT, LOGGING, RATE, BURST) CF_GRAMMAR @@ -37,6 +38,8 @@ babel_proto_start: proto_start BABEL this_proto = proto_config_new(&proto_babel, $1); init_list(&BABEL_CFG->iface_list); BABEL_CFG->hold_time = 1 S_; + BABEL_CFG->log_pkt_tbf.rate = 1; + BABEL_CFG->log_pkt_tbf.burst = 5; }; babel_proto_item: @@ -44,6 +47,7 @@ babel_proto_item: | proto_channel | INTERFACE babel_iface | RANDOMIZE ROUTER ID bool { BABEL_CFG->randomize_router_id = $4; } + | LOGGING RATE PKT expr expr { BABEL_CFG->log_pkt_tbf.rate = $4; BABEL_CFG->log_pkt_tbf.burst = $5; } ; babel_proto_opts: diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 7d35304a..a193c2ba 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -202,6 +202,7 @@ CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH) CF_KEYWORDS(MERGE, LSA, SUPPRESSION, MULTICAST, RFC5838, VPN, PE, ADDRESS) CF_KEYWORDS(GRACEFUL, RESTART, AWARE, TIME) +CF_KEYWORDS(PKT, LSA, LOGGING, RATE, BURST) %type lsadb_args %type ospf_variant ospf_af_mc nbma_eligible @@ -230,6 +231,10 @@ ospf_proto_start: proto_start ospf_variant OSPF_CFG->af_ext = !$2; OSPF_CFG->gr_mode = OSPF_GR_AWARE; OSPF_CFG->gr_time = OSPF_DEFAULT_GR_TIME; + OSPF_CFG->log_pkt_tbf.rate = 1; + OSPF_CFG->log_lsa_tbf.rate = 4; + OSPF_CFG->log_pkt_tbf.burst = 5; + OSPF_CFG->log_lsa_tbf.burst = 20; }; ospf_proto: @@ -270,6 +275,8 @@ ospf_proto_item: | TICK expr { OSPF_CFG->tick = $2; if($2 <= 0) cf_error("Tick must be greater than zero"); } | INSTANCE ID expr { OSPF_CFG->instance_id = $3; OSPF_CFG->instance_id_set = 1; if ($3 > 255) cf_error("Instance ID must be in range 0-255"); } | ospf_area + | LOGGING RATE PKT expr expr { OSPF_CFG->log_pkt_tbf.rate = $4; OSPF_CFG->log_pkt_tbf.burst = $5; } + | LOGGING RATE LSA expr expr { OSPF_CFG->log_lsa_tbf.rate = $4; OSPF_CFG->log_lsa_tbf.burst = $4; } ; ospf_area_start: AREA idval { @@ -568,6 +575,8 @@ lsadb_args: | lsadb_args CF_SYM_KNOWN { cf_assert_symbol($2, SYM_PROTO); $$ = $1; $$->proto = (struct ospf_proto *) proto_get_named($2, &proto_ospf); } ; +logging_rate_target: OSPF_PKT | OSPF_LSA ; + CF_CODE CF_END diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index ad4b2d14..0a133bfc 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -311,8 +311,9 @@ ospf_start(struct proto *P) p->flood_event = ev_new_init(P->pool, ospf_flood_event, p); - p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 }; - p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 }; + p->log_pkt_tbf = (struct tbf){ .cf.rate = c->log_pkt_tbf.rate, .cf.burst = c->log_pkt_tbf.burst }; + p->log_lsa_tbf = (struct tbf){ .cf.rate = c->log_lsa_tbf.rate, .cf.burst = c->log_lsa_tbf.burst }; + P->set_logging_rate = ospf_set_logging_rate; // for setting logging tbf temporarily from cmd /* Lock the channel when in GR recovery mode */ if (p->p.gr_recovery && (p->gr_mode == OSPF_GR_ABLE)) @@ -773,6 +774,30 @@ ospf_reconfigure(struct proto *P, struct proto_config *CF) return 1; } +void +ospf_set_logging_rate(struct proto *P, uintptr_t arg) +{ + struct ospf_proto *p = (void *) P; + struct cmd_logging_rate_info *info = (struct cmd_logging_rate_info*) arg; + struct logging_rate_targets *targets = info->targets; + while (targets) + { + if (targets->target == TBF_OSPF_PKT || targets->target == TBF_ALL) + { + p->log_pkt_tbf.cf.rate = info->tbfc->rate; + p->log_pkt_tbf.cf.burst = info->tbfc->burst; + } + else if (targets->target == TBF_OSPF_LSA || targets->target == TBF_ALL) + { + p->log_lsa_tbf.cf.rate = info->tbfc->rate; + p->log_lsa_tbf.cf.burst = info->tbfc->burst; + } + else + cli_msg(9002, "protocol %s: wrong logging rate change type for ospf protocol", P->name); + targets = targets->next; + } +} + void ospf_sh_neigh(struct proto *P, const char *iff) diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 3e704ae8..ccf842c6 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -106,6 +106,8 @@ struct ospf_config uint ecmp; list area_list; /* list of area configs (struct ospf_area_config) */ list vlink_list; /* list of configured vlinks (struct ospf_iface_patt) */ + struct tbf_config log_pkt_tbf; + struct tbf_config log_lsa_tbf; }; struct ospf_area_config @@ -1021,6 +1023,7 @@ void ospf_iface_remove(struct ospf_iface *ifa); void ospf_iface_shutdown(struct ospf_iface *ifa); int ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen); int ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new); +void ospf_set_logging_rate(struct proto *P, uintptr_t arg); void ospf_reconfigure_ifaces(struct ospf_proto *p); void ospf_open_vlink_sk(struct ospf_proto *p); struct nbma_node *find_nbma_node_(list *nnl, ip_addr ip); diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 44f2742c..84b0f49d 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -38,7 +38,7 @@ CF_KEYWORDS(RIP, ECMP, LIMIT, WEIGHT, INFINITY, METRIC, UPDATE, TIMEOUT, PASSIVE, VERSION, SPLIT, HORIZON, POISON, REVERSE, CHECK, ZERO, TIME, BFD, AUTHENTICATION, NONE, PLAINTEXT, CRYPTOGRAPHIC, MD5, TTL, SECURITY, RX, TX, BUFFER, LENGTH, PRIORITY, ONLY, LINK, - DEMAND, CIRCUIT, RIP_METRIC, RIP_TAG) + DEMAND, CIRCUIT, RIP_METRIC, RIP_TAG, PKT, RTE, LOGGING, RATE, BURST) %type rip_variant rip_auth @@ -62,6 +62,10 @@ rip_proto_start: proto_start rip_variant RIP_CFG->infinity = RIP_DEFAULT_INFINITY; RIP_CFG->min_timeout_time = 60 S_; RIP_CFG->max_garbage_time = 60 S_; + RIP_CFG->log_pkt_tbf.rate = 1; + RIP_CFG->log_rte_tbf.rate = 4; + RIP_CFG->log_pkt_tbf.burst = 5; + RIP_CFG->log_rte_tbf.burst = 20; }; rip_proto_item: @@ -71,6 +75,8 @@ rip_proto_item: | ECMP bool LIMIT expr { RIP_CFG->ecmp = $2 ? $4 : 0; } | INFINITY expr { RIP_CFG->infinity = $2; } | INTERFACE rip_iface + | LOGGING RATE PKT expr expr { RIP_CFG->log_pkt_tbf.rate = $4; RIP_CFG->log_pkt_tbf.burst = $5; } + | LOGGING RATE RTE expr expr { RIP_CFG->log_rte_tbf.rate = $4; RIP_CFG->log_rte_tbf.burst = $4; } ; rip_proto_opts: @@ -202,6 +208,8 @@ CF_CLI(SHOW RIP INTERFACES, optproto opttext, [] [\"\"], [[Show CF_CLI(SHOW RIP NEIGHBORS, optproto opttext, [] [\"\"], [[Show information about RIP neighbors]]) { PROTO_WALK_CMD($4, &proto_rip, p) rip_show_neighbors(p, $5); }; +logging_rate_target: RIP_PKT | RIP_RTE ; + CF_CODE diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 4bfb5756..d4c8eaa0 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -1161,8 +1161,9 @@ rip_start(struct proto *P) p->infinity = cf->infinity; p->triggered = 0; - p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 }; - p->log_rte_tbf = (struct tbf){ .rate = 4, .burst = 20 }; + p->log_pkt_tbf = (struct tbf){ .cf.rate = cf->log_pkt_tbf.rate, .cf.burst = cf->log_pkt_tbf.burst }; + p->log_rte_tbf = (struct tbf){ .cf.rate = cf->log_rte_tbf.rate, .cf.burst = cf->log_pkt_tbf.burst }; + P->set_logging_rate = rip_set_logging_rate; tm_start(p->timer, MIN(cf->min_timeout_time, cf->max_garbage_time)); @@ -1204,6 +1205,10 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) p->p.cf = CF; p->ecmp = new->ecmp; rip_reconfigure_ifaces(p, new); + p->log_pkt_tbf.cf.rate = new->log_pkt_tbf.rate; + p->log_pkt_tbf.cf.burst = new->log_pkt_tbf.burst; + p->log_rte_tbf.cf.rate = new->log_rte_tbf.rate; + p->log_rte_tbf.cf.burst = new->log_rte_tbf.burst; p->rt_reload = 1; rip_kick_timer(p); @@ -1211,6 +1216,30 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) return 1; } +void +rip_set_logging_rate(struct proto *P, uintptr_t arg) +{ + struct rip_proto *p = (void *) P; + struct cmd_logging_rate_info *info = (struct cmd_logging_rate_info*) arg; + struct logging_rate_targets *targets = info->targets; + while (targets) + { + if (targets->target == TBF_RIP_PKT || targets->target == TBF_ALL) + { + p->log_pkt_tbf.cf.rate = info->tbfc->rate; + p->log_pkt_tbf.cf.burst = info->tbfc->burst; + } + else if (targets->target == TBF_RIP_RTE || targets->target == TBF_ALL) + { + p->log_rte_tbf.cf.rate = info->tbfc->rate; + p->log_rte_tbf.cf.burst = info->tbfc->burst; + } + else + cli_msg(9002, "protocol %s: wrong logging rate change type for rip protocol", P->name); + targets = targets->next; + } +} + static void rip_get_route_info(rte *rte, byte *buf) { diff --git a/proto/rip/rip.h b/proto/rip/rip.h index f8713c4a..c8d174d9 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -55,6 +55,8 @@ struct rip_config btime min_timeout_time; /* Minimum of interface timeout_time */ btime max_garbage_time; /* Maximum of interface garbage_time */ + struct tbf_config log_pkt_tbf; + struct tbf_config log_rte_tbf; }; struct rip_iface_config @@ -224,6 +226,7 @@ struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct r void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n); void rip_show_interfaces(struct proto *P, const char *iff); void rip_show_neighbors(struct proto *P, const char *iff); +void rip_set_logging_rate(struct proto *P, uintptr_t arg); /* packets.c */ void rip_send_request(struct rip_proto *p, struct rip_iface *ifa);