From 7fbf0204d9f86a5fc48f88ab934fff0fa8741d15 Mon Sep 17 00:00:00 2001 From: Pascal Mathis Date: Mon, 14 May 2018 22:52:31 +0200 Subject: [PATCH] bgpd: Respect AFI/SAFI when hard-clearing a peer The current implementation does not respect the AFI+SAFI combination of a peer when executing a non-soft (hard) clear. An example would be the command `clear bgp ipv4 unicast *`, which will clear all BGP peers, even those that do not have IPv4-Unicast activated. This commit fixes that behavior by applying the same rules to both soft and hard clear commands, so that peers without a matching AFI+SAFI combination will be no longer modified. Additionally, this commit adds warning messages to all `clear bgp [] [] ` commands when no matching peers with the given AFI+SAFI combination could be found. Both existing and new warning messages have been extended to also mention the AFI+SAFI combination that is missing, which is more helpful to the user than a generic expression 'No peer configured'. Signed-off-by: Pascal Mathis (cherry picked from commit 3ae8bfa5d870d103325cf879a501758e217c6a89) --- bgpd/bgp_vty.c | 78 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 9a80042a98..d44e3e9600 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -553,39 +553,46 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, const char *arg) { int ret; + bool found = false; struct peer *peer; struct listnode *node, *nnode; /* Clear all neighbors. */ /* * Pass along pointer to next node to peer_clear() when walking all - * nodes - * on the BGP instance as that may get freed if it is a doppelganger + * nodes on the BGP instance as that may get freed if it is a + * doppelganger */ if (sort == clear_all) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!peer->afc[afi][safi]) + continue; + if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, &nnode); - else if (peer->afc[afi][safi]) - ret = peer_clear_soft(peer, afi, safi, stype); else - ret = 0; + ret = peer_clear_soft(peer, afi, safi, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); + else + found = true; } /* This is to apply read-only mode on this clear. */ if (stype == BGP_CLEAR_SOFT_NONE) bgp->update_delay_over = 0; + if (!found) + vty_out(vty, "%%BGP: No %s peer configured", + afi_safi_print(afi, safi)); + return CMD_SUCCESS; } - /* Clear specified neighbors. */ + /* Clear specified neighbor. */ if (sort == clear_peer) { union sockunion su; - int ret; /* Make sockunion for lookup. */ ret = str2sockunion(arg, &su); @@ -610,7 +617,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } } - if (stype == BGP_CLEAR_SOFT_NONE) + if (!peer->afc[afi][safi]) + ret = BGP_ERR_AF_UNCONFIGURED; + else if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, NULL); else ret = peer_clear_soft(peer, afi, safi, stype); @@ -621,7 +630,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, return CMD_SUCCESS; } - /* Clear all peer-group members. */ + /* Clear all neighbors belonging to a specific peer-group. */ if (sort == clear_group) { struct peer_group *group; @@ -632,27 +641,37 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { - if (stype == BGP_CLEAR_SOFT_NONE) { - peer_clear(peer, NULL); - continue; - } - if (!peer->afc[afi][safi]) continue; - ret = peer_clear_soft(peer, afi, safi, stype); + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, NULL); + else + ret = peer_clear_soft(peer, afi, safi, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); + else + found = true; } + + if (!found) + vty_out(vty, + "%%BGP: No %s peer belonging to peer-group %s is configured\n", + afi_safi_print(afi, safi), arg); + return CMD_SUCCESS; } + /* Clear all external (eBGP) neighbors. */ if (sort == clear_external) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->sort == BGP_PEER_IBGP) continue; + if (!peer->afc[afi][safi]) + continue; + if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, &nnode); else @@ -660,33 +679,44 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); + else + found = true; } + + if (!found) + vty_out(vty, + "%%BGP: No external %s peer is configured\n", + afi_safi_print(afi, safi)); + return CMD_SUCCESS; } + /* Clear all neighbors belonging to a specific AS. */ if (sort == clear_as) { - as_t as; - int find = 0; - - as = strtoul(arg, NULL, 10); + as_t as = strtoul(arg, NULL, 10); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->as != as) continue; - find = 1; - if (stype == BGP_CLEAR_SOFT_NONE) + if (!peer->afc[afi][safi]) + ret = BGP_ERR_AF_UNCONFIGURED; + else if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, &nnode); else ret = peer_clear_soft(peer, afi, safi, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); + else + found = true; } - if (!find) + + if (!found) vty_out(vty, - "%%BGP: No peer is configured with AS %s\n", - arg); + "%%BGP: No %s peer is configured with AS %s\n", + afi_safi_print(afi, safi), arg); + return CMD_SUCCESS; } -- 2.39.5