diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2012-04-15 15:28:29 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2012-04-15 15:28:29 +0200 |
commit | ebecb6f6a11bb418dd054cf12a2673ca0d9eac37 (patch) | |
tree | 9454aad3bd2e84fc65b518574aa9d112a0e5155c /proto | |
parent | ae8b300164a975597f9b6caea0b205af2e4db30b (diff) |
Implements generalized import hooks.
Thanks to Alexander V. Chernikov for the original patch.
Diffstat (limited to 'proto')
-rw-r--r-- | proto/bgp/bgp.c | 63 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 1 | ||||
-rw-r--r-- | proto/bgp/config.Y | 6 | ||||
-rw-r--r-- | proto/bgp/packets.c | 3 | ||||
-rw-r--r-- | proto/pipe/config.Y | 1 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 45 | ||||
-rw-r--r-- | proto/pipe/pipe.h | 1 |
7 files changed, 76 insertions, 44 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 4dd4b7be..cf743dff 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -542,22 +542,6 @@ bgp_active(struct bgp_proto *p) bgp_start_timer(conn->connect_retry_timer, delay); } -int -bgp_apply_limits(struct bgp_proto *p) -{ - if (p->cf->route_limit && (p->p.stats.imp_routes > p->cf->route_limit)) - { - log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name); - bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED); - bgp_update_startup_delay(p); - bgp_stop(p, 1); // Errcode 6, 1 - max number of prefixes reached - return -1; - } - - return 0; -} - - /** * bgp_connect - initiate an outgoing connection * @p: BGP instance @@ -868,24 +852,46 @@ static int bgp_shutdown(struct proto *P) { struct bgp_proto *p = (struct bgp_proto *) P; - unsigned subcode; + unsigned subcode = 0; BGP_TRACE(D_EVENTS, "Shutdown requested"); - bgp_store_error(p, NULL, BE_MAN_DOWN, 0); - if (P->reconfiguring) + switch (P->down_code) { - if (P->cf_new) - subcode = 6; // Errcode 6, 6 - other configuration change + case PDC_CF_REMOVE: + case PDC_CF_DISABLE: + subcode = 3; // Errcode 6, 3 - peer de-configured + break; + + case PDC_CF_RESTART: + subcode = 6; // Errcode 6, 6 - other configuration change + break; + + case PDC_CMD_DISABLE: + subcode = 2; // Errcode 6, 2 - administrative shutdown + break; + + case PDC_CMD_RESTART: + subcode = 4; // Errcode 6, 4 - administrative reset + break; + + case PDC_IN_LIMIT_HIT: + subcode = 1; // Errcode 6, 1 - max number of prefixes reached + log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name); + + bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED); + if (P->cf->in_limit->action == PLA_RESTART) + bgp_update_startup_delay(p); else - subcode = 3; // Errcode 6, 3 - peer de-configured + p->startup_delay = 0; + goto done; } - else - subcode = 2; // Errcode 6, 2 - administrative shutdown + bgp_store_error(p, NULL, BE_MAN_DOWN, 0); p->startup_delay = 0; - bgp_stop(p, subcode); + done: + bgp_stop(p, subcode); return p->p.proto_state; } @@ -969,6 +975,10 @@ bgp_check_config(struct bgp_config *c) /* Different default for gw_mode */ if (!c->gw_mode) c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT; + + /* Disable after error incompatible with restart limit action */ + if (c->c.in_limit && (c->c.in_limit->action == PLA_RESTART) && c->disable_after_error) + c->c.in_limit->action = PLA_DISABLE; } static int @@ -1116,9 +1126,6 @@ bgp_get_status(struct proto *P, byte *buf) bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2); } -static inline bird_clock_t tm_remains(timer *t) -{ return t->expires ? t->expires - now : 0; } - static void bgp_show_proto_info(struct proto *P) { diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index a8c5818e..aa2db4b0 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -152,7 +152,6 @@ void bgp_conn_enter_established_state(struct bgp_conn *conn); void bgp_conn_enter_close_state(struct bgp_conn *conn); void bgp_conn_enter_idle_state(struct bgp_conn *conn); void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code); -int bgp_apply_limits(struct bgp_proto *p); void bgp_stop(struct bgp_proto *p, unsigned subcode); diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 78ca52de..5feaea0d 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -98,7 +98,11 @@ bgp_proto: | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; } | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; } | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; } - | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; } + | bgp_proto ROUTE LIMIT expr ';' { + this_proto->in_limit = cfg_allocz(sizeof(struct proto_limit)); + this_proto->in_limit->limit = $4; + this_proto->in_limit->action = PLA_RESTART; + } | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; } | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; } | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index d3e9b6a1..168025d0 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -915,9 +915,6 @@ bgp_do_rx_update(struct bgp_conn *conn, if (n = net_find(p->p.table, prefix, pxlen)) rte_update(p->p.table, n, &p->p, &p->p, NULL); } - - if (bgp_apply_limits(p) < 0) - goto done; } done: diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y index 40637558..4fb2b499 100644 --- a/proto/pipe/config.Y +++ b/proto/pipe/config.Y @@ -36,6 +36,7 @@ pipe_proto: cf_error("Routing table name expected"); 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 TRANSPARENT ';' { PIPE_CFG->mode = PIPE_TRANSPARENT; } ; diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 36b06d43..a5fcc6f6 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -24,9 +24,10 @@ * rte_update(), an import filter in ahook 2 is called. When a new * route is announced in the peer table, an export filter in ahook2 * and an import filter in ahook 1 are used. Oviously, there is no - * need in filtering the same route twice, so both import filters - * are set to accept, while user configured 'import' and 'export' - * filters are used as export filters in ahooks 2 and 1. + * need in filtering the same route twice, so both import filters are + * set to accept, while user configured 'import' and 'export' filters + * are used as export filters in ahooks 2 and 1. Route limits are + * handled similarly, but on the import side of ahooks. */ #undef LOCAL_DEBUG @@ -116,6 +117,8 @@ pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpo static int pipe_reload_routes(struct proto *P) { + struct pipe_proto *p = (struct pipe_proto *) P; + /* * Because the pipe protocol feeds routes from both routing tables * together, both directions are reloaded during refeed and 'reload @@ -123,6 +126,12 @@ pipe_reload_routes(struct proto *P) * request refeed when 'reload in' command is used. */ proto_request_feeding(P); + + if (P->main_ahook->in_limit) + P->main_ahook->in_limit->active = 0; + if (p->peer_ahook->in_limit) + p->peer_ahook->in_limit->active = 0; + return 1; } @@ -146,6 +155,7 @@ pipe_init(struct proto_config *C) static int pipe_start(struct proto *P) { + struct pipe_config *cf = (struct pipe_config *) P->cf; struct pipe_proto *p = (struct pipe_proto *) P; /* Lock both tables, unlock is handled in pipe_cleanup() */ @@ -155,10 +165,13 @@ pipe_start(struct proto *P) /* Going directly to PS_UP - prepare for feeding, connect the protocol to both routing tables */ - P->main_ahook = proto_add_announce_hook(P, P->table, - FILTER_ACCEPT, P->cf->out_filter, &P->stats); - p->peer_ahook = proto_add_announce_hook(P, p->peer_table, - FILTER_ACCEPT, P->cf->in_filter, &p->peer_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->in_limit = cf->c.in_limit; + + 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->in_limit = cf->out_limit; return PS_UP; } @@ -204,10 +217,16 @@ pipe_reconfigure(struct proto *P, struct proto_config *new) /* Update output filters in ahooks */ if (P->main_ahook) - P->main_ahook->out_filter = new->out_filter; + { + P->main_ahook->out_filter = new->out_filter; + P->main_ahook->in_limit = new->in_limit; + } 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; + } if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT)) return 1; @@ -283,12 +302,16 @@ static void pipe_show_proto_info(struct proto *P) { struct pipe_proto *p = (struct pipe_proto *) P; + struct pipe_config *cf = (struct pipe_config *) P->cf; // cli_msg(-1006, " Table: %s", P->table->name); // cli_msg(-1006, " Peer table: %s", p->peer_table->name); cli_msg(-1006, " Preference: %d", P->preference); - cli_msg(-1006, " Input filter: %s", filter_name(P->cf->in_filter)); - cli_msg(-1006, " Output filter: %s", filter_name(P->cf->out_filter)); + cli_msg(-1006, " Input filter: %s", filter_name(cf->c.in_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->out_limit, "Export limit:"); if (P->proto_state != PS_DOWN) pipe_show_stats(p); diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h index 50b31698..e777fb41 100644 --- a/proto/pipe/pipe.h +++ b/proto/pipe/pipe.h @@ -15,6 +15,7 @@ struct pipe_config { struct proto_config c; struct rtable_config *peer; /* Table we're connected to */ + struct proto_limit *out_limit; /* Export route limit */ int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */ }; |