From 794b37d521176053ca1b1177a367333f1fc5c280 Mon Sep 17 00:00:00 2001 From: bisdhdh Date: Wed, 23 Oct 2019 11:10:22 +0530 Subject: [PATCH] bgpd: Adding BGP GR Global & Per Neighbour FSM changes * Added FSM for peer and global configuration for graceful restart * Added debug option BGP_GRACEFUL_RESTART for logs specific to graceful restart processing Signed-off-by: Biswajit Sadhu --- bgpd/bgp_debug.c | 55 ++++++- bgpd/bgp_debug.h | 1 - bgpd/bgp_fsm.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_fsm.h | 11 +- bgpd/bgp_vty.h | 4 - bgpd/bgpd.c | 150 ++++++++++++++++++ bgpd/bgpd.h | 15 +- lib/command.h | 2 - 8 files changed, 597 insertions(+), 28 deletions(-) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index f716c4f308..498a871ce7 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -63,6 +63,7 @@ unsigned long conf_bgp_debug_vpn; unsigned long conf_bgp_debug_flowspec; unsigned long conf_bgp_debug_labelpool; unsigned long conf_bgp_debug_pbr; +unsigned long conf_bgp_debug_graceful_restart; unsigned long term_bgp_debug_as4; unsigned long term_bgp_debug_neighbor_events; @@ -80,6 +81,7 @@ unsigned long term_bgp_debug_vpn; unsigned long term_bgp_debug_flowspec; unsigned long term_bgp_debug_labelpool; unsigned long term_bgp_debug_pbr; +unsigned long term_bgp_debug_graceful_restart; struct list *bgp_debug_neighbor_events_peers = NULL; struct list *bgp_debug_keepalive_peers = NULL; @@ -1644,6 +1646,23 @@ DEFUN (debug_bgp_zebra, return CMD_SUCCESS; } +DEFUN (debug_bgp_graceful_restart, + debug_bgp_graceful_restart_cmd, + "debug bgp graceful-restart", + DEBUG_STR + BGP_STR + GR_DEBUG) +{ + if (vty->node == CONFIG_NODE) { + DEBUG_ON(graceful_restart, GRACEFUL_RESTART); + } else { + TERM_DEBUG_ON(graceful_restart, GRACEFUL_RESTART); + vty_out(vty, "BGP Graceful Restart debugging is on\n"); + } + return CMD_SUCCESS; +} + + DEFUN (debug_bgp_zebra_prefix, debug_bgp_zebra_prefix_cmd, "debug bgp zebra prefix ", @@ -1702,6 +1721,23 @@ DEFUN (no_debug_bgp_zebra, return CMD_SUCCESS; } +DEFUN (no_debug_bgp_graceful_restart, + no_debug_bgp_graceful_restart_cmd, + "no debug bgp graceful-restart", + DEBUG_STR + BGP_STR + GR_DEBUG + NO_STR) +{ + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(graceful_restart, GRACEFUL_RESTART); + } else { + TERM_DEBUG_OFF(graceful_restart, GRACEFUL_RESTART); + vty_out(vty, "BGP Graceful Restart debugging is off\n"); + } + return CMD_SUCCESS; +} + DEFUN (no_debug_bgp_zebra_prefix, no_debug_bgp_zebra_prefix_cmd, "no debug bgp zebra prefix ", @@ -2039,6 +2075,8 @@ DEFUN (no_debug_bgp, TERM_DEBUG_OFF(labelpool, LABELPOOL); TERM_DEBUG_OFF(pbr, PBR); TERM_DEBUG_OFF(pbr, PBR_ERROR); + TERM_DEBUG_OFF(graceful_restart, GRACEFUL_RESTART); + vty_out(vty, "All possible debugging has been turned off\n"); return CMD_SUCCESS; @@ -2094,7 +2132,11 @@ DEFUN_NOSH (show_debugging_bgp, if (BGP_DEBUG(zebra, ZEBRA)) bgp_debug_list_print(vty, " BGP zebra debugging is on", - bgp_debug_zebra_prefixes); + bgp_debug_zebra_prefixes); + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + vty_out(vty, + " BGP graceful-restart debugging is on"); if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) vty_out(vty, " BGP allow martian next hop debugging is on\n"); @@ -2229,6 +2271,11 @@ static int bgp_config_write_debug(struct vty *vty) vty_out(vty, "debug bgp pbr error\n"); write++; } + + if (CONF_BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) { + vty_out(vty, "debug bgp graceful-restart\n"); + write++; + } return write; } @@ -2262,6 +2309,9 @@ void bgp_debug_init(void) install_element(ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd); install_element(CONFIG_NODE, &debug_bgp_bestpath_prefix_cmd); + install_element(ENABLE_NODE, &debug_bgp_graceful_restart_cmd); + install_element(CONFIG_NODE, &debug_bgp_graceful_restart_cmd); + /* debug bgp updates (in|out) */ install_element(ENABLE_NODE, &debug_bgp_update_direct_cmd); install_element(CONFIG_NODE, &debug_bgp_update_direct_cmd); @@ -2327,6 +2377,9 @@ void bgp_debug_init(void) install_element(ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd); install_element(CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_graceful_restart_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_graceful_restart_cmd); + install_element(ENABLE_NODE, &debug_bgp_vpn_cmd); install_element(CONFIG_NODE, &debug_bgp_vpn_cmd); install_element(ENABLE_NODE, &no_debug_bgp_vpn_cmd); diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 9dff8266fa..1e6482e969 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -94,7 +94,6 @@ extern unsigned long term_bgp_debug_labelpool; extern unsigned long term_bgp_debug_pbr; extern unsigned long term_bgp_debug_graceful_restart; - extern struct list *bgp_debug_neighbor_events_peers; extern struct list *bgp_debug_keepalive_peers; extern struct list *bgp_debug_update_in_peers; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 3667dae83d..1f09233c5d 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1076,6 +1076,7 @@ int bgp_stop(struct peer *peer) safi_t safi; char orf_name[BUFSIZ]; int ret = 0; + peer->nsf_af_count = 0; if (peer_dynamic_neighbor(peer) && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { @@ -1647,6 +1648,8 @@ static int bgp_establish(struct peer *peer) } } + peer->nsf_af_count = nsf_af_count; + if (nsf_af_count) SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); else { @@ -2063,3 +2066,387 @@ int bgp_event_update(struct peer *peer, int event) return ret; } +/* BGP GR Code */ + +int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp, + enum global_mode global_new_state, + enum global_mode global_old_state) +{ + struct peer *peer = {0}; + struct listnode *node = {0}; + struct listnode *nnode = {0}; + enum peer_mode peer_old_state = PEER_INVALID; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: %s ---> Peer: (%s) :", + __func__, peer->host); + + peer_old_state = bgp_peer_gr_mode_get(peer); + + if (peer_old_state == PEER_GLOBAL_INHERIT) { + + /* + *Reset only these peers and send a + *new open message with the change capabilities. + *Considering the mode to be "global_new_state" and + *do all operation accordingly + */ + + switch (global_new_state) { + + case GLOBAL_HELPER: + + BGP_PEER_GR_HELPER_ENABLE(peer); + break; + case GLOBAL_GR: + + BGP_PEER_GR_ENABLE(peer); + break; + case GLOBAL_DISABLE: + + BGP_PEER_GR_DISABLE(peer); + break; + case GLOBAL_INVALID: + + zlog_debug( + "BGP_GR:: %s :GLOBAL_INVALID", + __func__); + return BGP_ERR_GR_OPERATION_FAILED; + default: + + zlog_debug( + "BGP_GR:: %s :Global unknown ERROR", + __func__); + return BGP_ERR_GR_OPERATION_FAILED; + } + } + } + + bgp->global_gr_present_state = global_new_state; + + /* debug Trace msg */ + return BGP_GR_SUCCESS; +} + +int bgp_gr_update_all(struct bgp *bgp, int global_GR_Cmd) +{ + enum global_mode global_new_state = GLOBAL_INVALID; + enum global_mode global_old_state = GLOBAL_INVALID; + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR::%s:START ---> global_GR_Cmd :%d:", + __func__, global_GR_Cmd); + + global_old_state = bgp_global_gr_mode_get(bgp); + + if (global_old_state != GLOBAL_INVALID) { + + global_new_state = + bgp->GLOBAL_GR_FSM[global_old_state][global_GR_Cmd]; + } else { + /* Trace msg */ + zlog_debug("BGP_GR::%s:global_old_state == GLOBAL_INVALID", + __func__); + return BGP_ERR_GR_OPERATION_FAILED; + } + + if (global_new_state == GLOBAL_INVALID) { + /* Trace msg */ + zlog_debug( + "BGP_GR::%s: global_new_state == GLOBAL_INVALID", + __func__); + return BGP_ERR_GR_INVALID_CMD; + } + if (global_new_state == global_old_state) { + /* Trace msg */ + zlog_debug( + "BGP_GR::%s : global_new_state == global_old_state", + __func__); + return BGP_GR_NO_OPERATION; + } + + return bgp_gr_lookup_n_update_all_peer(bgp, + global_new_state, + global_old_state); +} + +enum global_mode bgp_global_gr_mode_get(struct bgp *bgp) +{ + return bgp->global_gr_present_state; +} + +enum peer_mode bgp_peer_gr_mode_get(struct peer *peer) +{ + return peer->peer_gr_present_state; +} + +int bgp_neighbor_graceful_restart(struct peer *peer, + int peer_GR_Cmd) +{ + enum peer_mode peer_new_state = PEER_INVALID; + enum peer_mode peer_old_state = PEER_INVALID; + struct bgp_peer_gr peer_state; + int result = BGP_GR_FAILURE; + + /* + * fetch peer_old_state from peer structure also + * fetch global_old_state from bgp structure, + * peer had a back pointer to bgpo struct ; + */ + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: %s:START--->Peer: (%s) : peer_GR_Cmd :%d:", + __func__, peer->host, peer_GR_Cmd); + + peer_old_state = bgp_peer_gr_mode_get(peer); + + if (peer_old_state == PEER_INVALID) { + /* debug Trace msg */ + zlog_debug( + "BGP_GR:: peer_old_state ==Invalid state !"); + return BGP_ERR_GR_OPERATION_FAILED; + } + + peer_state = peer->PEER_GR_FSM[peer_old_state][peer_GR_Cmd]; + peer_new_state = peer_state.next_state; + + if (peer_new_state == PEER_INVALID) { + /* debug Trace msg */ + zlog_debug( + "BGP_GR:: Invalid bgp graceful restart command used !"); + return BGP_ERR_GR_INVALID_CMD; + } + + if (peer_new_state != peer_old_state) { + result = peer_state.action_fun(peer, + peer_old_state, + peer_new_state); + } else { + /* debug Trace msg */ + zlog_debug( + "BGP_GR:: peer_old_state == peer_new_state !"); + return BGP_GR_NO_OPERATION; + } + + if (result == BGP_GR_SUCCESS) { + + /* Update the mode i.e peer_new_state into the peer structure */ + peer->peer_gr_present_state = peer_new_state; + /* debug Trace msg */ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("BGP_GR:: Succesfully change the state of the peer to : %d : !", + peer_new_state); + + return BGP_GR_SUCCESS; + } + + return result; +} + +unsigned int bgp_peer_gr_action(struct peer *peer, + int old_peer_state, int new_peer_state) +{ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: %s : Move peer from old_peer_state :%d: to old_peer_state :%d: !!!!", + __func__, old_peer_state, new_peer_state); + + int bgp_gr_global_mode = GLOBAL_INVALID; + unsigned int ret = BGP_GR_FAILURE; + + if (old_peer_state == new_peer_state) { + /* Nothing to do over here as the present and old state is the same */ + /* debug Trace msg */ + return BGP_GR_NO_OPERATION; + } + if ((old_peer_state == PEER_INVALID) || + (new_peer_state == PEER_INVALID)) { + /* something bad happend , print error message */ + return BGP_ERR_GR_INVALID_CMD; + } + + bgp_gr_global_mode = bgp_global_gr_mode_get(peer->bgp); + + if ((old_peer_state == PEER_GLOBAL_INHERIT) && + (new_peer_state != PEER_GLOBAL_INHERIT)) { + + /* fetch the Mode running in the Global state machine + *from the bgp structure into a variable called + *bgp_gr_global_mode + */ + + /* Here we are checking if the + *1. peer_new_state == global_mode == helper_mode + *2. peer_new_state == global_mode == GR_mode + *3. peer_new_state == global_mode == disabled_mode + */ + + BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer); + + if (new_peer_state == bgp_gr_global_mode) { + /*This is incremental updates i.e no tear down + *of the existing session + *as the peer is already working in the same mode. + */ + /* debug Trace msg */ + ret = BGP_GR_SUCCESS; + } else { + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: Peer state changed from :%d =>", + old_peer_state); + + bgp_peer_move_to_gr_mode(peer, new_peer_state); + + ret = BGP_GR_SUCCESS; + } + } + /* In the case below peer is going into Global inherit mode i.e. + * the peer would work as the mode configured at the global level + */ + else if ((new_peer_state == PEER_GLOBAL_INHERIT) && + (old_peer_state != PEER_GLOBAL_INHERIT)) { + /* Here in this case it would be destructive + * in all the cases except one case when, + * Global GR is configured Disabled + * and present_peer_state is not disable + */ + + BGP_PEER_GR_GLOBAL_INHERIT_SET(peer); + + if (old_peer_state == bgp_gr_global_mode) { + + /* This is incremental updates + *i.e no tear down of the existing session + *as the peer is already working in the same mode. + */ + ret = BGP_GR_SUCCESS; + } else { + /* Destructive always */ + /* Tear down the old session + * and send the new capability + * as per the bgp_gr_global_mode + */ + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("BGP_GR:: Peer state changed from :%d ==>", + old_peer_state); + + bgp_peer_move_to_gr_mode(peer, bgp_gr_global_mode); + + ret = BGP_GR_SUCCESS; + } + } else { + /* + *This else case, it include all the cases except --> + *(new_peer_state != Peer_Global) && + *( old_peer_state != Peer_Global ) + */ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("BGP_GR:: Peer state changed from :%d ===>", + old_peer_state); + + bgp_peer_move_to_gr_mode(peer, new_peer_state); + + ret = BGP_GR_SUCCESS; + } + + return ret; +} + +inline void bgp_peer_move_to_gr_mode(struct peer *peer, int new_state) + +{ + int bgp_global_gr_mode = bgp_global_gr_mode_get(peer->bgp); + + switch (new_state) { + + case PEER_HELPER: + BGP_PEER_GR_HELPER_ENABLE(peer); + break; + + case PEER_GR: + BGP_PEER_GR_ENABLE(peer); + break; + + case PEER_DISABLE: + BGP_PEER_GR_DISABLE(peer); + break; + + case PEER_GLOBAL_INHERIT: + BGP_PEER_GR_GLOBAL_INHERIT_SET(peer); + + if (bgp_global_gr_mode == GLOBAL_HELPER) { + BGP_PEER_GR_HELPER_ENABLE(peer); + } else if (bgp_global_gr_mode == GLOBAL_GR) { + BGP_PEER_GR_ENABLE(peer); + } else if (bgp_global_gr_mode == GLOBAL_DISABLE) { + BGP_PEER_GR_DISABLE(peer); + } else { + zlog_debug( + "BGP_GR:: Default switch inherit mode ::: SOMETHING IS WORONG !!!"); + } + break; + default: + zlog_debug("BGP_GR:: Default switch mode ::: SOMETHING IS WORONG !!!"); + break; + } + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("BGP_GR:: Peer state changed --to--> : %d : !", + new_state); +} + +void bgp_peer_gr_flags_update(struct peer *peer) +{ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: %s called !", + __func__); + if (CHECK_FLAG(peer->peer_gr_new_status_flag, + PEER_GRACEFUL_RESTART_NEW_STATE_HELPER)) + bgp_peer_flag_set(peer, + PEER_FLAG_GRACEFUL_RESTART_HELPER); + else + bgp_peer_flag_unset(peer, + PEER_FLAG_GRACEFUL_RESTART_HELPER); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_HELPER : %s : !", + peer->host, + (bgp_peer_flag_check(peer, + PEER_FLAG_GRACEFUL_RESTART_HELPER) ? + "Set" : "UnSet")); + if (CHECK_FLAG(peer->peer_gr_new_status_flag, + PEER_GRACEFUL_RESTART_NEW_STATE_RESTART)) + bgp_peer_flag_set(peer, + PEER_FLAG_GRACEFUL_RESTART); + else + bgp_peer_flag_unset(peer, + PEER_FLAG_GRACEFUL_RESTART); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: Peer %s Flag PEER_FLAG_GRACEFUL_RESTART : %s : !", + peer->host, + (bgp_peer_flag_check(peer, + PEER_FLAG_GRACEFUL_RESTART) ? + "Set" : "UnSet")); + if (CHECK_FLAG(peer->peer_gr_new_status_flag, + PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT)) + bgp_peer_flag_set(peer, + PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT); + else + bgp_peer_flag_unset(peer, + PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: Peer %s Flag PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT : %s : !", + peer->host, + (bgp_peer_flag_check(peer, + PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT) ? + "Set" : "UnSet")); +} diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index da415db64c..8a25d1b29e 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -66,8 +66,6 @@ PEER_GRACEFUL_RESTART_NEW_STATE_HELPER);\ } while (0) - - #define BGP_PEER_GR_ENABLE(peer)\ do { \ SET_FLAG( \ @@ -78,7 +76,6 @@ PEER_GRACEFUL_RESTART_NEW_STATE_HELPER);\ } while (0) - #define BGP_PEER_GR_DISABLE(peer)\ do { \ UNSET_FLAG( \ @@ -89,17 +86,14 @@ PEER_GRACEFUL_RESTART_NEW_STATE_HELPER);\ } while (0) - #define BGP_PEER_GR_GLOBAL_INHERIT_SET(peer) \ SET_FLAG(peer->peer_gr_new_status_flag, \ PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT) - #define BGP_PEER_GR_GLOBAL_INHERIT_UNSET(peer) \ UNSET_FLAG(peer->peer_gr_new_status_flag, \ PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT) - /* Prototypes. */ extern void bgp_fsm_event_update(struct peer *peer, int valid); extern int bgp_event(struct thread *); @@ -151,9 +145,8 @@ unsigned int bgp_peer_gr_global_inherit_unset(struct peer *peer); int bgp_gr_lookup_n_update_all_peer(struct bgp *bgp, enum global_mode global_new_state, enum global_mode global_old_state); - void bgp_peer_gr_flags_update(struct peer *peer); -extern int bgp_peer_flag_unset(struct peer *peer, int flag_bit); -extern int bgp_peer_flag_set(struct peer *peer, int flag_bit); +extern void bgp_peer_flag_unset(struct peer *peer, int flag_bit); +extern void bgp_peer_flag_set(struct peer *peer, int flag_bit); #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index e1109841d2..3f60c7719c 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -46,8 +46,6 @@ struct bgp; "Address Family modifier\n" \ "Address Family modifier\n" - - #define SHOW_GR_HEADER \ "Codes: GR - Graceful Restart," \ " * - Inheriting Global GR Config,\n" \ @@ -70,8 +68,6 @@ struct bgp; vty, p, use_json, json); \ } while (0) - - extern void bgp_vty_init(void); extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json); extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9b0e81491a..05e5822c8c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1102,6 +1102,117 @@ struct peer *peer_unlock_with_caller(const char *name, struct peer *peer) return peer; } +/* BGP GR changes */ + +int bgp_global_gr_init(struct bgp *bgp) +{ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s called ..", __func__); + + int local_GLOBAL_GR_FSM[GLOBAL_MODE][EVENT_CMD] = { + /* GLOBAL_HELPER Mode */ + { + /*Event -> */ + /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/ + GLOBAL_GR, GLOBAL_INVALID, + /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/ + GLOBAL_DISABLE, GLOBAL_INVALID + }, + /* GLOBAL_GR Mode */ + { + /*Event -> */ + /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/ + GLOBAL_INVALID, GLOBAL_HELPER, + /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/ + GLOBAL_DISABLE, GLOBAL_INVALID + }, + /* GLOBAL_DISABLE Mode */ + { + /*Event -> */ + /*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/ + GLOBAL_GR, GLOBAL_INVALID, + /*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/ + GLOBAL_INVALID, GLOBAL_HELPER + }, + /* GLOBAL_INVALID Mode */ + { + /*Event -> */ + /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/ + GLOBAL_INVALID, GLOBAL_INVALID, + /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/ + GLOBAL_INVALID, GLOBAL_INVALID + } + }; + memcpy(bgp->GLOBAL_GR_FSM, local_GLOBAL_GR_FSM, + sizeof(local_GLOBAL_GR_FSM)); + + bgp->global_gr_present_state = GLOBAL_HELPER; + + return BGP_GR_SUCCESS; +} + +int bgp_peer_gr_init(struct peer *peer) +{ + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s called ..", __func__); + + struct bgp_peer_gr local_Peer_GR_FSM[PEER_MODE][PEER_EVENT_CMD] = { + { + /* PEER_HELPER Mode */ + /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ + { PEER_GR, bgp_peer_gr_action }, {PEER_INVALID, NULL }, + /* Event-> */ /* PEER_DISABLE_cmd */ /* NO_PEER_DISABLE_CMD */ + {PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL }, + /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ + { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT, + bgp_peer_gr_action } + }, + { + /* PEER_GR Mode */ + /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ + { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + bgp_peer_gr_action }, + /* Event-> */ /* PEER_DISABLE_cmd */ /* NO_PEER_DISABLE_CMD */ + {PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ + { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } + }, + { + /* PEER_DISABLE Mode */ + /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ + { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_DISABLE_cmd */ /* NO_PEER_DISABLE_CMD */ + { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + bgp_peer_gr_action }, + /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ + { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } + }, + { + /* PEER_INVALID Mode */ + /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ + { PEER_INVALID, NULL }, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_DISABLE_cmd */ /* NO_PEER_DISABLE_CMD */ + { PEER_INVALID, NULL }, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ + { PEER_INVALID, NULL }, { PEER_INVALID, NULL }, + }, + { + /* PEER_GLOBAL_INHERIT Mode */ + /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ + { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_DISABLE_cmd */ /* NO_PEER_DISABLE_CMD */ + { PEER_DISABLE, bgp_peer_gr_action}, { PEER_INVALID, NULL }, + /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ + { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } + } + }; + memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM, + sizeof(local_Peer_GR_FSM)); + peer->peer_gr_present_state = PEER_GLOBAL_INHERIT; + bgp_peer_move_to_gr_mode(peer, PEER_GLOBAL_INHERIT); + + return BGP_GR_SUCCESS; +} /* Allocate new peer object, implicitely locked. */ struct peer *peer_new(struct bgp *bgp) @@ -1153,6 +1264,9 @@ struct peer *peer_new(struct bgp *bgp) SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); + /* Initialize per peer bgp GR FSM */ + bgp_peer_gr_init(peer); + /* Create buffers. */ peer->ibuf = stream_fifo_new(); peer->obuf = stream_fifo_new(); @@ -1534,6 +1648,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, else if (!active && peer_active(peer)) bgp_timer_set(peer); + bgp_peer_gr_flags_update(peer); return peer; } @@ -2990,6 +3105,9 @@ static struct bgp *bgp_create(as_t *as, const char *name, bgp_evpn_init(bgp); bgp_pbr_init(bgp); + + /*initilize global GR FSM */ + bgp_global_gr_init(bgp); return bgp; } @@ -7099,3 +7217,35 @@ struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, return peer; } + +/* BGP peer flag manipulation. */ +void bgp_peer_flag_set(struct peer *peer, int flag) +{ + SET_FLAG(peer->flags, flag); +} + +void bgp_peer_flag_unset(struct peer *peer, int flag) +{ + UNSET_FLAG(peer->flags, flag); +} + +int bgp_peer_flag_check(struct peer *peer, int flag) +{ + return CHECK_FLAG(peer->flags, flag); +} + +void bgp_gr_apply_running_config(void) +{ + struct peer *peer = NULL; + struct bgp *bgp = NULL; + struct listnode *node, *nnode; + + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug( + "BGP_GR:: %s called !", + __func__); + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + bgp_peer_gr_flags_update(peer); +} diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index b0fe7b912a..028f1179cf 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -238,7 +238,6 @@ enum bgp_instance_type { #define GLOBAL_MODE 4 #define EVENT_CMD 4 - /* Graceful restart selection deferral timer info */ struct graceful_restart_info { /* Count of EOR message expected */ @@ -253,7 +252,6 @@ struct graceful_restart_info { struct thread *t_route_select; }; - enum global_mode { GLOBAL_HELPER = 0, /* This is the default mode */ GLOBAL_GR, @@ -271,7 +269,6 @@ enum global_gr_command { #define BGP_GR_SUCCESS 0 #define BGP_GR_FAILURE 1 - /* BGP instance structure. */ struct bgp { /* AS number of this BGP instance. */ @@ -777,7 +774,6 @@ struct peer_af { }; /* BGP GR per peer ds */ - #define PEER_MODE 5 #define PEER_EVENT_CMD 6 @@ -1046,7 +1042,7 @@ struct peer { uint8_t peer_gr_new_status_flag; #define PEER_GRACEFUL_RESTART_NEW_STATE_HELPER (1 << 0) #define PEER_GRACEFUL_RESTART_NEW_STATE_RESTART (1 << 1) -#define PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT (1 << 2) +#define PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT (1 << 2) /* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */ char *tx_shutdown_message; @@ -1076,8 +1072,7 @@ struct peer { #define PEER_FLAG_DEFAULT_ORIGINATE (1 << 9) /* default-originate */ #define PEER_FLAG_REMOVE_PRIVATE_AS (1 << 10) /* remove-private-as */ #define PEER_FLAG_ALLOWAS_IN (1 << 11) /* set allowas-in */ -/* orf capability send-mode */ -#define PEER_FLAG_ORF_PREFIX_SM (1 << 12) +#define PEER_FLAG_ORF_PREFIX_SM (1 << 12) /* orf capability send-mode */ #define PEER_FLAG_ORF_PREFIX_RM (1 << 13) /* orf capability receive-mode */ #define PEER_FLAG_MAX_PREFIX (1 << 14) /* maximum prefix */ #define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */ @@ -1624,7 +1619,6 @@ enum bgp_clear_type { #define BGP_ERR_PEER_SAFI_CONFLICT -35 /* BGP GR ERRORS */ - #define BGP_ERR_GR_INVALID_CMD -36 #define BGP_ERR_GR_OPERATION_FAILED -37 #define BGP_GR_NO_OPERATION -38 @@ -1884,9 +1878,8 @@ extern void bgp_free(struct bgp *); void bgp_gr_apply_running_config(void); /* BGP GR */ - -int bgp_peer_flag_set(struct peer *peer, int flag_bit); -int bgp_peer_flag_unset(struct peer *peer, int flag_bit); +void bgp_peer_flag_set(struct peer *peer, int flag_bit); +void bgp_peer_flag_unset(struct peer *peer, int flag_bit); int bgp_peer_flag_check(struct peer *peer, int flag_bit); int bgp_global_gr_init(struct bgp *bgp); int bgp_peer_gr_init(struct peer *peer); diff --git a/lib/command.h b/lib/command.h index ca2ff1d5fb..ea8a76a964 100644 --- a/lib/command.h +++ b/lib/command.h @@ -419,7 +419,6 @@ struct cmd_node { "" /* Graceful Restart cli help strings */ - #define GR_CMD "Global Graceful Restart command\n" #define NO_GR_CMD "Undo Global Graceful Restart command\n" #define GR "Global Graceful Restart - GR Mode\n" @@ -434,7 +433,6 @@ struct cmd_node { #define GR_NEIGHBOR_HELPER_CMD "Graceful Restart Helper command for a neighbor\n" #define NO_GR_NEIGHBOR_HELPER_CMD "Undo Graceful Restart Helper command for a neighbor\n" - /* Prototypes. */ extern void install_node(struct cmd_node *node, int (*)(struct vty *)); extern void install_default(enum node_type); -- 2.39.5