]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_fsm.c
Merge pull request #3394 from karamalla0406/frr3360
[mirror_frr.git] / bgpd / bgp_fsm.c
index dc51aa981d1eb63536ce479fcf55f1b179c4e6c5..b70c8bbd631cb88b2cf55b12838185ade095d858 100644 (file)
@@ -34,6 +34,7 @@
 #include "queue.h"
 #include "filter.h"
 #include "command.h"
+#include "lib_errors.h"
 
 #include "lib/json.h"
 #include "bgpd/bgpd.h"
@@ -124,6 +125,20 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
        if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
                return from_peer;
 
+       /*
+        * Let's check that we are not going to loose known configuration
+        * state based upon doppelganger rules.
+        */
+       FOREACH_AFI_SAFI (afi, safi) {
+               if (from_peer->afc[afi][safi] != peer->afc[afi][safi]) {
+                       flog_err(
+                               EC_BGP_DOPPELGANGER_CONFIG,
+                               "from_peer->afc[%d][%d] is not the same as what we are overwriting",
+                               afi, safi);
+                       return NULL;
+               }
+       }
+
        if (bgp_debug_neighbor_events(peer))
                zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)",
                           from_peer->host, from_peer, from_peer->fd, peer,
@@ -165,8 +180,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
                 * runs in our pthread.
                 */
                if (peer->curr) {
-                       zlog_ferr(
-                               BGP_ERR_PKT_PROCESS,
+                       flog_err(
+                               EC_BGP_PKT_PROCESS,
                                "[%s] Dropping pending packet on connection transfer:",
                                peer->host);
                        uint16_t type = stream_getc_from(peer->curr,
@@ -244,8 +259,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
        }
 
        if (bgp_getsockname(peer) < 0) {
-               zlog_ferr(
-                       BGP_ERR_SOCKET,
+               flog_err(
+                       EC_LIB_SOCKET,
                        "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
                        (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)
                                 ? "accept"
@@ -257,8 +272,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
        }
        if (from_peer->status > Active) {
                if (bgp_getsockname(from_peer) < 0) {
-                       zlog_ferr(
-                               BGP_ERR_SOCKET,
+                       flog_err(
+                               EC_LIB_SOCKET,
                                "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
 
                                (CHECK_FLAG(from_peer->sflags,
@@ -916,13 +931,33 @@ static void bgp_update_delay_process_status_change(struct peer *peer)
        }
 }
 
-/* Called after event occured, this function change status and reset
+/* Called after event occurred, this function change status and reset
    read/write and timer thread. */
 void bgp_fsm_change_status(struct peer *peer, int status)
 {
+       struct bgp *bgp;
+       uint32_t peer_count;
 
        bgp_dump_state(peer, peer->status, status);
 
+       bgp = peer->bgp;
+       peer_count = bgp->established_peers;
+
+       if (status == Established)
+               bgp->established_peers++;
+       else if ((peer->status == Established) && (status != Established))
+               bgp->established_peers--;
+
+       if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS))
+               zlog_debug("%s : vrf %u, established_peers %u", __func__,
+                               bgp->vrf_id, bgp->established_peers);
+       /* Set to router ID to the value provided by RIB if there are no peers
+        * in the established state and peer count did not change
+        */
+       if ((peer_count != bgp->established_peers) &&
+           (bgp->established_peers == 0))
+               bgp_router_id_zebra_bump(bgp->vrf_id, NULL);
+
        /* Transition into Clearing or Deleted must /always/ clear all routes..
         * (and must do so before actually changing into Deleted..
         */
@@ -1028,8 +1063,9 @@ int bgp_stop(struct peer *peer)
                                "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s",
                                peer->host,
                                (peer->hostname) ? peer->hostname : "Unknown",
-                               vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
-                                                                   : "Default")
+                               vrf ? ((vrf->vrf_id != VRF_DEFAULT)
+                                               ? vrf->name
+                                               : VRF_DEFAULT_NAME)
                                    : "",
                                peer_down_str[(int)peer->last_reset]);
                }
@@ -1285,17 +1321,17 @@ static int bgp_connect_check(struct thread *thread)
 static int bgp_connect_success(struct peer *peer)
 {
        if (peer->fd < 0) {
-               zlog_ferr(BGP_ERR_CONNECT,
-                         "bgp_connect_success peer's fd is negative value %d",
-                         peer->fd);
+               flog_err(EC_BGP_CONNECT,
+                        "bgp_connect_success peer's fd is negative value %d",
+                        peer->fd);
                bgp_stop(peer);
                return -1;
        }
 
        if (bgp_getsockname(peer) < 0) {
-               zlog_ferr(BGP_ERR_SOCKET,
-                         "%s: bgp_getsockname(): failed for peer %s, fd %d",
-                         __FUNCTION__, peer->host, peer->fd);
+               flog_err_sys(EC_LIB_SOCKET,
+                            "%s: bgp_getsockname(): failed for peer %s, fd %d",
+                            __FUNCTION__, peer->host, peer->fd);
                bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR,
                                0); /* internal error */
                bgp_writes_on(peer);
@@ -1353,10 +1389,10 @@ int bgp_start(struct peer *peer)
 
        if (BGP_PEER_START_SUPPRESSED(peer)) {
                if (bgp_debug_neighbor_events(peer))
-                       zlog_ferr(BGP_ERR_FSM,
-                                 "%s [FSM] Trying to start suppressed peer"
-                                 " - this is never supposed to happen!",
-                                 peer->host);
+                       flog_err(EC_BGP_FSM,
+                                "%s [FSM] Trying to start suppressed peer"
+                                " - this is never supposed to happen!",
+                                peer->host);
                return -1;
        }
 
@@ -1388,8 +1424,8 @@ int bgp_start(struct peer *peer)
 
        if (peer->bgp->vrf_id == VRF_UNKNOWN) {
                if (bgp_debug_neighbor_events(peer))
-                       zlog_ferr(
-                               BGP_ERR_FSM,
+                       flog_err(
+                               EC_BGP_FSM,
                                "%s [FSM] In a VRF that is not initialised yet",
                                peer->host);
                return -1;
@@ -1443,9 +1479,9 @@ int bgp_start(struct peer *peer)
                                "%s [FSM] Non blocking connect waiting result, fd %d",
                                peer->host, peer->fd);
                if (peer->fd < 0) {
-                       zlog_ferr(BGP_ERR_FSM,
-                                 "bgp_start peer's fd is negative value %d",
-                                 peer->fd);
+                       flog_err(EC_BGP_FSM,
+                                "bgp_start peer's fd is negative value %d",
+                                peer->fd);
                        return -1;
                }
                /*
@@ -1491,9 +1527,8 @@ static int bgp_fsm_open(struct peer *peer)
    peer and change to Idle status. */
 static int bgp_fsm_event_error(struct peer *peer)
 {
-       zlog_ferr(BGP_ERR_FSM,
-                 "%s [FSM] unexpected packet received in state %s", peer->host,
-                 lookup_msg(bgp_status_msg, peer->status, NULL));
+       flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s",
+                peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
 
        return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0);
 }
@@ -1525,7 +1560,7 @@ static int bgp_establish(struct peer *peer)
        other = peer->doppelganger;
        peer = peer_xfer_conn(peer);
        if (!peer) {
-               zlog_ferr(BGP_ERR_CONNECT, "%%Neighbor failed in xfer_conn");
+               flog_err(EC_BGP_CONNECT, "%%Neighbor failed in xfer_conn");
                return -1;
        }
 
@@ -1550,8 +1585,9 @@ static int bgp_establish(struct peer *peer)
                zlog_info("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up",
                          peer->host,
                          (peer->hostname) ? peer->hostname : "Unknown",
-                         vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name
-                                                             : "Default")
+                         vrf ? ((vrf->vrf_id != VRF_DEFAULT)
+                                       ? vrf->name
+                                       : VRF_DEFAULT_NAME)
                              : "");
        }
        /* assign update-group/subgroup */
@@ -1663,6 +1699,15 @@ static int bgp_establish(struct peer *peer)
                        peer_delete(peer->doppelganger);
        }
 
+       /*
+        * If we are replacing the old peer for a doppelganger
+        * then switch it around in the bgp->peerhash
+        * the doppelgangers su and this peer's su are the same
+        * so the hash_release is the same for either.
+        */
+       hash_release(peer->bgp->peerhash, peer);
+       hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
+
        bgp_bfd_register_peer(peer);
        return ret;
 }
@@ -1684,8 +1729,8 @@ static int bgp_fsm_update(struct peer *peer)
 /* This is empty event. */
 static int bgp_ignore(struct peer *peer)
 {
-       zlog_ferr(
-               BGP_ERR_FSM,
+       flog_err(
+               EC_BGP_FSM,
                "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d",
                peer->host, bgp_event_str[peer->cur_event],
                lookup_msg(bgp_status_msg, peer->status, NULL),
@@ -1697,8 +1742,8 @@ static int bgp_ignore(struct peer *peer)
 /* This is to handle unexpected events.. */
 static int bgp_fsm_exeption(struct peer *peer)
 {
-       zlog_ferr(
-               BGP_ERR_FSM,
+       flog_err(
+               EC_BGP_FSM,
                "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d",
                peer->host, bgp_event_str[peer->cur_event],
                lookup_msg(bgp_status_msg, peer->status, NULL),
@@ -1972,8 +2017,8 @@ int bgp_event_update(struct peer *peer, int event)
                 * code.
                 */
                if (!dyn_nbr && !passive_conn && peer->bgp) {
-                       zlog_ferr(
-                               BGP_ERR_FSM,
+                       flog_err(
+                               EC_BGP_FSM,
                                "%s [FSM] Failure handling event %s in state %s, "
                                "prior events %s, %s, fd %d",
                                peer->host, bgp_event_str[peer->cur_event],