summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y30
-rw-r--r--proto/bgp/packets.c10
3 files changed, 41 insertions, 0 deletions
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 1310582b..30424abb 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -118,6 +118,7 @@ struct bgp_config {
unsigned error_delay_time_min; /* Time to wait after an error is detected */
unsigned error_delay_time_max;
unsigned disable_after_error; /* Disable the protocol when error is detected */
+ u32 disable_after_cease; /* Disable it when cease is received, bitfield */
char *password; /* Password used for MD5 authentication */
int check_link; /* Use iface link state for liveness detection */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 04e6d666..41eaa729 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -32,6 +32,12 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
%type <i32> bgp_afi
+CF_KEYWORDS(CEASE, PREFIX, LIMIT, HIT, ADMINISTRATIVE, SHUTDOWN, RESET, PEER,
+ CONFIGURATION, CHANGE, DECONFIGURED, CONNECTION, REJECTED, COLLISION,
+ OUT, OF, RESOURCES)
+
+%type<i> bgp_cease_mask bgp_cease_list bgp_cease_flag
+
CF_GRAMMAR
CF_ADDTO(proto, bgp_proto '}' )
@@ -74,6 +80,29 @@ bgp_nbr_opts:
| bgp_nbr_opts AS expr { BGP_CFG->remote_as = $3; }
;
+bgp_cease_mask:
+ /* true -> all except connection collision */
+ bool { $$ = $1 ? ~(1 << 7) : 0; }
+ | '{' bgp_cease_list '}' { $$ = $2; }
+ ;
+
+bgp_cease_list:
+ bgp_cease_flag
+ | bgp_cease_list ',' bgp_cease_flag { $$ = $1 | $3; }
+ ;
+
+bgp_cease_flag:
+ CEASE { $$ = 1 << 0; }
+ | PREFIX LIMIT HIT { $$ = 1 << 1; }
+ | ADMINISTRATIVE SHUTDOWN { $$ = 1 << 2; }
+ | PEER DECONFIGURED { $$ = 1 << 3; }
+ | ADMINISTRATIVE RESET { $$ = 1 << 4; }
+ | CONNECTION REJECTED { $$ = 1 << 5; }
+ | CONFIGURATION CHANGE { $$ = 1 << 6; }
+ | CONNECTION COLLISION { $$ = 1 << 7; }
+ | OUT OF RESOURCES { $$ = 1 << 8; }
+ ;
+
bgp_proto:
bgp_proto_start proto_name '{'
| bgp_proto proto_item ';'
@@ -117,6 +146,7 @@ bgp_proto:
| bgp_proto ERROR FORGET TIME expr ';' { BGP_CFG->error_amnesia_time = $5; }
| bgp_proto ERROR WAIT TIME expr ',' expr ';' { BGP_CFG->error_delay_time_min = $5; BGP_CFG->error_delay_time_max = $7; }
| bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; }
+ | bgp_proto DISABLE AFTER CEASE bgp_cease_mask ';' { BGP_CFG->disable_after_cease = $5; }
| bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
| bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
| bgp_proto ENABLE EXTENDED MESSAGES bool ';' { BGP_CFG->enable_extended_messages = $5; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 95a974eb..aa08732d 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -2772,6 +2772,16 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len)
bgp_update_startup_delay(p);
bgp_stop(p, 0, NULL, 0);
}
+ else
+ {
+ uint subcode_bit = 1 << ((subcode <= 8) ? subcode : 0);
+ if (p->cf->disable_after_cease & subcode_bit)
+ {
+ log(L_INFO "%s: Disabled after Cease notification", p->p.name);
+ p->startup_delay = 0;
+ p->p.disabled = 1;
+ }
+ }
}
static void