bgpd: Add clear command to force a bestpath recalculation and re-advertisement of a prefix
Add these commands to bgp:
clear ip bgp prefix A.B.C.D/M
clear bgp ipv6 (unicast|multicast) prefix X:X::X:X/M
These two commands forces a bestpath calculation to happen again if
necessary to re-advertise the prefix.
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 17b87f4..48645cf 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1602,7 +1602,8 @@
new_select = old_and_new.new;
/* Nothing to do. */
- if (old_select && old_select == new_select)
+ if (old_select && old_select == new_select
+ && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR))
{
if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
{
@@ -1616,6 +1617,9 @@
}
}
+ /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set */
+ UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
+
if (old_select)
bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 3b4e6cf..8e963ae 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -65,6 +65,7 @@
u_char flags;
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
+#define BGP_NODE_USER_CLEAR (1 << 1)
};
/*
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 4c1de16..406ecb1 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -4680,6 +4680,87 @@
return CMD_SUCCESS;
}
+/* Recalculate bestpath and re-advertise a prefix */
+static int
+bgp_clear_prefix (struct vty *vty, char *view_name, const char *ip_str,
+ afi_t afi, safi_t safi, struct prefix_rd *prd)
+{
+ int ret;
+ struct prefix match;
+ struct bgp_node *rn;
+ struct bgp_node *rm;
+ struct bgp *bgp;
+ struct bgp_table *table;
+ struct bgp_table *rib;
+
+ /* BGP structure lookup. */
+ if (view_name)
+ {
+ bgp = bgp_lookup_by_name (view_name);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "%% Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ bgp = bgp_get_default ();
+ if (bgp == NULL)
+ {
+ vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ /* Check IP address argument. */
+ ret = str2prefix (ip_str, &match);
+ if (! ret)
+ {
+ vty_out (vty, "%% address is malformed%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ match.family = afi2family (afi);
+ rib = bgp->rib[afi][safi];
+
+ if (safi == SAFI_MPLS_VPN)
+ {
+ for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
+ {
+ if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+ continue;
+
+ if ((table = rn->info) != NULL)
+ {
+ if ((rm = bgp_node_match (table, &match)) != NULL)
+ {
+ if (rm->p.prefixlen == match.prefixlen)
+ {
+ SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR);
+ bgp_process (bgp, rm, afi, safi);
+ }
+ bgp_unlock_node (rm);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((rn = bgp_node_match (rib, &match)) != NULL)
+ {
+ if (rn->p.prefixlen == match.prefixlen)
+ {
+ SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR);
+ bgp_process (bgp, rn, afi, safi);
+ }
+ bgp_unlock_node (rn);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
static int
bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi,
enum clear_sort sort, enum bgp_clear_type stype,
@@ -4842,6 +4923,27 @@
"Address family\n"
"Clear all external peers\n")
+DEFUN (clear_ip_bgp_prefix,
+ clear_ip_bgp_prefix_cmd,
+ "clear ip bgp prefix A.B.C.D/M",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ "Clear bestpath and re-advertise\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+ return bgp_clear_prefix (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL);
+}
+
+ALIAS (clear_ip_bgp_prefix,
+ clear_bgp_prefix_cmd,
+ "clear bgp prefix A.B.C.D/M",
+ CLEAR_STR
+ BGP_STR
+ "Clear bestpath and re-advertise\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
+
DEFUN (clear_ip_bgp_as,
clear_ip_bgp_as_cmd,
"clear ip bgp " CMD_AS_RANGE,
@@ -5072,6 +5174,22 @@
"Clear all peers\n"
"Soft reconfig outbound update\n")
+DEFUN (clear_bgp_ipv6_safi_prefix,
+ clear_bgp_ipv6_safi_prefix_cmd,
+ "clear bgp ipv6 (unicast|multicast) prefix X:X::X:X/M",
+ CLEAR_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family Modifier\n"
+ "Clear bestpath and re-advertise\n"
+ "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL);
+ else
+ return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL);
+}
+
DEFUN (clear_ip_bgp_peer_soft_out,
clear_ip_bgp_peer_soft_out_cmd,
"clear ip bgp A.B.C.D soft out",
@@ -10909,6 +11027,10 @@
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_prefix_filter_cmd);
+ /* clear ip bgp prefix */
+ install_element (ENABLE_NODE, &clear_ip_bgp_prefix_cmd);
+ install_element (ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd);
+
/* "clear ip bgp neighbor soft out" */
install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_out_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_out_cmd);