mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 01:43:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2744 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2744 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* BGP-4, BGP-4+ packet debug routine
 | 
						|
 * Copyright (C) 1996, 97, 99 Kunihiro Ishiguro
 | 
						|
 *
 | 
						|
 * This file is part of GNU Zebra.
 | 
						|
 *
 | 
						|
 * GNU Zebra is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms of the GNU General Public License as published by the
 | 
						|
 * Free Software Foundation; either version 2, or (at your option) any
 | 
						|
 * later version.
 | 
						|
 *
 | 
						|
 * GNU Zebra is distributed in the hope that it will be useful, but
 | 
						|
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License along
 | 
						|
 * with this program; see the file COPYING; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include <lib/version.h>
 | 
						|
#include "lib/bfd.h"
 | 
						|
#include "lib/printfrr.h"
 | 
						|
#include "prefix.h"
 | 
						|
#include "linklist.h"
 | 
						|
#include "stream.h"
 | 
						|
#include "command.h"
 | 
						|
#include "log.h"
 | 
						|
#include "sockunion.h"
 | 
						|
#include "memory.h"
 | 
						|
#include "queue.h"
 | 
						|
#include "filter.h"
 | 
						|
 | 
						|
#include "bgpd/bgpd.h"
 | 
						|
#include "bgpd/bgp_aspath.h"
 | 
						|
#include "bgpd/bgp_route.h"
 | 
						|
#include "bgpd/bgp_attr.h"
 | 
						|
#include "bgpd/bgp_debug.h"
 | 
						|
#include "bgpd/bgp_community.h"
 | 
						|
#include "bgpd/bgp_lcommunity.h"
 | 
						|
#include "bgpd/bgp_updgrp.h"
 | 
						|
#include "bgpd/bgp_mplsvpn.h"
 | 
						|
#include "bgpd/bgp_ecommunity.h"
 | 
						|
#include "bgpd/bgp_label.h"
 | 
						|
#include "bgpd/bgp_evpn.h"
 | 
						|
#include "bgpd/bgp_evpn_private.h"
 | 
						|
#include "bgpd/bgp_evpn_vty.h"
 | 
						|
#include "bgpd/bgp_vty.h"
 | 
						|
#include "bgpd/bgp_flowspec.h"
 | 
						|
#include "bgpd/bgp_packet.h"
 | 
						|
 | 
						|
unsigned long conf_bgp_debug_as4;
 | 
						|
unsigned long conf_bgp_debug_neighbor_events;
 | 
						|
unsigned long conf_bgp_debug_events;
 | 
						|
unsigned long conf_bgp_debug_packet;
 | 
						|
unsigned long conf_bgp_debug_filter;
 | 
						|
unsigned long conf_bgp_debug_keepalive;
 | 
						|
unsigned long conf_bgp_debug_update;
 | 
						|
unsigned long conf_bgp_debug_bestpath;
 | 
						|
unsigned long conf_bgp_debug_zebra;
 | 
						|
unsigned long conf_bgp_debug_allow_martians;
 | 
						|
unsigned long conf_bgp_debug_nht;
 | 
						|
unsigned long conf_bgp_debug_update_groups;
 | 
						|
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 conf_bgp_debug_evpn_mh;
 | 
						|
unsigned long conf_bgp_debug_bfd;
 | 
						|
 | 
						|
unsigned long term_bgp_debug_as4;
 | 
						|
unsigned long term_bgp_debug_neighbor_events;
 | 
						|
unsigned long term_bgp_debug_events;
 | 
						|
unsigned long term_bgp_debug_packet;
 | 
						|
unsigned long term_bgp_debug_filter;
 | 
						|
unsigned long term_bgp_debug_keepalive;
 | 
						|
unsigned long term_bgp_debug_update;
 | 
						|
unsigned long term_bgp_debug_bestpath;
 | 
						|
unsigned long term_bgp_debug_zebra;
 | 
						|
unsigned long term_bgp_debug_allow_martians;
 | 
						|
unsigned long term_bgp_debug_nht;
 | 
						|
unsigned long term_bgp_debug_update_groups;
 | 
						|
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;
 | 
						|
unsigned long term_bgp_debug_evpn_mh;
 | 
						|
unsigned long term_bgp_debug_bfd;
 | 
						|
 | 
						|
struct list *bgp_debug_neighbor_events_peers = NULL;
 | 
						|
struct list *bgp_debug_keepalive_peers = NULL;
 | 
						|
struct list *bgp_debug_update_out_peers = NULL;
 | 
						|
struct list *bgp_debug_update_in_peers = NULL;
 | 
						|
struct list *bgp_debug_update_prefixes = NULL;
 | 
						|
struct list *bgp_debug_bestpath_prefixes = NULL;
 | 
						|
struct list *bgp_debug_zebra_prefixes = NULL;
 | 
						|
 | 
						|
/* messages for BGP-4 status */
 | 
						|
const struct message bgp_status_msg[] = {{Idle, "Idle"},
 | 
						|
					 {Connect, "Connect"},
 | 
						|
					 {Active, "Active"},
 | 
						|
					 {OpenSent, "OpenSent"},
 | 
						|
					 {OpenConfirm, "OpenConfirm"},
 | 
						|
					 {Established, "Established"},
 | 
						|
					 {Clearing, "Clearing"},
 | 
						|
					 {Deleted, "Deleted"},
 | 
						|
					 {0}};
 | 
						|
 | 
						|
/* BGP message type string. */
 | 
						|
const char *const bgp_type_str[] = {NULL,	   "OPEN",      "UPDATE",
 | 
						|
			      "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH",
 | 
						|
			      "CAPABILITY"};
 | 
						|
 | 
						|
/* message for BGP-4 Notify */
 | 
						|
static const struct message bgp_notify_msg[] = {
 | 
						|
	{BGP_NOTIFY_HEADER_ERR, "Message Header Error"},
 | 
						|
	{BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"},
 | 
						|
	{BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"},
 | 
						|
	{BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"},
 | 
						|
	{BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"},
 | 
						|
	{BGP_NOTIFY_CEASE, "Cease"},
 | 
						|
	{BGP_NOTIFY_ROUTE_REFRESH_ERR, "ROUTE-REFRESH Message Error"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_head_msg[] = {
 | 
						|
	{BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized"},
 | 
						|
	{BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length"},
 | 
						|
	{BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_open_msg[] = {
 | 
						|
	{BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
 | 
						|
	{BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number"},
 | 
						|
	{BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"},
 | 
						|
	{BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"},
 | 
						|
	{BGP_NOTIFY_OPEN_UNSUP_PARAM, "/Unsupported Optional Parameter"},
 | 
						|
	{BGP_NOTIFY_OPEN_AUTH_FAILURE, "/Authentication Failure"},
 | 
						|
	{BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time"},
 | 
						|
	{BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability"},
 | 
						|
	{BGP_NOTIFY_OPEN_ROLE_MISMATCH, "/Role Mismatch"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_update_msg[] = {
 | 
						|
	{BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
 | 
						|
	{BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"},
 | 
						|
	{BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"},
 | 
						|
	{BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"},
 | 
						|
	{BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, "/Attribute Flags Error"},
 | 
						|
	{BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, "/Attribute Length Error"},
 | 
						|
	{BGP_NOTIFY_UPDATE_INVAL_ORIGIN, "/Invalid ORIGIN Attribute"},
 | 
						|
	{BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP, "/AS Routing Loop"},
 | 
						|
	{BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, "/Invalid NEXT_HOP Attribute"},
 | 
						|
	{BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, "/Optional Attribute Error"},
 | 
						|
	{BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field"},
 | 
						|
	{BGP_NOTIFY_UPDATE_MAL_AS_PATH, "/Malformed AS_PATH"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_cease_msg[] = {
 | 
						|
	{BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
 | 
						|
	{BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"},
 | 
						|
	{BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administrative Shutdown"},
 | 
						|
	{BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer De-configured"},
 | 
						|
	{BGP_NOTIFY_CEASE_ADMIN_RESET, "/Administrative Reset"},
 | 
						|
	{BGP_NOTIFY_CEASE_CONNECT_REJECT, "/Connection Rejected"},
 | 
						|
	{BGP_NOTIFY_CEASE_CONFIG_CHANGE, "/Other Configuration Change"},
 | 
						|
	{BGP_NOTIFY_CEASE_COLLISION_RESOLUTION,
 | 
						|
	 "/Connection Collision Resolution"},
 | 
						|
	{BGP_NOTIFY_CEASE_OUT_OF_RESOURCE, "/Out of Resources"},
 | 
						|
	{BGP_NOTIFY_CEASE_HARD_RESET, "/Hard Reset"},
 | 
						|
	{BGP_NOTIFY_CEASE_BFD_DOWN, "/BFD Down"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_route_refresh_msg[] = {
 | 
						|
	{BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
 | 
						|
	{BGP_NOTIFY_ROUTE_REFRESH_INVALID_MSG_LEN, "/Invalid Message Length"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
static const struct message bgp_notify_fsm_msg[] = {
 | 
						|
	{BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC, "/Unspecific"},
 | 
						|
	{BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT,
 | 
						|
	 "/Receive Unexpected Message in OpenSent State"},
 | 
						|
	{BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM,
 | 
						|
	 "/Receive Unexpected Message in OpenConfirm State"},
 | 
						|
	{BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED,
 | 
						|
	 "/Receive Unexpected Message in Established State"},
 | 
						|
	{0}};
 | 
						|
 | 
						|
/* Origin strings. */
 | 
						|
const char *const bgp_origin_str[] = {"i", "e", "?"};
 | 
						|
const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"};
 | 
						|
 | 
						|
static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
 | 
						|
					struct prefix *p);
 | 
						|
/* Given a string return a pointer the corresponding peer structure */
 | 
						|
static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str)
 | 
						|
{
 | 
						|
	struct bgp *bgp = VTY_GET_CONTEXT(bgp);
 | 
						|
	int ret;
 | 
						|
	union sockunion su;
 | 
						|
	struct peer *peer;
 | 
						|
 | 
						|
	if (!bgp) {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	ret = str2sockunion(peer_str, &su);
 | 
						|
 | 
						|
	/* 'swpX' string */
 | 
						|
	if (ret < 0) {
 | 
						|
		peer = peer_lookup_by_conf_if(bgp, peer_str);
 | 
						|
 | 
						|
		if (!peer)
 | 
						|
			peer = peer_lookup_by_hostname(bgp, peer_str);
 | 
						|
 | 
						|
		return peer;
 | 
						|
	} else
 | 
						|
		return peer_lookup(bgp, &su);
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_debug_list_free(struct list *list)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	if (list)
 | 
						|
		for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
 | 
						|
			listnode_delete(list, filter);
 | 
						|
			prefix_free(&filter->p);
 | 
						|
			XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
 | 
						|
			XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
 | 
						|
		}
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Print the desc along with a list of peers/prefixes this debug is
 | 
						|
 * enabled for
 | 
						|
 */
 | 
						|
static void bgp_debug_list_print(struct vty *vty, const char *desc,
 | 
						|
				 struct list *list)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	vty_out(vty, "%s", desc);
 | 
						|
 | 
						|
	if (list && !list_isempty(list)) {
 | 
						|
		vty_out(vty, " for");
 | 
						|
		for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
 | 
						|
			if (filter->host)
 | 
						|
				vty_out(vty, " %s", filter->host);
 | 
						|
 | 
						|
			if (filter->p && filter->p->family == AF_EVPN)
 | 
						|
				bgp_debug_print_evpn_prefix(vty, "", filter->p);
 | 
						|
			else if (filter->p)
 | 
						|
				vty_out(vty, " %pFX", filter->p);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	vty_out(vty, "\n");
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Print the command to enable the debug for each peer/prefix this debug is
 | 
						|
 * enabled for
 | 
						|
 */
 | 
						|
static int bgp_debug_list_conf_print(struct vty *vty, const char *desc,
 | 
						|
				     struct list *list)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
	int write = 0;
 | 
						|
 | 
						|
	if (list && !list_isempty(list)) {
 | 
						|
		for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
 | 
						|
			if (filter->host) {
 | 
						|
				vty_out(vty, "%s %s\n", desc, filter->host);
 | 
						|
				write++;
 | 
						|
			}
 | 
						|
 | 
						|
			if (filter->p && filter->p->family == AF_EVPN) {
 | 
						|
				bgp_debug_print_evpn_prefix(vty, desc,
 | 
						|
							    filter->p);
 | 
						|
				write++;
 | 
						|
			} else if (filter->p) {
 | 
						|
				vty_out(vty, "%s %pFX\n", desc, filter->p);
 | 
						|
				write++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (!write) {
 | 
						|
		vty_out(vty, "%s\n", desc);
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	return write;
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_debug_list_add_entry(struct list *list, const char *host,
 | 
						|
				     const struct prefix *p)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
 | 
						|
	filter = XCALLOC(MTYPE_BGP_DEBUG_FILTER,
 | 
						|
			 sizeof(struct bgp_debug_filter));
 | 
						|
 | 
						|
	if (host) {
 | 
						|
		filter->host = XSTRDUP(MTYPE_BGP_DEBUG_STR, host);
 | 
						|
		filter->p = NULL;
 | 
						|
	} else if (p) {
 | 
						|
		filter->host = NULL;
 | 
						|
		filter->p = prefix_new();
 | 
						|
		prefix_copy(filter->p, p);
 | 
						|
	}
 | 
						|
 | 
						|
	listnode_add(list, filter);
 | 
						|
}
 | 
						|
 | 
						|
static bool bgp_debug_list_remove_entry(struct list *list, const char *host,
 | 
						|
					struct prefix *p)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
 | 
						|
		if (host && strcmp(filter->host, host) == 0) {
 | 
						|
			listnode_delete(list, filter);
 | 
						|
			XFREE(MTYPE_BGP_DEBUG_STR, filter->host);
 | 
						|
			XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
 | 
						|
			return true;
 | 
						|
		} else if (p && filter->p->prefixlen == p->prefixlen
 | 
						|
			   && prefix_match(filter->p, p)) {
 | 
						|
			listnode_delete(list, filter);
 | 
						|
			prefix_free(&filter->p);
 | 
						|
			XFREE(MTYPE_BGP_DEBUG_FILTER, filter);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
static bool bgp_debug_list_has_entry(struct list *list, const char *host,
 | 
						|
				     const struct prefix *p)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) {
 | 
						|
		if (host) {
 | 
						|
			if (strcmp(filter->host, host) == 0) {
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
		} else if (p) {
 | 
						|
			if (filter->p->prefixlen == p->prefixlen
 | 
						|
			    && prefix_match(filter->p, p)) {
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_peer_updout_enabled(char *host)
 | 
						|
{
 | 
						|
	return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
 | 
						|
					 NULL));
 | 
						|
}
 | 
						|
 | 
						|
/* Dump attribute. */
 | 
						|
bool bgp_dump_attr(struct attr *attr, char *buf, size_t size)
 | 
						|
{
 | 
						|
	char addrbuf[BUFSIZ];
 | 
						|
 | 
						|
	if (!attr)
 | 
						|
		return false;
 | 
						|
 | 
						|
	buf[0] = '\0';
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)))
 | 
						|
		snprintfrr(buf, size, "nexthop %pI4", &attr->nexthop);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf), ", origin %s",
 | 
						|
			 bgp_origin_str[attr->origin]);
 | 
						|
 | 
						|
	/* Add MP case. */
 | 
						|
	if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
 | 
						|
	    || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", mp_nexthop %s",
 | 
						|
			 inet_ntop(AF_INET6, &attr->mp_nexthop_global, addrbuf,
 | 
						|
				   BUFSIZ));
 | 
						|
 | 
						|
	if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf), "(%s)",
 | 
						|
			 inet_ntop(AF_INET6, &attr->mp_nexthop_local, addrbuf,
 | 
						|
				   BUFSIZ));
 | 
						|
 | 
						|
	if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
 | 
						|
		snprintfrr(buf, size, "nexthop %pI4", &attr->nexthop);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", localpref %u", attr->local_pref);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf), ", metric %u",
 | 
						|
			 attr->med);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", community %s",
 | 
						|
			 community_str(bgp_attr_get_community(attr), false,
 | 
						|
				       true));
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", large-community %s",
 | 
						|
			 lcommunity_str(bgp_attr_get_lcommunity(attr), false,
 | 
						|
					true));
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", extcommunity %s",
 | 
						|
			 ecommunity_str(bgp_attr_get_ecommunity(attr)));
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", atomic-aggregate");
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)))
 | 
						|
		snprintfrr(buf + strlen(buf), size - strlen(buf),
 | 
						|
			   ", aggregated by %u %pI4", attr->aggregator_as,
 | 
						|
			   &attr->aggregator_addr);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
 | 
						|
		snprintfrr(buf + strlen(buf), size - strlen(buf),
 | 
						|
			   ", originator %pI4", &attr->originator_id);
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
 | 
						|
		struct cluster_list *cluster;
 | 
						|
		int i;
 | 
						|
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", clusterlist");
 | 
						|
 | 
						|
		cluster = bgp_attr_get_cluster(attr);
 | 
						|
		for (i = 0; i < cluster->length / 4; i++)
 | 
						|
			snprintfrr(buf + strlen(buf), size - strlen(buf),
 | 
						|
				   " %pI4", &cluster->list[i]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
			 ", pmsi tnltype %u", bgp_attr_get_pmsi_tnl_type(attr));
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
 | 
						|
		snprintf(buf + strlen(buf), size - strlen(buf), ", path %s",
 | 
						|
			 aspath_print(attr->aspath));
 | 
						|
 | 
						|
	if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))) {
 | 
						|
		if (attr->label_index != BGP_INVALID_LABEL_INDEX)
 | 
						|
			snprintf(buf + strlen(buf), size - strlen(buf),
 | 
						|
				 ", label-index %u", attr->label_index);
 | 
						|
	}
 | 
						|
 | 
						|
	if (strlen(buf) > 1)
 | 
						|
		return true;
 | 
						|
	else
 | 
						|
		return false;
 | 
						|
}
 | 
						|
 | 
						|
const char *bgp_notify_code_str(char code)
 | 
						|
{
 | 
						|
	return lookup_msg(bgp_notify_msg, code, "Unrecognized Error Code");
 | 
						|
}
 | 
						|
 | 
						|
const char *bgp_notify_subcode_str(char code, char subcode)
 | 
						|
{
 | 
						|
 | 
						|
	switch (code) {
 | 
						|
	case BGP_NOTIFY_HEADER_ERR:
 | 
						|
		return lookup_msg(bgp_notify_head_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	case BGP_NOTIFY_OPEN_ERR:
 | 
						|
		return lookup_msg(bgp_notify_open_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	case BGP_NOTIFY_UPDATE_ERR:
 | 
						|
		return lookup_msg(bgp_notify_update_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	case BGP_NOTIFY_HOLD_ERR:
 | 
						|
		break;
 | 
						|
	case BGP_NOTIFY_FSM_ERR:
 | 
						|
		return lookup_msg(bgp_notify_fsm_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	case BGP_NOTIFY_CEASE:
 | 
						|
		return lookup_msg(bgp_notify_cease_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	case BGP_NOTIFY_ROUTE_REFRESH_ERR:
 | 
						|
		return lookup_msg(bgp_notify_route_refresh_msg, subcode,
 | 
						|
				  "Unrecognized Error Subcode");
 | 
						|
	}
 | 
						|
	return "";
 | 
						|
}
 | 
						|
 | 
						|
/* extract notify admin reason if correctly present */
 | 
						|
const char *bgp_notify_admin_message(char *buf, size_t bufsz, uint8_t *data,
 | 
						|
				     size_t datalen)
 | 
						|
{
 | 
						|
	if (!data || datalen < 1)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	uint8_t len = data[0];
 | 
						|
	if (!len || len > datalen - 1)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	return zlog_sanitize(buf, bufsz, data + 1, len);
 | 
						|
}
 | 
						|
 | 
						|
/* dump notify packet */
 | 
						|
void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
 | 
						|
		      const char *direct, bool hard_reset)
 | 
						|
{
 | 
						|
	const char *subcode_str;
 | 
						|
	const char *code_str;
 | 
						|
	const char *msg_str = NULL;
 | 
						|
	char msg_buf[1024];
 | 
						|
 | 
						|
	if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)
 | 
						|
	    || CHECK_FLAG(peer->bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) {
 | 
						|
		code_str = bgp_notify_code_str(bgp_notify->code);
 | 
						|
		subcode_str = bgp_notify_subcode_str(bgp_notify->code,
 | 
						|
						     bgp_notify->subcode);
 | 
						|
 | 
						|
		if (bgp_notify->code == BGP_NOTIFY_CEASE
 | 
						|
		    && (bgp_notify->subcode == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN
 | 
						|
			|| bgp_notify->subcode
 | 
						|
				   == BGP_NOTIFY_CEASE_ADMIN_RESET)) {
 | 
						|
			msg_str = bgp_notify_admin_message(
 | 
						|
				msg_buf, sizeof(msg_buf), bgp_notify->raw_data,
 | 
						|
				bgp_notify->length);
 | 
						|
		}
 | 
						|
 | 
						|
		if (msg_str) {
 | 
						|
			zlog_info(
 | 
						|
				"%%NOTIFICATION%s: %s neighbor %s %d/%d (%s%s) \"%s\"",
 | 
						|
				hard_reset ? "(Hard Reset)" : "",
 | 
						|
				strcmp(direct, "received") == 0
 | 
						|
					? "received from"
 | 
						|
					: "sent to",
 | 
						|
				peer->host, bgp_notify->code,
 | 
						|
				bgp_notify->subcode, code_str, subcode_str,
 | 
						|
				msg_str);
 | 
						|
		} else {
 | 
						|
			msg_str = bgp_notify->data ? bgp_notify->data : "";
 | 
						|
			zlog_info(
 | 
						|
				"%%NOTIFICATION%s: %s neighbor %s %d/%d (%s%s) %d bytes %s",
 | 
						|
				hard_reset ? "(Hard Reset)" : "",
 | 
						|
				strcmp(direct, "received") == 0
 | 
						|
					? "received from"
 | 
						|
					: "sent to",
 | 
						|
				peer->host, bgp_notify->code,
 | 
						|
				bgp_notify->subcode, code_str, subcode_str,
 | 
						|
				bgp_notify->length, msg_str);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp)
 | 
						|
{
 | 
						|
	if (!bgp)
 | 
						|
		bgp = bgp_get_default();
 | 
						|
	update_group_walk(bgp, update_group_clear_update_dbg, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
 | 
						|
					struct prefix *p)
 | 
						|
{
 | 
						|
	char evpn_desc[PREFIX2STR_BUFFER + INET_ADDRSTRLEN];
 | 
						|
	char buf[PREFIX2STR_BUFFER];
 | 
						|
	char buf2[ETHER_ADDR_STRLEN];
 | 
						|
 | 
						|
	if (p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE) {
 | 
						|
		if (is_evpn_prefix_ipaddr_none((struct prefix_evpn *)p)) {
 | 
						|
			snprintf(
 | 
						|
				evpn_desc, sizeof(evpn_desc),
 | 
						|
				"l2vpn evpn type macip mac %s",
 | 
						|
				prefix_mac2str(&p->u.prefix_evpn.macip_addr.mac,
 | 
						|
					       buf2, sizeof(buf2)));
 | 
						|
		} else {
 | 
						|
			uint8_t family = is_evpn_prefix_ipaddr_v4(
 | 
						|
						(struct prefix_evpn *)p) ?
 | 
						|
							AF_INET : AF_INET6;
 | 
						|
			snprintf(
 | 
						|
				evpn_desc, sizeof(evpn_desc),
 | 
						|
				"l2vpn evpn type macip mac %s ip %s",
 | 
						|
				prefix_mac2str(&p->u.prefix_evpn.macip_addr.mac,
 | 
						|
					       buf2, sizeof(buf2)),
 | 
						|
				inet_ntop(
 | 
						|
					family,
 | 
						|
					&p->u.prefix_evpn.macip_addr.ip.ip.addr,
 | 
						|
					buf, PREFIX2STR_BUFFER));
 | 
						|
		}
 | 
						|
	} else if (p->u.prefix_evpn.route_type == BGP_EVPN_IMET_ROUTE) {
 | 
						|
		snprintfrr(evpn_desc, sizeof(evpn_desc),
 | 
						|
			   "l2vpn evpn type multicast ip %pI4",
 | 
						|
			   &p->u.prefix_evpn.imet_addr.ip.ipaddr_v4);
 | 
						|
	} else if (p->u.prefix_evpn.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
 | 
						|
		uint8_t family = is_evpn_prefix_ipaddr_v4(
 | 
						|
					(struct prefix_evpn *)p) ? AF_INET
 | 
						|
								: AF_INET6;
 | 
						|
		snprintf(evpn_desc, sizeof(evpn_desc),
 | 
						|
			 "l2vpn evpn type prefix ip %s/%d",
 | 
						|
			 inet_ntop(family,
 | 
						|
				   &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
 | 
						|
				   buf, PREFIX2STR_BUFFER),
 | 
						|
			 p->u.prefix_evpn.prefix_addr.ip_prefix_length);
 | 
						|
	}
 | 
						|
 | 
						|
	vty_out(vty, "%s %s\n", desc, evpn_desc);
 | 
						|
}
 | 
						|
 | 
						|
static int bgp_debug_parse_evpn_prefix(struct vty *vty, struct cmd_token **argv,
 | 
						|
				       int argc, struct prefix **argv_pp)
 | 
						|
{
 | 
						|
	struct prefix *argv_p;
 | 
						|
	struct ethaddr mac = {};
 | 
						|
	struct ipaddr ip = {};
 | 
						|
	int evpn_type = 0;
 | 
						|
	int mac_idx = 0;
 | 
						|
	int ip_idx = 0;
 | 
						|
 | 
						|
	argv_p = *argv_pp;
 | 
						|
 | 
						|
	if (bgp_evpn_cli_parse_type(&evpn_type, argv, argc) < 0)
 | 
						|
		return CMD_WARNING;
 | 
						|
 | 
						|
	if (evpn_type == BGP_EVPN_MAC_IP_ROUTE) {
 | 
						|
		memset(&ip, 0, sizeof(ip));
 | 
						|
 | 
						|
		if (argv_find(argv, argc, "mac", &mac_idx))
 | 
						|
			if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
 | 
						|
				vty_out(vty, "%% Malformed MAC address\n");
 | 
						|
				return CMD_WARNING;
 | 
						|
			}
 | 
						|
 | 
						|
		if (argv_find(argv, argc, "ip", &ip_idx))
 | 
						|
			if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
 | 
						|
				vty_out(vty, "%% Malformed IP address\n");
 | 
						|
				return CMD_WARNING;
 | 
						|
			}
 | 
						|
 | 
						|
		build_evpn_type2_prefix((struct prefix_evpn *)argv_p,
 | 
						|
					&mac, &ip);
 | 
						|
	} else if (evpn_type == BGP_EVPN_IMET_ROUTE) {
 | 
						|
		memset(&ip, 0, sizeof(ip));
 | 
						|
 | 
						|
		if (argv_find(argv, argc, "ip", &ip_idx))
 | 
						|
			if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
 | 
						|
				vty_out(vty, "%% Malformed IP address\n");
 | 
						|
				return CMD_WARNING;
 | 
						|
			}
 | 
						|
 | 
						|
		build_evpn_type3_prefix((struct prefix_evpn *)argv_p,
 | 
						|
					ip.ipaddr_v4);
 | 
						|
	} else if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
 | 
						|
		struct prefix ip_prefix;
 | 
						|
 | 
						|
		memset(&ip_prefix, 0, sizeof(ip_prefix));
 | 
						|
		if (argv_find(argv, argc, "ip", &ip_idx)) {
 | 
						|
			(void)str2prefix(argv[ip_idx + 1]->arg, &ip_prefix);
 | 
						|
			apply_mask(&ip_prefix);
 | 
						|
		}
 | 
						|
		build_type5_prefix_from_ip_prefix(
 | 
						|
					(struct prefix_evpn *)argv_p,
 | 
						|
					&ip_prefix);
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* Debug option setting interface. */
 | 
						|
unsigned long bgp_debug_option = 0;
 | 
						|
 | 
						|
int debug(unsigned int option)
 | 
						|
{
 | 
						|
	return bgp_debug_option & option;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_as4,
 | 
						|
       debug_bgp_as4_cmd,
 | 
						|
       "debug bgp as4",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP AS4 actions\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(as4, AS4);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(as4, AS4);
 | 
						|
		vty_out(vty, "BGP as4 debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_as4,
 | 
						|
       no_debug_bgp_as4_cmd,
 | 
						|
       "no debug bgp as4",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP AS4 actions\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(as4, AS4);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(as4, AS4);
 | 
						|
		vty_out(vty, "BGP as4 debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_as4_segment,
 | 
						|
       debug_bgp_as4_segment_cmd,
 | 
						|
       "debug bgp as4 segment",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP AS4 actions\n"
 | 
						|
       "BGP AS4 aspath segment handling\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(as4, AS4_SEGMENT);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(as4, AS4_SEGMENT);
 | 
						|
		vty_out(vty, "BGP as4 segment debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_as4_segment,
 | 
						|
       no_debug_bgp_as4_segment_cmd,
 | 
						|
       "no debug bgp as4 segment",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP AS4 actions\n"
 | 
						|
       "BGP AS4 aspath segment handling\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(as4, AS4_SEGMENT);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(as4, AS4_SEGMENT);
 | 
						|
		vty_out(vty, "BGP as4 segment debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp neighbor_events */
 | 
						|
DEFUN (debug_bgp_neighbor_events,
 | 
						|
       debug_bgp_neighbor_events_cmd,
 | 
						|
       "debug bgp neighbor-events",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Neighbor Events\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_neighbor_events_peers);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
		vty_out(vty, "BGP neighbor-events debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_neighbor_events_peer,
 | 
						|
       debug_bgp_neighbor_events_peer_cmd,
 | 
						|
       "debug bgp neighbor-events <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Neighbor Events\n"
 | 
						|
       "BGP neighbor IP address to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_peer = 3;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
 | 
						|
	if (!bgp_debug_neighbor_events_peers)
 | 
						|
		bgp_debug_neighbor_events_peers = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host,
 | 
						|
				     NULL)) {
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP neighbor-events debugging is already enabled for %s\n",
 | 
						|
			host);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
		vty_out(vty, "BGP neighbor-events debugging is on for %s\n",
 | 
						|
			host);
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_neighbor_events,
 | 
						|
       no_debug_bgp_neighbor_events_cmd,
 | 
						|
       "no debug bgp neighbor-events",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "Neighbor Events\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_neighbor_events_peers);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
		vty_out(vty, "BGP neighbor-events debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_neighbor_events_peer,
 | 
						|
       no_debug_bgp_neighbor_events_peer_cmd,
 | 
						|
       "no debug bgp neighbor-events <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "Neighbor Events\n"
 | 
						|
       "BGP neighbor IP address to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_peer = 4;
 | 
						|
	int found_peer = 0;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
 | 
						|
	if (bgp_debug_neighbor_events_peers
 | 
						|
	    && !list_isempty(bgp_debug_neighbor_events_peers)) {
 | 
						|
		found_peer = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_neighbor_events_peers, host, NULL);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_neighbor_events_peers)) {
 | 
						|
			if (vty->node == CONFIG_NODE)
 | 
						|
				DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
			else
 | 
						|
				TERM_DEBUG_OFF(neighbor_events,
 | 
						|
					       NEIGHBOR_EVENTS);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_peer)
 | 
						|
		vty_out(vty, "BGP neighbor-events debugging is off for %s\n",
 | 
						|
			host);
 | 
						|
	else
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP neighbor-events debugging was not enabled for %s\n",
 | 
						|
			host);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp nht */
 | 
						|
DEFUN (debug_bgp_nht,
 | 
						|
       debug_bgp_nht_cmd,
 | 
						|
       "debug bgp nht",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP nexthop tracking events\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(nht, NHT);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(nht, NHT);
 | 
						|
		vty_out(vty, "BGP nexthop tracking debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_nht,
 | 
						|
       no_debug_bgp_nht_cmd,
 | 
						|
       "no debug bgp nht",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP nexthop tracking events\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(nht, NHT);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(nht, NHT);
 | 
						|
		vty_out(vty, "BGP nexthop tracking debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp keepalives */
 | 
						|
DEFUN (debug_bgp_keepalive,
 | 
						|
       debug_bgp_keepalive_cmd,
 | 
						|
       "debug bgp keepalives",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP keepalives\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_keepalive_peers);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(keepalive, KEEPALIVE);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(keepalive, KEEPALIVE);
 | 
						|
		vty_out(vty, "BGP keepalives debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_keepalive_peer,
 | 
						|
       debug_bgp_keepalive_peer_cmd,
 | 
						|
       "debug bgp keepalives <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP keepalives\n"
 | 
						|
       "BGP IPv4 neighbor to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_peer = 3;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
 | 
						|
	if (!bgp_debug_keepalive_peers)
 | 
						|
		bgp_debug_keepalive_peers = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL)) {
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP keepalive debugging is already enabled for %s\n",
 | 
						|
			host);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(keepalive, KEEPALIVE);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(keepalive, KEEPALIVE);
 | 
						|
		vty_out(vty, "BGP keepalives debugging is on for %s\n", host);
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_keepalive,
 | 
						|
       no_debug_bgp_keepalive_cmd,
 | 
						|
       "no debug bgp keepalives",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP keepalives\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_keepalive_peers);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(keepalive, KEEPALIVE);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(keepalive, KEEPALIVE);
 | 
						|
		vty_out(vty, "BGP keepalives debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_keepalive_peer,
 | 
						|
       no_debug_bgp_keepalive_peer_cmd,
 | 
						|
       "no debug bgp keepalives <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP keepalives\n"
 | 
						|
       "BGP neighbor IP address to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_peer = 4;
 | 
						|
	int found_peer = 0;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
 | 
						|
	if (bgp_debug_keepalive_peers
 | 
						|
	    && !list_isempty(bgp_debug_keepalive_peers)) {
 | 
						|
		found_peer = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_keepalive_peers, host, NULL);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_keepalive_peers)) {
 | 
						|
			if (vty->node == CONFIG_NODE)
 | 
						|
				DEBUG_OFF(keepalive, KEEPALIVE);
 | 
						|
			else
 | 
						|
				TERM_DEBUG_OFF(keepalive, KEEPALIVE);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_peer)
 | 
						|
		vty_out(vty, "BGP keepalives debugging is off for %s\n", host);
 | 
						|
	else
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP keepalives debugging was not enabled for %s\n",
 | 
						|
			host);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp bestpath */
 | 
						|
DEFUN (debug_bgp_bestpath_prefix,
 | 
						|
       debug_bgp_bestpath_prefix_cmd,
 | 
						|
       "debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP bestpath\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	struct prefix *argv_p;
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 3;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (!bgp_debug_bestpath_prefixes)
 | 
						|
		bgp_debug_bestpath_prefixes = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL,
 | 
						|
				     argv_p)) {
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP bestpath debugging is already enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		DEBUG_ON(bestpath, BESTPATH);
 | 
						|
	} else {
 | 
						|
		TERM_DEBUG_ON(bestpath, BESTPATH);
 | 
						|
		vty_out(vty, "BGP bestpath debugging is on for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_bestpath_prefix,
 | 
						|
       no_debug_bgp_bestpath_prefix_cmd,
 | 
						|
       "no debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP bestpath\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 4;
 | 
						|
	struct prefix *argv_p;
 | 
						|
	int found_prefix = 0;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (bgp_debug_bestpath_prefixes
 | 
						|
	    && !list_isempty(bgp_debug_bestpath_prefixes)) {
 | 
						|
		found_prefix = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_bestpath_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_bestpath_prefixes)) {
 | 
						|
			if (vty->node == CONFIG_NODE) {
 | 
						|
				DEBUG_OFF(bestpath, BESTPATH);
 | 
						|
			} else {
 | 
						|
				TERM_DEBUG_OFF(bestpath, BESTPATH);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP bestpath debugging (per prefix) is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_prefix)
 | 
						|
		vty_out(vty, "BGP bestpath debugging is off for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	else
 | 
						|
		vty_out(vty, "BGP bestpath debugging was not enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_bestpath,
 | 
						|
       no_debug_bgp_bestpath_cmd,
 | 
						|
       "no debug bgp bestpath",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP bestpath\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_bestpath_prefixes);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(bestpath, BESTPATH);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(bestpath, BESTPATH);
 | 
						|
		vty_out(vty, "BGP bestpath debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp updates */
 | 
						|
DEFUN (debug_bgp_update,
 | 
						|
       debug_bgp_update_cmd,
 | 
						|
       "debug bgp updates",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_update_in_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_out_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_prefixes);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		DEBUG_ON(update, UPDATE_IN);
 | 
						|
		DEBUG_ON(update, UPDATE_OUT);
 | 
						|
	} else {
 | 
						|
		TERM_DEBUG_ON(update, UPDATE_IN);
 | 
						|
		TERM_DEBUG_ON(update, UPDATE_OUT);
 | 
						|
		vty_out(vty, "BGP updates debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_update_direct,
 | 
						|
       debug_bgp_update_direct_cmd,
 | 
						|
       "debug bgp updates <in|out>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Inbound updates\n"
 | 
						|
       "Outbound updates\n")
 | 
						|
{
 | 
						|
	int idx_in_out = 3;
 | 
						|
 | 
						|
	if (strncmp("i", argv[idx_in_out]->arg, 1) == 0)
 | 
						|
		bgp_debug_list_free(bgp_debug_update_in_peers);
 | 
						|
	else
 | 
						|
		bgp_debug_list_free(bgp_debug_update_out_peers);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		if (strncmp("i", argv[idx_in_out]->arg, 1) == 0)
 | 
						|
			DEBUG_ON(update, UPDATE_IN);
 | 
						|
		else
 | 
						|
			DEBUG_ON(update, UPDATE_OUT);
 | 
						|
	} else {
 | 
						|
		if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) {
 | 
						|
			TERM_DEBUG_ON(update, UPDATE_IN);
 | 
						|
			vty_out(vty, "BGP updates debugging is on (inbound)\n");
 | 
						|
		} else {
 | 
						|
			TERM_DEBUG_ON(update, UPDATE_OUT);
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging is on (outbound)\n");
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_update_direct_peer,
 | 
						|
       debug_bgp_update_direct_peer_cmd,
 | 
						|
       "debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Inbound updates\n"
 | 
						|
       "Outbound updates\n"
 | 
						|
       "BGP neighbor IP address to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_in_out = 3;
 | 
						|
	int idx_peer = 4;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
	int inbound;
 | 
						|
 | 
						|
	if (!bgp_debug_update_in_peers)
 | 
						|
		bgp_debug_update_in_peers = list_new();
 | 
						|
 | 
						|
	if (!bgp_debug_update_out_peers)
 | 
						|
		bgp_debug_update_out_peers = list_new();
 | 
						|
 | 
						|
	if (strncmp("i", argv[idx_in_out]->arg, 1) == 0)
 | 
						|
		inbound = 1;
 | 
						|
	else
 | 
						|
		inbound = 0;
 | 
						|
 | 
						|
	if (inbound) {
 | 
						|
		if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host,
 | 
						|
					     NULL)) {
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP inbound update debugging is already enabled for %s\n",
 | 
						|
				host);
 | 
						|
			return CMD_SUCCESS;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	else {
 | 
						|
		if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host,
 | 
						|
					     NULL)) {
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP outbound update debugging is already enabled for %s\n",
 | 
						|
				host);
 | 
						|
			return CMD_SUCCESS;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (inbound)
 | 
						|
		bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL);
 | 
						|
	else {
 | 
						|
		struct peer *peer;
 | 
						|
		struct peer_af *paf;
 | 
						|
		int afidx;
 | 
						|
 | 
						|
		bgp_debug_list_add_entry(bgp_debug_update_out_peers, host,
 | 
						|
					 NULL);
 | 
						|
		peer = bgp_find_peer(vty, host);
 | 
						|
 | 
						|
		if (peer) {
 | 
						|
			for (afidx = BGP_AF_START; afidx < BGP_AF_MAX;
 | 
						|
			     afidx++) {
 | 
						|
				paf = peer->peer_af_array[afidx];
 | 
						|
				if (paf != NULL) {
 | 
						|
					if (PAF_SUBGRP(paf)) {
 | 
						|
						UPDGRP_PEER_DBG_EN(
 | 
						|
							PAF_SUBGRP(paf)
 | 
						|
								->update_group);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		if (inbound)
 | 
						|
			DEBUG_ON(update, UPDATE_IN);
 | 
						|
		else
 | 
						|
			DEBUG_ON(update, UPDATE_OUT);
 | 
						|
	} else {
 | 
						|
		if (inbound) {
 | 
						|
			TERM_DEBUG_ON(update, UPDATE_IN);
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging is on (inbound) for %s\n",
 | 
						|
				argv[idx_peer]->arg);
 | 
						|
		} else {
 | 
						|
			TERM_DEBUG_ON(update, UPDATE_OUT);
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging is on (outbound) for %s\n",
 | 
						|
				argv[idx_peer]->arg);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_update_direct,
 | 
						|
       no_debug_bgp_update_direct_cmd,
 | 
						|
       "no debug bgp updates <in|out>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Inbound updates\n"
 | 
						|
       "Outbound updates\n")
 | 
						|
{
 | 
						|
	int idx_in_out = 4;
 | 
						|
	if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) {
 | 
						|
		bgp_debug_list_free(bgp_debug_update_in_peers);
 | 
						|
 | 
						|
		if (vty->node == CONFIG_NODE) {
 | 
						|
			DEBUG_OFF(update, UPDATE_IN);
 | 
						|
		} else {
 | 
						|
			TERM_DEBUG_OFF(update, UPDATE_IN);
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging is off (inbound)\n");
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		bgp_debug_list_free(bgp_debug_update_out_peers);
 | 
						|
 | 
						|
		if (vty->node == CONFIG_NODE) {
 | 
						|
			DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
		} else {
 | 
						|
			TERM_DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging is off (outbound)\n");
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_update_direct_peer,
 | 
						|
       no_debug_bgp_update_direct_peer_cmd,
 | 
						|
       "no debug bgp updates <in|out> <A.B.C.D|X:X::X:X|WORD>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Inbound updates\n"
 | 
						|
       "Outbound updates\n"
 | 
						|
       "BGP neighbor IP address to debug\n"
 | 
						|
       "BGP IPv6 neighbor to debug\n"
 | 
						|
       "BGP neighbor on interface to debug\n")
 | 
						|
{
 | 
						|
	int idx_in_out = 4;
 | 
						|
	int idx_peer = 5;
 | 
						|
	int inbound;
 | 
						|
	int found_peer = 0;
 | 
						|
	const char *host = argv[idx_peer]->arg;
 | 
						|
 | 
						|
	if (strncmp("i", argv[idx_in_out]->arg, 1) == 0)
 | 
						|
		inbound = 1;
 | 
						|
	else
 | 
						|
		inbound = 0;
 | 
						|
 | 
						|
	if (inbound && bgp_debug_update_in_peers
 | 
						|
	    && !list_isempty(bgp_debug_update_in_peers)) {
 | 
						|
		found_peer = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_update_in_peers, host, NULL);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_update_in_peers)) {
 | 
						|
			if (vty->node == CONFIG_NODE)
 | 
						|
				DEBUG_OFF(update, UPDATE_IN);
 | 
						|
			else {
 | 
						|
				TERM_DEBUG_OFF(update, UPDATE_IN);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP updates debugging (inbound) is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (!inbound && bgp_debug_update_out_peers
 | 
						|
	    && !list_isempty(bgp_debug_update_out_peers)) {
 | 
						|
		found_peer = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_update_out_peers, host, NULL);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_update_out_peers)) {
 | 
						|
			if (vty->node == CONFIG_NODE)
 | 
						|
				DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
			else {
 | 
						|
				TERM_DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP updates debugging (outbound) is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		struct peer *peer;
 | 
						|
		struct peer_af *paf;
 | 
						|
		int afidx;
 | 
						|
		peer = bgp_find_peer(vty, host);
 | 
						|
 | 
						|
		if (peer) {
 | 
						|
			for (afidx = BGP_AF_START; afidx < BGP_AF_MAX;
 | 
						|
			     afidx++) {
 | 
						|
				paf = peer->peer_af_array[afidx];
 | 
						|
				if (paf != NULL) {
 | 
						|
					if (PAF_SUBGRP(paf)) {
 | 
						|
						UPDGRP_PEER_DBG_DIS(
 | 
						|
							PAF_SUBGRP(paf)
 | 
						|
								->update_group);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_peer)
 | 
						|
		if (inbound)
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging (inbound) is off for %s\n",
 | 
						|
				host);
 | 
						|
		else
 | 
						|
			vty_out(vty,
 | 
						|
				"BGP updates debugging (outbound) is off for %s\n",
 | 
						|
				host);
 | 
						|
	else if (inbound)
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP updates debugging (inbound) was not enabled for %s\n",
 | 
						|
			host);
 | 
						|
	else
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP updates debugging (outbound) was not enabled for %s\n",
 | 
						|
			host);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
#ifndef VTYSH_EXTRACT_PL
 | 
						|
#include "bgpd/bgp_debug_clippy.c"
 | 
						|
#endif
 | 
						|
 | 
						|
DEFPY (debug_bgp_update_prefix_afi_safi,
 | 
						|
       debug_bgp_update_prefix_afi_safi_cmd,
 | 
						|
       "debug bgp updates prefix l2vpn$afi evpn$safi type <<macip|2> mac <X:X:X:X:X:X|X:X:X:X:X:X/M> [ip <A.B.C.D|X:X::X:X>]|<multicast|3> ip <A.B.C.D|X:X::X:X>|<prefix|5> ip <A.B.C.D/M|X:X::X:X/M>>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       L2VPN_HELP_STR
 | 
						|
       EVPN_HELP_STR
 | 
						|
       EVPN_TYPE_HELP_STR
 | 
						|
       EVPN_TYPE_2_HELP_STR
 | 
						|
       EVPN_TYPE_2_HELP_STR
 | 
						|
       MAC_STR MAC_STR MAC_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 address\n"
 | 
						|
       "IPv6 address\n"
 | 
						|
       EVPN_TYPE_3_HELP_STR
 | 
						|
       EVPN_TYPE_3_HELP_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 address\n"
 | 
						|
       "IPv6 address\n"
 | 
						|
       EVPN_TYPE_5_HELP_STR
 | 
						|
       EVPN_TYPE_5_HELP_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	struct prefix *argv_p;
 | 
						|
	int ret = CMD_SUCCESS;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
 | 
						|
	ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p);
 | 
						|
	if (ret != CMD_SUCCESS) {
 | 
						|
		prefix_free(&argv_p);
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	if (!bgp_debug_update_prefixes)
 | 
						|
		bgp_debug_update_prefixes = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) {
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP updates debugging is already enabled for %pFX\n",
 | 
						|
			argv_p);
 | 
						|
		prefix_free(&argv_p);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		DEBUG_ON(update, UPDATE_PREFIX);
 | 
						|
	} else {
 | 
						|
		TERM_DEBUG_ON(update, UPDATE_PREFIX);
 | 
						|
		vty_out(vty, "BGP updates debugging is on for %pFX\n", argv_p);
 | 
						|
	}
 | 
						|
 | 
						|
	prefix_free(&argv_p);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFPY (no_debug_bgp_update_prefix_afi_safi,
 | 
						|
       no_debug_bgp_update_prefix_afi_safi_cmd,
 | 
						|
       "no debug bgp updates prefix l2vpn$afi evpn$safi type <<macip|2> mac <X:X:X:X:X:X|X:X:X:X:X:X/M> [ip <A.B.C.D|X:X::X:X>]|<multicast|3> ip <A.B.C.D|X:X::X:X>|<prefix|5> ip <A.B.C.D/M|X:X::X:X/M>>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       L2VPN_HELP_STR
 | 
						|
       EVPN_HELP_STR
 | 
						|
       EVPN_TYPE_HELP_STR
 | 
						|
       EVPN_TYPE_2_HELP_STR
 | 
						|
       EVPN_TYPE_2_HELP_STR
 | 
						|
       MAC_STR MAC_STR MAC_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 address\n"
 | 
						|
       "IPv6 address\n"
 | 
						|
       EVPN_TYPE_3_HELP_STR
 | 
						|
       EVPN_TYPE_3_HELP_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 address\n"
 | 
						|
       "IPv6 address\n"
 | 
						|
       EVPN_TYPE_5_HELP_STR
 | 
						|
       EVPN_TYPE_5_HELP_STR
 | 
						|
       IP_STR
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	struct prefix *argv_p;
 | 
						|
	bool found_prefix = false;
 | 
						|
	int ret = CMD_SUCCESS;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
 | 
						|
	ret = bgp_debug_parse_evpn_prefix(vty, argv, argc, &argv_p);
 | 
						|
	if (ret != CMD_SUCCESS) {
 | 
						|
		prefix_free(&argv_p);
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	if (bgp_debug_update_prefixes
 | 
						|
	    && !list_isempty(bgp_debug_update_prefixes)) {
 | 
						|
		found_prefix = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_update_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_update_prefixes)) {
 | 
						|
			if (vty->node == CONFIG_NODE) {
 | 
						|
				DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
			} else {
 | 
						|
				TERM_DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP updates debugging (per prefix) is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_prefix)
 | 
						|
		vty_out(vty, "BGP updates debugging is off for %pFX\n", argv_p);
 | 
						|
	else
 | 
						|
		vty_out(vty, "BGP updates debugging was not enabled for %pFX\n",
 | 
						|
			argv_p);
 | 
						|
 | 
						|
	prefix_free(&argv_p);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
DEFUN (debug_bgp_update_prefix,
 | 
						|
       debug_bgp_update_prefix_cmd,
 | 
						|
       "debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 4;
 | 
						|
	struct prefix *argv_p;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (!bgp_debug_update_prefixes)
 | 
						|
		bgp_debug_update_prefixes = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) {
 | 
						|
		vty_out(vty,
 | 
						|
			"BGP updates debugging is already enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		DEBUG_ON(update, UPDATE_PREFIX);
 | 
						|
	} else {
 | 
						|
		TERM_DEBUG_ON(update, UPDATE_PREFIX);
 | 
						|
		vty_out(vty, "BGP updates debugging is on for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_update_prefix,
 | 
						|
       no_debug_bgp_update_prefix_cmd,
 | 
						|
       "no debug bgp updates prefix <A.B.C.D/M|X:X::X:X/M>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 5;
 | 
						|
	struct prefix *argv_p;
 | 
						|
	int found_prefix = 0;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (bgp_debug_update_prefixes
 | 
						|
	    && !list_isempty(bgp_debug_update_prefixes)) {
 | 
						|
		found_prefix = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_update_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_update_prefixes)) {
 | 
						|
			if (vty->node == CONFIG_NODE) {
 | 
						|
				DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
			} else {
 | 
						|
				TERM_DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP updates debugging (per prefix) is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_prefix)
 | 
						|
		vty_out(vty, "BGP updates debugging is off for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	else
 | 
						|
		vty_out(vty, "BGP updates debugging was not enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_update,
 | 
						|
       no_debug_bgp_update_cmd,
 | 
						|
       "no debug bgp updates",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP updates\n")
 | 
						|
{
 | 
						|
	struct listnode *ln;
 | 
						|
	struct bgp *bgp;
 | 
						|
 | 
						|
	bgp_debug_list_free(bgp_debug_update_in_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_out_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_prefixes);
 | 
						|
 | 
						|
	for (ALL_LIST_ELEMENTS_RO(bm->bgp, ln, bgp))
 | 
						|
		bgp_debug_clear_updgrp_update_dbg(bgp);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		DEBUG_OFF(update, UPDATE_IN);
 | 
						|
		DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
		DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
	} else {
 | 
						|
		TERM_DEBUG_OFF(update, UPDATE_IN);
 | 
						|
		TERM_DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
		TERM_DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
		vty_out(vty, "BGP updates debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp zebra */
 | 
						|
DEFUN (debug_bgp_zebra,
 | 
						|
       debug_bgp_zebra_cmd,
 | 
						|
       "debug bgp zebra",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Zebra messages\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(zebra, ZEBRA);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(zebra, ZEBRA);
 | 
						|
		vty_out(vty, "BGP zebra debugging is on\n");
 | 
						|
	}
 | 
						|
	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>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Zebra messages\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 4;
 | 
						|
	struct prefix *argv_p;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (!bgp_debug_zebra_prefixes)
 | 
						|
		bgp_debug_zebra_prefixes = list_new();
 | 
						|
 | 
						|
	if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p)) {
 | 
						|
		vty_out(vty, "BGP zebra debugging is already enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
 | 
						|
	bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(zebra, ZEBRA);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(zebra, ZEBRA);
 | 
						|
		vty_out(vty, "BGP zebra debugging is on for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_zebra,
 | 
						|
       no_debug_bgp_zebra_cmd,
 | 
						|
       "no debug bgp zebra",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Zebra messages\n")
 | 
						|
{
 | 
						|
	bgp_debug_list_free(bgp_debug_zebra_prefixes);
 | 
						|
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(zebra, ZEBRA);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(zebra, ZEBRA);
 | 
						|
		vty_out(vty, "BGP zebra debugging is off\n");
 | 
						|
	}
 | 
						|
	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>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP Zebra messages\n"
 | 
						|
       "Specify a prefix to debug\n"
 | 
						|
       "IPv4 prefix\n"
 | 
						|
       "IPv6 prefix\n")
 | 
						|
{
 | 
						|
	int idx_ipv4_ipv6_prefixlen = 5;
 | 
						|
	struct prefix *argv_p;
 | 
						|
	int found_prefix = 0;
 | 
						|
 | 
						|
	argv_p = prefix_new();
 | 
						|
	(void)str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p);
 | 
						|
	apply_mask(argv_p);
 | 
						|
 | 
						|
	if (bgp_debug_zebra_prefixes
 | 
						|
	    && !list_isempty(bgp_debug_zebra_prefixes)) {
 | 
						|
		found_prefix = bgp_debug_list_remove_entry(
 | 
						|
			bgp_debug_zebra_prefixes, NULL, argv_p);
 | 
						|
 | 
						|
		if (list_isempty(bgp_debug_zebra_prefixes)) {
 | 
						|
			if (vty->node == CONFIG_NODE)
 | 
						|
				DEBUG_OFF(zebra, ZEBRA);
 | 
						|
			else {
 | 
						|
				TERM_DEBUG_OFF(zebra, ZEBRA);
 | 
						|
				vty_out(vty, "BGP zebra debugging is off\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (found_prefix)
 | 
						|
		vty_out(vty, "BGP zebra debugging is off for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
	else
 | 
						|
		vty_out(vty, "BGP zebra debugging was not enabled for %s\n",
 | 
						|
			argv[idx_ipv4_ipv6_prefixlen]->arg);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp update-groups */
 | 
						|
DEFUN (debug_bgp_update_groups,
 | 
						|
       debug_bgp_update_groups_cmd,
 | 
						|
       "debug bgp update-groups",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP update-groups\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(update_groups, UPDATE_GROUPS);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(update_groups, UPDATE_GROUPS);
 | 
						|
		vty_out(vty, "BGP update-groups debugging is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_update_groups,
 | 
						|
       no_debug_bgp_update_groups_cmd,
 | 
						|
       "no debug bgp update-groups",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP update-groups\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(update_groups, UPDATE_GROUPS);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(update_groups, UPDATE_GROUPS);
 | 
						|
		vty_out(vty, "BGP update-groups debugging is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_vpn,
 | 
						|
       debug_bgp_vpn_cmd,
 | 
						|
       "debug bgp vpn <leak-from-vrf|leak-to-vrf|rmap-event|label>",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "VPN routes\n"
 | 
						|
       "leaked from vrf to vpn\n"
 | 
						|
       "leaked to vrf from vpn\n"
 | 
						|
       "route-map updates\n"
 | 
						|
       "labels\n")
 | 
						|
{
 | 
						|
	int idx = 3;
 | 
						|
 | 
						|
	if (argv_find(argv, argc, "leak-from-vrf", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_ON(vpn, VPN_LEAK_FROM_VRF);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_ON(vpn, VPN_LEAK_FROM_VRF);
 | 
						|
	} else if (argv_find(argv, argc, "leak-to-vrf", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_ON(vpn, VPN_LEAK_TO_VRF);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_ON(vpn, VPN_LEAK_TO_VRF);
 | 
						|
	} else if (argv_find(argv, argc, "rmap-event", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_ON(vpn, VPN_LEAK_RMAP_EVENT);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_ON(vpn, VPN_LEAK_RMAP_EVENT);
 | 
						|
	} else if (argv_find(argv, argc, "label", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_ON(vpn, VPN_LEAK_LABEL);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_ON(vpn, VPN_LEAK_LABEL);
 | 
						|
	} else {
 | 
						|
		vty_out(vty, "%% unknown debug bgp vpn keyword\n");
 | 
						|
		return CMD_WARNING_CONFIG_FAILED;
 | 
						|
	}
 | 
						|
 | 
						|
	if (vty->node != CONFIG_NODE)
 | 
						|
		vty_out(vty, "enabled debug bgp vpn %s\n", argv[idx]->text);
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_vpn,
 | 
						|
       no_debug_bgp_vpn_cmd,
 | 
						|
       "no debug bgp vpn <leak-from-vrf|leak-to-vrf|rmap-event|label>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "VPN routes\n"
 | 
						|
       "leaked from vrf to vpn\n"
 | 
						|
       "leaked to vrf from vpn\n"
 | 
						|
       "route-map updates\n"
 | 
						|
       "labels\n")
 | 
						|
{
 | 
						|
	int idx = 4;
 | 
						|
 | 
						|
	if (argv_find(argv, argc, "leak-from-vrf", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
 | 
						|
 | 
						|
	} else if (argv_find(argv, argc, "leak-to-vrf", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
 | 
						|
	} else if (argv_find(argv, argc, "rmap-event", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
 | 
						|
	} else if (argv_find(argv, argc, "label", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_OFF(vpn, VPN_LEAK_LABEL);
 | 
						|
		else
 | 
						|
			TERM_DEBUG_OFF(vpn, VPN_LEAK_LABEL);
 | 
						|
	} else {
 | 
						|
		vty_out(vty, "%% unknown debug bgp vpn keyword\n");
 | 
						|
		return CMD_WARNING_CONFIG_FAILED;
 | 
						|
	}
 | 
						|
 | 
						|
	if (vty->node != CONFIG_NODE)
 | 
						|
		vty_out(vty, "disabled debug bgp vpn %s\n", argv[idx]->text);
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/* debug bgp pbr */
 | 
						|
DEFUN (debug_bgp_pbr,
 | 
						|
       debug_bgp_pbr_cmd,
 | 
						|
       "debug bgp pbr [error]",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP policy based routing\n"
 | 
						|
       "BGP PBR error\n")
 | 
						|
{
 | 
						|
	int idx = 3;
 | 
						|
 | 
						|
	if (argv_find(argv, argc, "error", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_ON(pbr, PBR_ERROR);
 | 
						|
		else {
 | 
						|
			TERM_DEBUG_ON(pbr, PBR_ERROR);
 | 
						|
			vty_out(vty, "BGP policy based routing error is on\n");
 | 
						|
		}
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(pbr, PBR);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_ON(pbr, PBR);
 | 
						|
		vty_out(vty, "BGP policy based routing is on\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_pbr,
 | 
						|
       no_debug_bgp_pbr_cmd,
 | 
						|
       "no debug bgp pbr [error]",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "BGP policy based routing\n"
 | 
						|
       "BGP PBR Error\n")
 | 
						|
{
 | 
						|
	int idx = 3;
 | 
						|
 | 
						|
	if (argv_find(argv, argc, "error", &idx)) {
 | 
						|
		if (vty->node == CONFIG_NODE)
 | 
						|
			DEBUG_OFF(pbr, PBR_ERROR);
 | 
						|
		else {
 | 
						|
			TERM_DEBUG_OFF(pbr, PBR_ERROR);
 | 
						|
			vty_out(vty, "BGP policy based routing error is off\n");
 | 
						|
		}
 | 
						|
		return CMD_SUCCESS;
 | 
						|
	}
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(pbr, PBR);
 | 
						|
	else {
 | 
						|
		TERM_DEBUG_OFF(pbr, PBR);
 | 
						|
		vty_out(vty, "BGP policy based routing is off\n");
 | 
						|
	}
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFPY (debug_bgp_evpn_mh,
 | 
						|
       debug_bgp_evpn_mh_cmd,
 | 
						|
       "[no$no] debug bgp evpn mh <es$es|route$rt>",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "EVPN\n"
 | 
						|
       "Multihoming\n"
 | 
						|
       "Ethernet Segment debugging\n"
 | 
						|
       "Route debugging\n")
 | 
						|
{
 | 
						|
	if (es) {
 | 
						|
		if (vty->node == CONFIG_NODE) {
 | 
						|
			if (no)
 | 
						|
				DEBUG_OFF(evpn_mh, EVPN_MH_ES);
 | 
						|
			else
 | 
						|
				DEBUG_ON(evpn_mh, EVPN_MH_ES);
 | 
						|
		} else {
 | 
						|
			if (no) {
 | 
						|
				TERM_DEBUG_OFF(evpn_mh, EVPN_MH_ES);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP EVPN-MH ES debugging is off\n");
 | 
						|
			} else {
 | 
						|
				TERM_DEBUG_ON(evpn_mh, EVPN_MH_ES);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP EVPN-MH ES debugging is on\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (rt) {
 | 
						|
		if (vty->node == CONFIG_NODE) {
 | 
						|
			if (no)
 | 
						|
				DEBUG_OFF(evpn_mh, EVPN_MH_RT);
 | 
						|
			else
 | 
						|
				DEBUG_ON(evpn_mh, EVPN_MH_RT);
 | 
						|
		} else {
 | 
						|
			if (no) {
 | 
						|
				TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP EVPN-MH route debugging is off\n");
 | 
						|
			} else {
 | 
						|
				TERM_DEBUG_ON(evpn_mh, EVPN_MH_RT);
 | 
						|
				vty_out(vty,
 | 
						|
					"BGP EVPN-MH route debugging is on\n");
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (debug_bgp_labelpool,
 | 
						|
       debug_bgp_labelpool_cmd,
 | 
						|
       "debug bgp labelpool",
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "label pool\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_ON(labelpool, LABELPOOL);
 | 
						|
	else
 | 
						|
		TERM_DEBUG_ON(labelpool, LABELPOOL);
 | 
						|
 | 
						|
	if (vty->node != CONFIG_NODE)
 | 
						|
		vty_out(vty, "enabled debug bgp labelpool\n");
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp_labelpool,
 | 
						|
       no_debug_bgp_labelpool_cmd,
 | 
						|
       "no debug bgp labelpool",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR
 | 
						|
       "label pool\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE)
 | 
						|
		DEBUG_OFF(labelpool, LABELPOOL);
 | 
						|
	else
 | 
						|
		TERM_DEBUG_OFF(labelpool, LABELPOOL);
 | 
						|
 | 
						|
 | 
						|
	if (vty->node != CONFIG_NODE)
 | 
						|
		vty_out(vty, "disabled debug bgp labelpool\n");
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFPY(debug_bgp_bfd, debug_bgp_bfd_cmd,
 | 
						|
      "[no] debug bgp bfd",
 | 
						|
      NO_STR
 | 
						|
      DEBUG_STR
 | 
						|
      BGP_STR
 | 
						|
      "Bidirection Forwarding Detection\n")
 | 
						|
{
 | 
						|
	if (vty->node == CONFIG_NODE) {
 | 
						|
		if (no) {
 | 
						|
			DEBUG_OFF(bfd, BFD_LIB);
 | 
						|
			bfd_protocol_integration_set_debug(false);
 | 
						|
		} else {
 | 
						|
			DEBUG_ON(bfd, BFD_LIB);
 | 
						|
			bfd_protocol_integration_set_debug(true);
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (no) {
 | 
						|
			TERM_DEBUG_OFF(bfd, BFD_LIB);
 | 
						|
			bfd_protocol_integration_set_debug(false);
 | 
						|
		} else {
 | 
						|
			TERM_DEBUG_ON(bfd, BFD_LIB);
 | 
						|
			bfd_protocol_integration_set_debug(true);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN (no_debug_bgp,
 | 
						|
       no_debug_bgp_cmd,
 | 
						|
       "no debug bgp",
 | 
						|
       NO_STR
 | 
						|
       DEBUG_STR
 | 
						|
       BGP_STR)
 | 
						|
{
 | 
						|
	struct bgp *bgp;
 | 
						|
	struct listnode *ln;
 | 
						|
 | 
						|
	bgp_debug_list_free(bgp_debug_neighbor_events_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_keepalive_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_in_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_out_peers);
 | 
						|
	bgp_debug_list_free(bgp_debug_update_prefixes);
 | 
						|
	bgp_debug_list_free(bgp_debug_bestpath_prefixes);
 | 
						|
	bgp_debug_list_free(bgp_debug_zebra_prefixes);
 | 
						|
 | 
						|
	for (ALL_LIST_ELEMENTS_RO(bm->bgp, ln, bgp))
 | 
						|
		bgp_debug_clear_updgrp_update_dbg(bgp);
 | 
						|
 | 
						|
	TERM_DEBUG_OFF(keepalive, KEEPALIVE);
 | 
						|
	TERM_DEBUG_OFF(update, UPDATE_IN);
 | 
						|
	TERM_DEBUG_OFF(update, UPDATE_OUT);
 | 
						|
	TERM_DEBUG_OFF(update, UPDATE_PREFIX);
 | 
						|
	TERM_DEBUG_OFF(bestpath, BESTPATH);
 | 
						|
	TERM_DEBUG_OFF(as4, AS4);
 | 
						|
	TERM_DEBUG_OFF(as4, AS4_SEGMENT);
 | 
						|
	TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
 | 
						|
	TERM_DEBUG_OFF(zebra, ZEBRA);
 | 
						|
	TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS);
 | 
						|
	TERM_DEBUG_OFF(nht, NHT);
 | 
						|
	TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
 | 
						|
	TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
 | 
						|
	TERM_DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
 | 
						|
	TERM_DEBUG_OFF(vpn, VPN_LEAK_LABEL);
 | 
						|
	TERM_DEBUG_OFF(flowspec, FLOWSPEC);
 | 
						|
	TERM_DEBUG_OFF(labelpool, LABELPOOL);
 | 
						|
	TERM_DEBUG_OFF(pbr, PBR);
 | 
						|
	TERM_DEBUG_OFF(pbr, PBR_ERROR);
 | 
						|
	TERM_DEBUG_OFF(graceful_restart, GRACEFUL_RESTART);
 | 
						|
	TERM_DEBUG_OFF(evpn_mh, EVPN_MH_ES);
 | 
						|
	TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
 | 
						|
	TERM_DEBUG_OFF(bfd, BFD_LIB);
 | 
						|
 | 
						|
	vty_out(vty, "All possible debugging has been turned off\n");
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
DEFUN_NOSH (show_debugging_bgp,
 | 
						|
	    show_debugging_bgp_cmd,
 | 
						|
	    "show debugging [bgp]",
 | 
						|
	    SHOW_STR
 | 
						|
	    DEBUG_STR
 | 
						|
	    BGP_STR)
 | 
						|
{
 | 
						|
	vty_out(vty, "BGP debugging status:\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(as4, AS4))
 | 
						|
		vty_out(vty, "  BGP as4 debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(as4, AS4_SEGMENT))
 | 
						|
		vty_out(vty, "  BGP as4 aspath segment debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(bestpath, BESTPATH))
 | 
						|
		bgp_debug_list_print(vty, "  BGP bestpath debugging is on",
 | 
						|
				     bgp_debug_bestpath_prefixes);
 | 
						|
 | 
						|
	if (BGP_DEBUG(keepalive, KEEPALIVE))
 | 
						|
		bgp_debug_list_print(vty, "  BGP keepalives debugging is on",
 | 
						|
				     bgp_debug_keepalive_peers);
 | 
						|
 | 
						|
	if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS))
 | 
						|
		bgp_debug_list_print(vty,
 | 
						|
				     "  BGP neighbor-events debugging is on",
 | 
						|
				     bgp_debug_neighbor_events_peers);
 | 
						|
 | 
						|
	if (BGP_DEBUG(nht, NHT))
 | 
						|
		vty_out(vty, "  BGP next-hop tracking debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
 | 
						|
		vty_out(vty, "  BGP update-groups debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(update, UPDATE_PREFIX))
 | 
						|
		bgp_debug_list_print(vty, "  BGP updates debugging is on",
 | 
						|
				     bgp_debug_update_prefixes);
 | 
						|
 | 
						|
	if (BGP_DEBUG(update, UPDATE_IN))
 | 
						|
		bgp_debug_list_print(vty,
 | 
						|
				     "  BGP updates debugging is on (inbound)",
 | 
						|
				     bgp_debug_update_in_peers);
 | 
						|
 | 
						|
	if (BGP_DEBUG(update, UPDATE_OUT))
 | 
						|
		bgp_debug_list_print(vty,
 | 
						|
				     "  BGP updates debugging is on (outbound)",
 | 
						|
				     bgp_debug_update_out_peers);
 | 
						|
 | 
						|
	if (BGP_DEBUG(zebra, ZEBRA))
 | 
						|
		bgp_debug_list_print(vty, "  BGP zebra debugging is on",
 | 
						|
				     bgp_debug_zebra_prefixes);
 | 
						|
 | 
						|
	if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
 | 
						|
		vty_out(vty, "  BGP graceful-restart debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
 | 
						|
		vty_out(vty, "  BGP allow martian next hop debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
 | 
						|
		vty_out(vty,
 | 
						|
			"  BGP route leak from vrf to vpn debugging is on\n");
 | 
						|
	if (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF))
 | 
						|
		vty_out(vty,
 | 
						|
			"  BGP route leak to vrf from vpn debugging is on\n");
 | 
						|
	if (BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT))
 | 
						|
		vty_out(vty, "  BGP vpn route-map event debugging is on\n");
 | 
						|
	if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
 | 
						|
		vty_out(vty, "  BGP vpn label event debugging is on\n");
 | 
						|
	if (BGP_DEBUG(flowspec, FLOWSPEC))
 | 
						|
		vty_out(vty, "  BGP flowspec debugging is on\n");
 | 
						|
	if (BGP_DEBUG(labelpool, LABELPOOL))
 | 
						|
		vty_out(vty, "  BGP labelpool debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(pbr, PBR))
 | 
						|
		vty_out(vty, "  BGP policy based routing debugging is on\n");
 | 
						|
	if (BGP_DEBUG(pbr, PBR_ERROR))
 | 
						|
		vty_out(vty, "  BGP policy based routing error debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
 | 
						|
		vty_out(vty, "  BGP EVPN-MH ES debugging is on\n");
 | 
						|
	if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
 | 
						|
		vty_out(vty, "  BGP EVPN-MH route debugging is on\n");
 | 
						|
 | 
						|
	if (BGP_DEBUG(bfd, BFD_LIB))
 | 
						|
		vty_out(vty, "  BGP BFD library debugging is on\n");
 | 
						|
 | 
						|
	return CMD_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
static int bgp_config_write_debug(struct vty *vty)
 | 
						|
{
 | 
						|
	int write = 0;
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(as4, AS4)) {
 | 
						|
		vty_out(vty, "debug bgp as4\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(as4, AS4_SEGMENT)) {
 | 
						|
		vty_out(vty, "debug bgp as4 segment\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(bestpath, BESTPATH)) {
 | 
						|
		write += bgp_debug_list_conf_print(vty, "debug bgp bestpath",
 | 
						|
						   bgp_debug_bestpath_prefixes);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(keepalive, KEEPALIVE)) {
 | 
						|
		write += bgp_debug_list_conf_print(vty, "debug bgp keepalives",
 | 
						|
						   bgp_debug_keepalive_peers);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) {
 | 
						|
		write += bgp_debug_list_conf_print(
 | 
						|
			vty, "debug bgp neighbor-events",
 | 
						|
			bgp_debug_neighbor_events_peers);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(nht, NHT)) {
 | 
						|
		vty_out(vty, "debug bgp nht\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(update_groups, UPDATE_GROUPS)) {
 | 
						|
		vty_out(vty, "debug bgp update-groups\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(update, UPDATE_PREFIX)) {
 | 
						|
		write += bgp_debug_list_conf_print(vty,
 | 
						|
						   "debug bgp updates prefix",
 | 
						|
						   bgp_debug_update_prefixes);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(update, UPDATE_IN)) {
 | 
						|
		write += bgp_debug_list_conf_print(vty, "debug bgp updates in",
 | 
						|
						   bgp_debug_update_in_peers);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(update, UPDATE_OUT)) {
 | 
						|
		write += bgp_debug_list_conf_print(vty, "debug bgp updates out",
 | 
						|
						   bgp_debug_update_out_peers);
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(zebra, ZEBRA)) {
 | 
						|
		if (!bgp_debug_zebra_prefixes
 | 
						|
		    || list_isempty(bgp_debug_zebra_prefixes)) {
 | 
						|
			vty_out(vty, "debug bgp zebra\n");
 | 
						|
			write++;
 | 
						|
		} else {
 | 
						|
			write += bgp_debug_list_conf_print(
 | 
						|
				vty, "debug bgp zebra prefix",
 | 
						|
				bgp_debug_zebra_prefixes);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
 | 
						|
		vty_out(vty, "debug bgp allow-martians\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)) {
 | 
						|
		vty_out(vty, "debug bgp vpn leak-from-vrf\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)) {
 | 
						|
		vty_out(vty, "debug bgp vpn leak-to-vrf\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT)) {
 | 
						|
		vty_out(vty, "debug bgp vpn rmap-event\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
 | 
						|
		vty_out(vty, "debug bgp vpn label\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(flowspec, FLOWSPEC)) {
 | 
						|
		vty_out(vty, "debug bgp flowspec\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(labelpool, LABELPOOL)) {
 | 
						|
		vty_out(vty, "debug bgp labelpool\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(pbr, PBR)) {
 | 
						|
		vty_out(vty, "debug bgp pbr\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(pbr, PBR_ERROR)) {
 | 
						|
		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++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(evpn_mh, EVPN_MH_ES)) {
 | 
						|
		vty_out(vty, "debug bgp evpn mh es\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
	if (CONF_BGP_DEBUG(evpn_mh, EVPN_MH_RT)) {
 | 
						|
		vty_out(vty, "debug bgp evpn mh route\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CONF_BGP_DEBUG(bfd, BFD_LIB)) {
 | 
						|
		vty_out(vty, "debug bgp bfd\n");
 | 
						|
		write++;
 | 
						|
	}
 | 
						|
 | 
						|
	return write;
 | 
						|
}
 | 
						|
 | 
						|
static int bgp_config_write_debug(struct vty *vty);
 | 
						|
static struct cmd_node debug_node = {
 | 
						|
	.name = "debug",
 | 
						|
	.node = DEBUG_NODE,
 | 
						|
	.prompt = "",
 | 
						|
	.config_write = bgp_config_write_debug,
 | 
						|
};
 | 
						|
 | 
						|
void bgp_debug_init(void)
 | 
						|
{
 | 
						|
	install_node(&debug_node);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &show_debugging_bgp_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_as4_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_as4_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_as4_segment_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_as4_segment_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_neighbor_events_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_neighbor_events_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_nht_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_nht_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_keepalive_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_keepalive_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_update_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_update_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_zebra_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_zebra_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_update_groups_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_update_groups_cmd);
 | 
						|
	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);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_direct_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_direct_cmd);
 | 
						|
 | 
						|
	/* debug bgp updates (in|out) A.B.C.D */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_update_direct_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_update_direct_peer_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd);
 | 
						|
 | 
						|
	/* debug bgp updates prefix A.B.C.D/M */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_update_prefix_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_update_prefix_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_prefix_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_prefix_cmd);
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_update_prefix_afi_safi_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_update_prefix_afi_safi_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_prefix_afi_safi_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_prefix_afi_safi_cmd);
 | 
						|
 | 
						|
	/* debug bgp zebra prefix A.B.C.D/M */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_zebra_prefix_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_zebra_prefix_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_zebra_prefix_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_as4_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_as4_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_as4_segment_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_as4_segment_cmd);
 | 
						|
 | 
						|
	/* debug bgp neighbor-events A.B.C.D */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
 | 
						|
 | 
						|
	/* debug bgp keepalive A.B.C.D */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_keepalive_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_keepalive_peer_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_keepalive_peer_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_neighbor_events_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_neighbor_events_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_nht_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_nht_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_keepalive_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_keepalive_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_zebra_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_zebra_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_update_groups_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_update_groups_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_bestpath_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_bestpath_cmd);
 | 
						|
	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);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_vpn_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_labelpool_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_labelpool_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_labelpool_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_labelpool_cmd);
 | 
						|
 | 
						|
	/* debug bgp pbr */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_pbr_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_pbr_cmd);
 | 
						|
	install_element(ENABLE_NODE, &no_debug_bgp_pbr_cmd);
 | 
						|
	install_element(CONFIG_NODE, &no_debug_bgp_pbr_cmd);
 | 
						|
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_evpn_mh_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_evpn_mh_cmd);
 | 
						|
 | 
						|
	/* debug bgp bfd */
 | 
						|
	install_element(ENABLE_NODE, &debug_bgp_bfd_cmd);
 | 
						|
	install_element(CONFIG_NODE, &debug_bgp_bfd_cmd);
 | 
						|
}
 | 
						|
 | 
						|
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
 | 
						|
 * for BGP_DEBUG_TYPE
 | 
						|
 */
 | 
						|
static int bgp_debug_per_prefix(const struct prefix *p,
 | 
						|
				unsigned long term_bgp_debug_type,
 | 
						|
				unsigned int BGP_DEBUG_TYPE,
 | 
						|
				struct list *per_prefix_list)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
 | 
						|
		/* We are debugging all prefixes so return true */
 | 
						|
		if (!per_prefix_list || list_isempty(per_prefix_list))
 | 
						|
			return 1;
 | 
						|
 | 
						|
		else {
 | 
						|
			if (!p)
 | 
						|
				return 0;
 | 
						|
 | 
						|
			for (ALL_LIST_ELEMENTS(per_prefix_list, node, nnode,
 | 
						|
					       filter))
 | 
						|
				if (filter->p->prefixlen == p->prefixlen
 | 
						|
				    && prefix_match(filter->p, p))
 | 
						|
					return 1;
 | 
						|
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* Return true if this peer is on the per_peer_list of peers to debug
 | 
						|
 * for BGP_DEBUG_TYPE
 | 
						|
 */
 | 
						|
static bool bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
 | 
						|
			       unsigned int BGP_DEBUG_TYPE,
 | 
						|
			       struct list *per_peer_list)
 | 
						|
{
 | 
						|
	struct bgp_debug_filter *filter;
 | 
						|
	struct listnode *node, *nnode;
 | 
						|
 | 
						|
	if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
 | 
						|
		/* We are debugging all peers so return true */
 | 
						|
		if (!per_peer_list || list_isempty(per_peer_list))
 | 
						|
			return true;
 | 
						|
 | 
						|
		else {
 | 
						|
			if (!host)
 | 
						|
				return false;
 | 
						|
 | 
						|
			for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode,
 | 
						|
					       filter))
 | 
						|
				if (strcmp(filter->host, host) == 0)
 | 
						|
					return true;
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_neighbor_events(const struct peer *peer)
 | 
						|
{
 | 
						|
	char *host = NULL;
 | 
						|
 | 
						|
	if (peer)
 | 
						|
		host = peer->host;
 | 
						|
 | 
						|
	return bgp_debug_per_peer(host, term_bgp_debug_neighbor_events,
 | 
						|
				  BGP_DEBUG_NEIGHBOR_EVENTS,
 | 
						|
				  bgp_debug_neighbor_events_peers);
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_keepalive(const struct peer *peer)
 | 
						|
{
 | 
						|
	char *host = NULL;
 | 
						|
 | 
						|
	if (peer)
 | 
						|
		host = peer->host;
 | 
						|
 | 
						|
	return bgp_debug_per_peer(host, term_bgp_debug_keepalive,
 | 
						|
				  BGP_DEBUG_KEEPALIVE,
 | 
						|
				  bgp_debug_keepalive_peers);
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_update(const struct peer *peer, const struct prefix *p,
 | 
						|
		      struct update_group *updgrp, unsigned int inbound)
 | 
						|
{
 | 
						|
	char *host = NULL;
 | 
						|
 | 
						|
	if (peer)
 | 
						|
		host = peer->host;
 | 
						|
 | 
						|
	if (inbound) {
 | 
						|
		if (bgp_debug_per_peer(host, term_bgp_debug_update,
 | 
						|
				       BGP_DEBUG_UPDATE_IN,
 | 
						|
				       bgp_debug_update_in_peers))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/* outbound */
 | 
						|
	else {
 | 
						|
		if (bgp_debug_per_peer(host, term_bgp_debug_update,
 | 
						|
				       BGP_DEBUG_UPDATE_OUT,
 | 
						|
				       bgp_debug_update_out_peers))
 | 
						|
			return true;
 | 
						|
 | 
						|
		/* Check if update debugging implicitly enabled for the group.
 | 
						|
		 */
 | 
						|
		if (updgrp && UPDGRP_DBG_ON(updgrp))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	if (BGP_DEBUG(update, UPDATE_PREFIX)) {
 | 
						|
		if (bgp_debug_per_prefix(p, term_bgp_debug_update,
 | 
						|
					 BGP_DEBUG_UPDATE_PREFIX,
 | 
						|
					 bgp_debug_update_prefixes))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_bestpath(struct bgp_dest *dest)
 | 
						|
{
 | 
						|
	if (BGP_DEBUG(bestpath, BESTPATH)) {
 | 
						|
		if (bgp_debug_per_prefix(
 | 
						|
			    bgp_dest_get_prefix(dest), term_bgp_debug_bestpath,
 | 
						|
			    BGP_DEBUG_BESTPATH, bgp_debug_bestpath_prefixes))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool bgp_debug_zebra(const struct prefix *p)
 | 
						|
{
 | 
						|
	if (BGP_DEBUG(zebra, ZEBRA)) {
 | 
						|
		if (bgp_debug_per_prefix(p, term_bgp_debug_zebra,
 | 
						|
					 BGP_DEBUG_ZEBRA,
 | 
						|
					 bgp_debug_zebra_prefixes))
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
 | 
						|
				    const struct prefix_rd *prd,
 | 
						|
				    union prefixconstptr pu,
 | 
						|
				    mpls_label_t *label, uint32_t num_labels,
 | 
						|
				    int addpath_valid, uint32_t addpath_id,
 | 
						|
				    struct bgp_route_evpn *overlay_index,
 | 
						|
				    char *str, int size)
 | 
						|
{
 | 
						|
	char rd_buf[RD_ADDRSTRLEN];
 | 
						|
	char tag_buf[30];
 | 
						|
	char overlay_index_buf[INET6_ADDRSTRLEN + 14];
 | 
						|
	const struct prefix_evpn *evp;
 | 
						|
 | 
						|
	/* ' with addpath ID '          17
 | 
						|
	 * max strlen of uint32       + 10
 | 
						|
	 * +/- (just in case)         +  1
 | 
						|
	 * null terminator            +  1
 | 
						|
	 * ============================ 29 */
 | 
						|
	char pathid_buf[30];
 | 
						|
 | 
						|
	if (size < BGP_PRD_PATH_STRLEN)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	/* Note: Path-id is created by default, but only included in update
 | 
						|
	 * sometimes. */
 | 
						|
	pathid_buf[0] = '\0';
 | 
						|
	if (addpath_valid)
 | 
						|
		snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u",
 | 
						|
			 addpath_id);
 | 
						|
 | 
						|
	overlay_index_buf[0] = '\0';
 | 
						|
	if (overlay_index && overlay_index->type == OVERLAY_INDEX_GATEWAY_IP) {
 | 
						|
		char obuf[INET6_ADDRSTRLEN];
 | 
						|
 | 
						|
		obuf[0] = '\0';
 | 
						|
		evp = pu.evp;
 | 
						|
		if (is_evpn_prefix_ipaddr_v4(evp))
 | 
						|
			inet_ntop(AF_INET, &overlay_index->gw_ip, obuf,
 | 
						|
				  sizeof(obuf));
 | 
						|
		else if (is_evpn_prefix_ipaddr_v6(evp))
 | 
						|
			inet_ntop(AF_INET6, &overlay_index->gw_ip, obuf,
 | 
						|
				  sizeof(obuf));
 | 
						|
 | 
						|
		snprintf(overlay_index_buf, sizeof(overlay_index_buf),
 | 
						|
			 " gateway IP %s", obuf);
 | 
						|
	}
 | 
						|
 | 
						|
	tag_buf[0] = '\0';
 | 
						|
	if (bgp_labeled_safi(safi) && num_labels) {
 | 
						|
 | 
						|
		if (safi == SAFI_EVPN) {
 | 
						|
			char tag_buf2[20];
 | 
						|
 | 
						|
			bgp_evpn_label2str(label, num_labels, tag_buf2, 20);
 | 
						|
			snprintf(tag_buf, sizeof(tag_buf), " label %s",
 | 
						|
				 tag_buf2);
 | 
						|
		} else {
 | 
						|
			uint32_t label_value;
 | 
						|
 | 
						|
			label_value = decode_label(label);
 | 
						|
			snprintf(tag_buf, sizeof(tag_buf), " label %u",
 | 
						|
				 label_value);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (prd)
 | 
						|
		snprintfrr(str, size, "RD %s %pFX%s%s%s %s %s",
 | 
						|
			   prefix_rd2str(prd, rd_buf, sizeof(rd_buf)), pu.p,
 | 
						|
			   overlay_index_buf, tag_buf, pathid_buf, afi2str(afi),
 | 
						|
			   safi2str(safi));
 | 
						|
	else if (safi == SAFI_FLOWSPEC) {
 | 
						|
		char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
 | 
						|
		const struct prefix_fs *fs = pu.fs;
 | 
						|
 | 
						|
		bgp_fs_nlri_get_string((unsigned char *)fs->prefix.ptr,
 | 
						|
				       fs->prefix.prefixlen,
 | 
						|
				       return_string,
 | 
						|
				       NLRI_STRING_FORMAT_DEBUG, NULL,
 | 
						|
				       family2afi(fs->prefix.family));
 | 
						|
		snprintf(str, size, "FS %s Match{%s}", afi2str(afi),
 | 
						|
			 return_string);
 | 
						|
	} else
 | 
						|
		snprintfrr(str, size, "%pFX%s%s %s %s", pu.p, tag_buf,
 | 
						|
			   pathid_buf, afi2str(afi), safi2str(safi));
 | 
						|
 | 
						|
	return str;
 | 
						|
}
 |