diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 65b8b5bd2d..d17426e3ff 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1677,6 +1677,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; } diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index d56fdd75ce..191b1641b2 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -406,7 +406,6 @@ static int bgp_accept(struct thread *thread) peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, peer1->as, peer1->as_type, 0, 0, NULL); - peer->su = su; hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 739c6fc0ed..91f3eaa30d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -11323,6 +11323,36 @@ DEFUN (clear_ip_bgp_dampening_address_mask, NULL, 0); } +static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg) +{ + struct vty *vty = arg; + struct peer *peer = backet->data; + char buf[SU_ADDRSTRLEN]; + + vty_out(vty, "\tPeer: %s %s\n", peer->host, + sockunion2str(&peer->su, buf, sizeof(buf))); +} + +DEFUN (show_bgp_peerhash, + show_bgp_peerhash_cmd, + "show bgp peerhash", + SHOW_STR + BGP_STR + "Display information about the BGP peerhash\n") +{ + struct list *instances = bm->bgp; + struct listnode *node; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) { + vty_out(vty, "BGP: %s\n", bgp->name); + hash_iterate(bgp->peerhash, show_bgp_peerhash_entry, + vty); + } + + return CMD_SUCCESS; +} + /* also used for encap safi */ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) @@ -11717,6 +11747,7 @@ void bgp_route_init(void) /* show bgp ipv4 flowspec detailed */ install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd); + install_element(VIEW_NODE, &show_bgp_peerhash_cmd); } void bgp_route_finish(void) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d7bae007e1..922db96079 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2835,7 +2835,7 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if, peer = peer_lookup_by_conf_if(bgp, conf_if); if (peer) { if (as_str) - ret = peer_remote_as(bgp, &su, conf_if, &as, as_type, + ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type, afi, safi); } else { if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 0300485e91..ed065c55fa 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1422,7 +1422,15 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) } } -/* Create new BGP peer. */ +/* + * Create new BGP peer. + * + * conf_if and su are mutually exclusive if configuring from the cli. + * If we are handing a doppelganger, then we *must* pass in both + * the original peer's su and conf_if, so that we can appropriately + * track the bgp->peerhash( ie we don't want to remove the current + * one from the config ). + */ struct peer *peer_create(union sockunion *su, const char *conf_if, struct bgp *bgp, as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi, @@ -1435,7 +1443,10 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, peer = peer_new(bgp); if (conf_if) { peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if); - bgp_peer_conf_if_to_su_update(peer); + if (su) + peer->su = *su; + else + bgp_peer_conf_if_to_su_update(peer); if (peer->host) XFREE(MTYPE_BGP_PEER_HOST, peer->host); peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);