1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

BGP: Shutdown communication (RFC 8203)

The patch implements BGP Administrative Shutdown Communication (RFC 8203)
allowing BGP operators to pass messages related to BGP session
administrative shutdown/restart. It handles both transmit and receive of
shutdown messages. Messages are logged and may be displayed by show
protocol all command.

Thanks to Job Snijders for the basic patch.
This commit is contained in:
Ondrej Zajicek (work)
2017-09-19 19:55:37 +02:00
parent 7b2c5f3d28
commit cd1d99611e
7 changed files with 149 additions and 54 deletions

View File

@@ -696,12 +696,12 @@ echo_size:
}
;
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
CF_CLI(DISABLE, proto_patt text_or_none, (<protocol> | \"<pattern>\" | all) [message], [[Disable protocol]])
{ proto_apply_cmd($2, proto_cmd_disable, 1, (uintptr_t) $3); } ;
CF_CLI(ENABLE, proto_patt text_or_none, (<protocol> | \"<pattern>\" | all) [message], [[Enable protocol]])
{ proto_apply_cmd($2, proto_cmd_enable, 1, (uintptr_t) $3); } ;
CF_CLI(RESTART, proto_patt text_or_none, (<protocol> | \"<pattern>\" | all) [message], [[Restart protocol]])
{ proto_apply_cmd($2, proto_cmd_restart, 1, (uintptr_t) $3); } ;
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])

View File

@@ -610,6 +610,7 @@ proto_rethink_goal(struct proto *p)
config_del_obstacle(p->cf->global);
rem_node(&p->n);
rem_node(&p->glob_node);
mb_free(p->message);
mb_free(p);
if (!nc)
return;
@@ -1096,6 +1097,39 @@ proto_schedule_down(struct proto *p, byte restart, byte code)
tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
}
/**
* proto_set_message - set administrative message to protocol
* @p: protocol
* @msg: message
* @len: message length (-1 for NULL-terminated string)
*
* The function sets administrative message (string) related to protocol state
* change. It is called by the nest code for manual enable/disable/restart
* commands all routes to the protocol, and by protocol-specific code when the
* protocol state change is initiated by the protocol. Using NULL message clears
* the last message. The message string may be either NULL-terminated or with an
* explicit length.
*/
void
proto_set_message(struct proto *p, char *msg, int len)
{
mb_free(p->message);
p->message = NULL;
if (!msg || !len)
return;
if (len < 0)
len = strlen(msg);
if (!len)
return;
p->message = mb_alloc(proto_pool, len + 1);
memcpy(p->message, msg, len);
p->message[len] = 0;
}
/**
* proto_request_feeding - request feeding routes to the protocol
@@ -1497,7 +1531,7 @@ proto_show_basic_info(struct proto *p)
}
void
proto_cmd_show(struct proto *p, uint verbose, int cnt)
proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
{
byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
@@ -1520,6 +1554,10 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt)
{
if (p->cf->dsc)
cli_msg(-1006, " Description: %s", p->cf->dsc);
if (p->message)
cli_msg(-1006, " Message: %s", p->message);
if (p->cf->router_id)
cli_msg(-1006, " Router ID: %R", p->cf->router_id);
@@ -1533,7 +1571,7 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt)
}
void
proto_cmd_disable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
proto_cmd_disable(struct proto *p, uintptr_t arg, int cnt UNUSED)
{
if (p->disabled)
{
@@ -1544,12 +1582,13 @@ proto_cmd_disable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
log(L_INFO "Disabling protocol %s", p->name);
p->disabled = 1;
p->down_code = PDC_CMD_DISABLE;
proto_set_message(p, (char *) arg, -1);
proto_rethink_goal(p);
cli_msg(-9, "%s: disabled", p->name);
}
void
proto_cmd_enable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
proto_cmd_enable(struct proto *p, uintptr_t arg, int cnt UNUSED)
{
if (!p->disabled)
{
@@ -1559,12 +1598,13 @@ proto_cmd_enable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
log(L_INFO "Enabling protocol %s", p->name);
p->disabled = 0;
proto_set_message(p, (char *) arg, -1);
proto_rethink_goal(p);
cli_msg(-11, "%s: enabled", p->name);
}
void
proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED)
proto_cmd_restart(struct proto *p, uintptr_t arg, int cnt UNUSED)
{
if (p->disabled)
{
@@ -1575,6 +1615,7 @@ proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED)
log(L_INFO "Restarting protocol %s", p->name);
p->disabled = 1;
p->down_code = PDC_CMD_RESTART;
proto_set_message(p, (char *) arg, -1);
proto_rethink_goal(p);
p->disabled = 0;
proto_rethink_goal(p);
@@ -1582,7 +1623,7 @@ proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED)
}
void
proto_cmd_reload(struct proto *p, uint dir, int cnt UNUSED)
proto_cmd_reload(struct proto *p, uintptr_t dir, int cnt UNUSED)
{
if (p->disabled)
{
@@ -1624,19 +1665,19 @@ proto_cmd_reload(struct proto *p, uint dir, int cnt UNUSED)
}
void
proto_cmd_debug(struct proto *p, uint mask, int cnt UNUSED)
proto_cmd_debug(struct proto *p, uintptr_t mask, int cnt UNUSED)
{
p->debug = mask;
}
void
proto_cmd_mrtdump(struct proto *p, uint mask, int cnt UNUSED)
proto_cmd_mrtdump(struct proto *p, uintptr_t mask, int cnt UNUSED)
{
p->mrtdump = mask;
}
static void
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uint, int), uint arg)
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg)
{
if (s->class != SYM_PROTO)
{
@@ -1649,7 +1690,7 @@ proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uint, int)
}
static void
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint arg)
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg)
{
int cnt = 0;
@@ -1669,8 +1710,8 @@ proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint a
}
void
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uint, int),
int restricted, uint arg)
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int),
int restricted, uintptr_t arg)
{
if (restricted && cli_access_restricted())
return;

View File

@@ -164,6 +164,7 @@ struct proto {
u32 hash_key; /* Random key used for hashing of neighbors */
bird_clock_t last_state_change; /* Time of last state transition */
char *last_state_name_announced; /* Last state name we've announced to the user */
char *message; /* State-change message, allocated from proto_pool */
struct proto_stats stats; /* Current protocol statistics */
/*
@@ -250,6 +251,7 @@ struct proto_spec {
void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, int class);
void proto_copy_config(struct proto_config *dest, struct proto_config *src);
void proto_set_message(struct proto *p, char *msg, int len);
void proto_request_feeding(struct proto *p);
static inline void
@@ -267,15 +269,15 @@ void proto_graceful_restart_unlock(struct proto *p);
void proto_show_limit(struct proto_limit *l, const char *dsc);
void proto_show_basic_info(struct proto *p);
void proto_cmd_show(struct proto *, uint, int);
void proto_cmd_disable(struct proto *, uint, int);
void proto_cmd_enable(struct proto *, uint, int);
void proto_cmd_restart(struct proto *, uint, int);
void proto_cmd_reload(struct proto *, uint, int);
void proto_cmd_debug(struct proto *, uint, int);
void proto_cmd_mrtdump(struct proto *, uint, int);
void proto_cmd_show(struct proto *, uintptr_t, int);
void proto_cmd_disable(struct proto *, uintptr_t, int);
void proto_cmd_enable(struct proto *, uintptr_t, int);
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_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uint, int), int restricted, uint arg);
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 *);
#define CMD_RELOAD 0