]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Adding BGP GR Global & Per Neighbour FSM changes
authorbisdhdh <biswajit.sadhu@gmail.com>
Wed, 23 Oct 2019 05:40:22 +0000 (11:10 +0530)
committerbisdhdh <biswajit.sadhu@gmail.com>
Thu, 23 Jan 2020 04:04:25 +0000 (09:34 +0530)
 * 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 <sadhub@vmware.com>
bgpd/bgp_debug.c
bgpd/bgp_debug.h
bgpd/bgp_fsm.c
bgpd/bgp_fsm.h
bgpd/bgp_vty.h
bgpd/bgpd.c
bgpd/bgpd.h
lib/command.h

index f716c4f308654beb7d7ee8d2275597262b173f17..498a871ce7e9ac6834be0ee562ede3ea20dcf209 100644 (file)
@@ -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 <A.B.C.D/M|X:X::X:X/M>",
@@ -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 <A.B.C.D/M|X:X::X:X/M>",
@@ -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);
index 9dff8266fa68647357be60f2b117f4184b76c350..1e6482e9693672c80804924350610ca96ab3ce61 100644 (file)
@@ -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;
index 3667dae83d164df70054b335843b00fb08e4416f..1f09233c5d7c946d1414c60218221a8aa458dd93 100644 (file)
@@ -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"));
+}
index da415db64c488c3fd867e1134a2d8aa065c17134..8a25d1b29e66a6f6828b2829533d952526cc3d65 100644 (file)
@@ -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( \
                        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 */
index e1109841d2b41c1578c7ccfedfa5f1338087f633..3f60c7719c2dccb030895d7c477f79229108612c 100644 (file)
@@ -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,
index 9b0e81491a89bebc63f785bf963c2ebf93b744c8..05e5822c8c84d7ee33fd3d215cb8a7c93ea75037 100644 (file)
@@ -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);
+}
index b0fe7b912a236c7152a6b1e8cd2e507e90bef55e..028f1179cfe37c284a531ae4499983da1488037f 100644 (file)
@@ -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);
index ca2ff1d5fb87e7712b1b9ac1a58f002b20e30b61..ea8a76a964f73881650b59a88a59f6976c5bc643 100644 (file)
@@ -419,7 +419,6 @@ struct cmd_node {
        "<zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd|fabricd|pimd|staticd|sharpd|vrrpd|ldpd>"
 
 /* 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);