mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 08:28:50 +00:00 
			
		
		
		
	Merge branch 'master' into docuser
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
		
						commit
						1f35b46a2f
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -82,3 +82,6 @@ GPATH
 | 
			
		||||
*.lo
 | 
			
		||||
compile_commands.json
 | 
			
		||||
.dirstamp
 | 
			
		||||
 | 
			
		||||
# clippy generated source
 | 
			
		||||
*_clippy.c
 | 
			
		||||
 | 
			
		||||
@ -114,3 +114,6 @@ EXTRA_DIST += \
 | 
			
		||||
ACLOCAL_AMFLAGS = -I m4
 | 
			
		||||
 | 
			
		||||
noinst_HEADERS += defaults.h
 | 
			
		||||
 | 
			
		||||
indent:
 | 
			
		||||
	tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								alpine/APKBUILD.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								alpine/APKBUILD.in
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
# Maintainer: Arthur Jones <arthur.jones@riverbed.com>
 | 
			
		||||
pkgname=frr
 | 
			
		||||
pkgver=@VERSION@
 | 
			
		||||
pkgrel=0
 | 
			
		||||
pkgdesc="Free Range Routing is a fork of quagga"
 | 
			
		||||
url="https://frrouting.org/"
 | 
			
		||||
arch="all"
 | 
			
		||||
license="GPL-2.0"
 | 
			
		||||
depends="iproute2 json-c c-ares ipsec-tools iproute2"
 | 
			
		||||
makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
 | 
			
		||||
    acct autoconf automake bash
 | 
			
		||||
    binutils binutils-libs bison bsd-compat-headers build-base
 | 
			
		||||
    c-ares c-ares-dev ca-certificates cryptsetup-libs curl
 | 
			
		||||
    device-mapper-libs expat fakeroot flex fortify-headers gdbm
 | 
			
		||||
    git gmp isl json-c-dev kmod lddtree libacl libatomic libattr
 | 
			
		||||
    libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc
 | 
			
		||||
    libgomp libisoburn libisofs libltdl libressl libssh2
 | 
			
		||||
    libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1
 | 
			
		||||
    mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base
 | 
			
		||||
    patch pax-utils pcre perl pkgconf python2 python2-dev readline
 | 
			
		||||
    readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs"
 | 
			
		||||
subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
 | 
			
		||||
source="$pkgname-$pkgver.tar.gz"
 | 
			
		||||
 | 
			
		||||
builddir="$srcdir"/$pkgname-$pkgver
 | 
			
		||||
 | 
			
		||||
build() {
 | 
			
		||||
	cd "$builddir"
 | 
			
		||||
	./configure --prefix=/usr || return 1
 | 
			
		||||
	make || return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
package() {
 | 
			
		||||
	cd "$builddir"
 | 
			
		||||
	make DESTDIR="$pkgdir" install || return 1
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								bgpd/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								bgpd/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -16,4 +16,3 @@ TAGS
 | 
			
		||||
.arch-ids
 | 
			
		||||
*~
 | 
			
		||||
*.loT
 | 
			
		||||
*clippy.c
 | 
			
		||||
 | 
			
		||||
@ -498,7 +498,8 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
 | 
			
		||||
	if (!as->segments) {
 | 
			
		||||
		if (make_json) {
 | 
			
		||||
			json_object_string_add(as->json, "string", "Local");
 | 
			
		||||
			json_object_object_add(as->json, "segments", jaspath_segments);
 | 
			
		||||
			json_object_object_add(as->json, "segments",
 | 
			
		||||
					       jaspath_segments);
 | 
			
		||||
			json_object_int_add(as->json, "length", 0);
 | 
			
		||||
		}
 | 
			
		||||
		as->str = XMALLOC(MTYPE_AS_STR, 1);
 | 
			
		||||
@ -575,8 +576,9 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
 | 
			
		||||
		/* write out the ASNs, with their seperators, bar the last one*/
 | 
			
		||||
		for (i = 0; i < seg->length; i++) {
 | 
			
		||||
			if (make_json)
 | 
			
		||||
				json_object_array_add(jseg_list,
 | 
			
		||||
						      json_object_new_int(seg->as[i]));
 | 
			
		||||
				json_object_array_add(
 | 
			
		||||
					jseg_list,
 | 
			
		||||
					json_object_new_int(seg->as[i]));
 | 
			
		||||
 | 
			
		||||
			len += snprintf(str_buf + len, str_size - len, "%u",
 | 
			
		||||
					seg->as[i]);
 | 
			
		||||
@ -588,8 +590,9 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
 | 
			
		||||
 | 
			
		||||
		if (make_json) {
 | 
			
		||||
			jseg = json_object_new_object();
 | 
			
		||||
			json_object_string_add(jseg, "type",
 | 
			
		||||
					       aspath_segment_type_str[seg->type]);
 | 
			
		||||
			json_object_string_add(
 | 
			
		||||
				jseg, "type",
 | 
			
		||||
				aspath_segment_type_str[seg->type]);
 | 
			
		||||
			json_object_object_add(jseg, "list", jseg_list);
 | 
			
		||||
			json_object_array_add(jaspath_segments, jseg);
 | 
			
		||||
		}
 | 
			
		||||
@ -904,7 +907,8 @@ size_t aspath_put(struct stream *s, struct aspath *as, int use32bit)
 | 
			
		||||
				assegment_data_put(s, seg->as, AS_SEGMENT_MAX,
 | 
			
		||||
						   use32bit);
 | 
			
		||||
				written += AS_SEGMENT_MAX;
 | 
			
		||||
				bytes += ASSEGMENT_SIZE(AS_SEGMENT_MAX, use32bit);
 | 
			
		||||
				bytes += ASSEGMENT_SIZE(AS_SEGMENT_MAX,
 | 
			
		||||
							use32bit);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* write the final segment, probably is also the first
 | 
			
		||||
@ -2032,9 +2036,7 @@ int aspath_cmp(const void *arg1, const void *arg2)
 | 
			
		||||
/* AS path hash initialize. */
 | 
			
		||||
void aspath_init(void)
 | 
			
		||||
{
 | 
			
		||||
	ashash = hash_create_size(32768,
 | 
			
		||||
				  aspath_key_make,
 | 
			
		||||
				  aspath_cmp,
 | 
			
		||||
	ashash = hash_create_size(32768, aspath_key_make, aspath_cmp,
 | 
			
		||||
				  "BGP AS Path");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										159
									
								
								bgpd/bgp_attr.c
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								bgpd/bgp_attr.c
									
									
									
									
									
								
							@ -83,15 +83,14 @@ static const struct message attr_str[] = {
 | 
			
		||||
	{BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
 | 
			
		||||
	{0}};
 | 
			
		||||
 | 
			
		||||
static const struct message attr_flag_str[] =
 | 
			
		||||
	{
 | 
			
		||||
		{BGP_ATTR_FLAG_OPTIONAL, "Optional"},
 | 
			
		||||
		{BGP_ATTR_FLAG_TRANS, "Transitive"},
 | 
			
		||||
		{BGP_ATTR_FLAG_PARTIAL, "Partial"},
 | 
			
		||||
		/* bgp_attr_flags_diagnose() relies on this bit being last in
 | 
			
		||||
		   this list */
 | 
			
		||||
		{BGP_ATTR_FLAG_EXTLEN, "Extended Length"},
 | 
			
		||||
		{0}};
 | 
			
		||||
static const struct message attr_flag_str[] = {
 | 
			
		||||
	{BGP_ATTR_FLAG_OPTIONAL, "Optional"},
 | 
			
		||||
	{BGP_ATTR_FLAG_TRANS, "Transitive"},
 | 
			
		||||
	{BGP_ATTR_FLAG_PARTIAL, "Partial"},
 | 
			
		||||
	/* bgp_attr_flags_diagnose() relies on this bit being last in
 | 
			
		||||
	   this list */
 | 
			
		||||
	{BGP_ATTR_FLAG_EXTLEN, "Extended Length"},
 | 
			
		||||
	{0}};
 | 
			
		||||
 | 
			
		||||
static struct hash *cluster_hash;
 | 
			
		||||
 | 
			
		||||
@ -185,8 +184,7 @@ void cluster_unintern(struct cluster_list *cluster)
 | 
			
		||||
 | 
			
		||||
static void cluster_init(void)
 | 
			
		||||
{
 | 
			
		||||
	cluster_hash = hash_create(cluster_hash_key_make,
 | 
			
		||||
				   cluster_hash_cmp,
 | 
			
		||||
	cluster_hash = hash_create(cluster_hash_key_make, cluster_hash_cmp,
 | 
			
		||||
				   "BGP Cluster");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -363,12 +361,10 @@ static int encap_hash_cmp(const void *p1, const void *p2)
 | 
			
		||||
 | 
			
		||||
static void encap_init(void)
 | 
			
		||||
{
 | 
			
		||||
	encap_hash = hash_create(encap_hash_key_make,
 | 
			
		||||
				 encap_hash_cmp,
 | 
			
		||||
	encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
 | 
			
		||||
				 "BGP Encap Hash");
 | 
			
		||||
#if ENABLE_BGP_VNC
 | 
			
		||||
	vnc_hash = hash_create(encap_hash_key_make,
 | 
			
		||||
			       encap_hash_cmp,
 | 
			
		||||
	vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
 | 
			
		||||
			       "BGP VNC Hash");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@ -454,8 +450,7 @@ static int transit_hash_cmp(const void *p1, const void *p2)
 | 
			
		||||
 | 
			
		||||
static void transit_init(void)
 | 
			
		||||
{
 | 
			
		||||
	transit_hash = hash_create(transit_hash_key_make,
 | 
			
		||||
				   transit_hash_cmp,
 | 
			
		||||
	transit_hash = hash_create(transit_hash_key_make, transit_hash_cmp,
 | 
			
		||||
				   "BGP Transit Hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -496,7 +491,8 @@ unsigned int attrhash_key_make(void *p)
 | 
			
		||||
#define MIX3(a, b, c)	key = jhash_3words((a), (b), (c), key)
 | 
			
		||||
 | 
			
		||||
	MIX3(attr->origin, attr->nexthop.s_addr, attr->med);
 | 
			
		||||
	MIX3(attr->local_pref, attr->aggregator_as, attr->aggregator_addr.s_addr);
 | 
			
		||||
	MIX3(attr->local_pref, attr->aggregator_as,
 | 
			
		||||
	     attr->aggregator_addr.s_addr);
 | 
			
		||||
	MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr,
 | 
			
		||||
	     attr->originator_id.s_addr);
 | 
			
		||||
	MIX3(attr->tag, attr->label, attr->label_index);
 | 
			
		||||
@ -571,9 +567,8 @@ int attrhash_cmp(const void *p1, const void *p2)
 | 
			
		||||
 | 
			
		||||
static void attrhash_init(void)
 | 
			
		||||
{
 | 
			
		||||
	attrhash = hash_create(attrhash_key_make,
 | 
			
		||||
			       attrhash_cmp,
 | 
			
		||||
			       "BGP Attributes");
 | 
			
		||||
	attrhash =
 | 
			
		||||
		hash_create(attrhash_key_make, attrhash_cmp, "BGP Attributes");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -747,8 +742,8 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, u_char origin,
 | 
			
		||||
		/* If we are not shutting down ourselves and we are
 | 
			
		||||
		 * aggregating a route that contains the GSHUT community we
 | 
			
		||||
		 * need to remove that community when creating the aggregate */
 | 
			
		||||
		if (!bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN) &&
 | 
			
		||||
		    community_include(community, gshut)) {
 | 
			
		||||
		if (!bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)
 | 
			
		||||
		    && community_include(community, gshut)) {
 | 
			
		||||
			community_del_val(community, &gshut);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -840,7 +835,6 @@ void bgp_attr_undup(struct attr *new, struct attr *old)
 | 
			
		||||
 | 
			
		||||
	if (new->lcommunity != old->lcommunity)
 | 
			
		||||
		lcommunity_free(&new->lcommunity);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Free bgp attribute and aspath. */
 | 
			
		||||
@ -1661,14 +1655,14 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
 | 
			
		||||
	case BGP_ATTR_NHLEN_VPNV4:
 | 
			
		||||
		stream_getl(s); /* RD high */
 | 
			
		||||
		stream_getl(s); /* RD low */
 | 
			
		||||
		/*
 | 
			
		||||
		 * NOTE: intentional fall through
 | 
			
		||||
		 * - for consistency in rx processing
 | 
			
		||||
		 *
 | 
			
		||||
		 * The following comment is to signal GCC this intention
 | 
			
		||||
		 * and supress the warning
 | 
			
		||||
		 */
 | 
			
		||||
		/* FALLTHRU */
 | 
			
		||||
				/*
 | 
			
		||||
				 * NOTE: intentional fall through
 | 
			
		||||
				 * - for consistency in rx processing
 | 
			
		||||
				 *
 | 
			
		||||
				 * The following comment is to signal GCC this intention
 | 
			
		||||
				 * and supress the warning
 | 
			
		||||
				 */
 | 
			
		||||
	/* FALLTHRU */
 | 
			
		||||
	case BGP_ATTR_NHLEN_IPV4:
 | 
			
		||||
		stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
 | 
			
		||||
		/* Probably needed for RFC 2283 */
 | 
			
		||||
@ -1960,8 +1954,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
 | 
			
		||||
		/* alloc and copy sub-tlv */
 | 
			
		||||
		/* TBD make sure these are freed when attributes are released */
 | 
			
		||||
		tlv = XCALLOC(MTYPE_ENCAP_TLV,
 | 
			
		||||
			      sizeof(struct bgp_attr_encap_subtlv)
 | 
			
		||||
				      + sublength);
 | 
			
		||||
			      sizeof(struct bgp_attr_encap_subtlv) + sublength);
 | 
			
		||||
		tlv->type = subtype;
 | 
			
		||||
		tlv->length = sublength;
 | 
			
		||||
		stream_get(tlv->value, peer->curr, sublength);
 | 
			
		||||
@ -2715,8 +2708,8 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
 | 
			
		||||
		stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
 | 
			
		||||
	} else if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
 | 
			
		||||
		/* EVPN prefix - contents depend on type */
 | 
			
		||||
		bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
 | 
			
		||||
				       attr, addpath_encode, addpath_tx_id);
 | 
			
		||||
		bgp_evpn_encode_prefix(s, p, prd, label, num_labels, attr,
 | 
			
		||||
				       addpath_encode, addpath_tx_id);
 | 
			
		||||
	} else if (safi == SAFI_LABELED_UNICAST) {
 | 
			
		||||
		/* Prefix write with label. */
 | 
			
		||||
		stream_put_labeled_prefix(s, p, label);
 | 
			
		||||
@ -2799,8 +2792,9 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
 | 
			
		||||
	if (attrlenfield > 0xff) {
 | 
			
		||||
		/* 2-octet length field */
 | 
			
		||||
		stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
				       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
		stream_putc(s,
 | 
			
		||||
			    BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
				    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
		stream_putc(s, attrtype);
 | 
			
		||||
		stream_putw(s, attrlenfield & 0xffff);
 | 
			
		||||
	} else {
 | 
			
		||||
@ -2867,9 +2861,9 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
 | 
			
		||||
		mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
 | 
			
		||||
							vecarr, attr);
 | 
			
		||||
		bgp_packet_mpattr_prefix(s, afi, safi, p, prd,
 | 
			
		||||
					 label, num_labels,
 | 
			
		||||
					 addpath_encode, addpath_tx_id, attr);
 | 
			
		||||
		bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
 | 
			
		||||
					 num_labels, addpath_encode,
 | 
			
		||||
					 addpath_tx_id, attr);
 | 
			
		||||
		bgp_packet_mpattr_end(s, mpattrlen_pos);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -3039,14 +3033,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
	if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
 | 
			
		||||
	    && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
 | 
			
		||||
		if (attr->community->size * 4 > 255) {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_COMMUNITIES);
 | 
			
		||||
			stream_putw(s, attr->community->size * 4);
 | 
			
		||||
		} else {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_COMMUNITIES);
 | 
			
		||||
			stream_putc(s, attr->community->size * 4);
 | 
			
		||||
		}
 | 
			
		||||
@ -3060,14 +3055,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
		       PEER_FLAG_SEND_LARGE_COMMUNITY)
 | 
			
		||||
	    && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
 | 
			
		||||
		if (lcom_length(attr->lcommunity) > 255) {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
 | 
			
		||||
			stream_putw(s, lcom_length(attr->lcommunity));
 | 
			
		||||
		} else {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
 | 
			
		||||
			stream_putc(s, lcom_length(attr->lcommunity));
 | 
			
		||||
		}
 | 
			
		||||
@ -3119,14 +3115,16 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
		if (peer->sort == BGP_PEER_IBGP
 | 
			
		||||
		    || peer->sort == BGP_PEER_CONFED) {
 | 
			
		||||
			if (attr->ecommunity->size * 8 > 255) {
 | 
			
		||||
				stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						       | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
						       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
				stream_putc(s,
 | 
			
		||||
					    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						    | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
						    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
				stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
 | 
			
		||||
				stream_putw(s, attr->ecommunity->size * 8);
 | 
			
		||||
			} else {
 | 
			
		||||
				stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
				stream_putc(s,
 | 
			
		||||
					    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
				stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
 | 
			
		||||
				stream_putc(s, attr->ecommunity->size * 8);
 | 
			
		||||
			}
 | 
			
		||||
@ -3192,8 +3190,9 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
			label_index = attr->label_index;
 | 
			
		||||
 | 
			
		||||
			if (label_index != BGP_INVALID_LABEL_INDEX) {
 | 
			
		||||
				stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
				stream_putc(s,
 | 
			
		||||
					    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
						    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
				stream_putc(s, BGP_ATTR_PREFIX_SID);
 | 
			
		||||
				stream_putc(s, 10);
 | 
			
		||||
				stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
 | 
			
		||||
@ -3221,8 +3220,9 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
		 */
 | 
			
		||||
		aspath = aspath_delete_confed_seq(aspath);
 | 
			
		||||
 | 
			
		||||
		stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
				       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
		stream_putc(s,
 | 
			
		||||
			    BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
				    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
		stream_putc(s, BGP_ATTR_AS4_PATH);
 | 
			
		||||
		aspath_sizep = stream_get_endp(s);
 | 
			
		||||
		stream_putw(s, 0);
 | 
			
		||||
@ -3264,8 +3264,10 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
 | 
			
		||||
		stream_putc(s, 9); // Length
 | 
			
		||||
		stream_putc(s, 0); // Flags
 | 
			
		||||
		stream_putc(s, 6); // Tunnel type: Ingress Replication (6)
 | 
			
		||||
		stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
 | 
			
		||||
		stream_put_ipv4(s, attr->nexthop.s_addr); // Unicast tunnel endpoint IP address
 | 
			
		||||
		stream_put(s, &(attr->label),
 | 
			
		||||
			   BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
 | 
			
		||||
		stream_put_ipv4(s, attr->nexthop.s_addr);
 | 
			
		||||
		// Unicast tunnel endpoint IP address
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unknown transit attribute. */
 | 
			
		||||
@ -3311,8 +3313,7 @@ void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p, afi_t afi,
 | 
			
		||||
		num_labels = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bgp_packet_mpattr_prefix(s, afi, safi, p, prd,
 | 
			
		||||
					label, num_labels,
 | 
			
		||||
	return bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
 | 
			
		||||
					addpath_encode, addpath_tx_id, attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3422,14 +3423,15 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
 | 
			
		||||
	/* Community attribute. */
 | 
			
		||||
	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
 | 
			
		||||
		if (attr->community->size * 4 > 255) {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_COMMUNITIES);
 | 
			
		||||
			stream_putw(s, attr->community->size * 4);
 | 
			
		||||
		} else {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_COMMUNITIES);
 | 
			
		||||
			stream_putc(s, attr->community->size * 4);
 | 
			
		||||
		}
 | 
			
		||||
@ -3439,19 +3441,21 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
 | 
			
		||||
	/* Large Community attribute. */
 | 
			
		||||
	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
 | 
			
		||||
		if (lcom_length(attr->lcommunity) > 255) {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					       | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
 | 
			
		||||
					    | BGP_ATTR_FLAG_EXTLEN);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
 | 
			
		||||
			stream_putw(s, lcom_length(attr->lcommunity));
 | 
			
		||||
		} else {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
 | 
			
		||||
			stream_putc(s, lcom_length(attr->lcommunity));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		stream_put(s, attr->lcommunity->val, lcom_length(attr->lcommunity));
 | 
			
		||||
		stream_put(s, attr->lcommunity->val,
 | 
			
		||||
			   lcom_length(attr->lcommunity));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Add a MP_NLRI attribute to dump the IPv6 next hop */
 | 
			
		||||
@ -3490,8 +3494,9 @@ void bgp_dump_routes_attr(struct stream *s, struct attr *attr,
 | 
			
		||||
	/* Prefix SID */
 | 
			
		||||
	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
 | 
			
		||||
		if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
 | 
			
		||||
			stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					       | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s,
 | 
			
		||||
				    BGP_ATTR_FLAG_OPTIONAL
 | 
			
		||||
					    | BGP_ATTR_FLAG_TRANS);
 | 
			
		||||
			stream_putc(s, BGP_ATTR_PREFIX_SID);
 | 
			
		||||
			stream_putc(s, 10);
 | 
			
		||||
			stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
 | 
			
		||||
 | 
			
		||||
@ -215,10 +215,8 @@ struct transit {
 | 
			
		||||
 | 
			
		||||
/* "(void) 0" will generate a compiler error.  this is a safety check to
 | 
			
		||||
 * ensure we're not using a value that exceeds the bit size of attr->flag. */
 | 
			
		||||
#define ATTR_FLAG_BIT(X) \
 | 
			
		||||
	__builtin_choose_expr((X) >= 1 && (X) <= 64, \
 | 
			
		||||
			      1ULL << ((X) - 1), \
 | 
			
		||||
			      (void) 0)
 | 
			
		||||
#define ATTR_FLAG_BIT(X)                                                       \
 | 
			
		||||
	__builtin_choose_expr((X) >= 1 && (X) <= 64, 1ULL << ((X)-1), (void)0)
 | 
			
		||||
 | 
			
		||||
#define BGP_CLUSTER_LIST_LENGTH(attr)                                          \
 | 
			
		||||
	(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))                 \
 | 
			
		||||
@ -260,8 +258,8 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
 | 
			
		||||
				       struct bpacket_attr_vec_arr *vecarr,
 | 
			
		||||
				       struct prefix *, afi_t, safi_t,
 | 
			
		||||
				       struct peer *, struct prefix_rd *,
 | 
			
		||||
				       mpls_label_t *, u_int32_t,
 | 
			
		||||
				       int, u_int32_t);
 | 
			
		||||
				       mpls_label_t *, u_int32_t, int,
 | 
			
		||||
				       u_int32_t);
 | 
			
		||||
extern void bgp_dump_routes_attr(struct stream *, struct attr *,
 | 
			
		||||
				 struct prefix *);
 | 
			
		||||
extern int attrhash_cmp(const void *, const void *);
 | 
			
		||||
@ -320,9 +318,9 @@ extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
 | 
			
		||||
					 safi_t safi);
 | 
			
		||||
extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
 | 
			
		||||
					afi_t afi, safi_t safi,
 | 
			
		||||
					struct prefix_rd *prd,
 | 
			
		||||
					mpls_label_t *, u_int32_t,
 | 
			
		||||
					int, u_int32_t, struct attr *);
 | 
			
		||||
					struct prefix_rd *prd, mpls_label_t *,
 | 
			
		||||
					u_int32_t, int, u_int32_t,
 | 
			
		||||
					struct attr *);
 | 
			
		||||
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
 | 
			
		||||
 | 
			
		||||
static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags,
 | 
			
		||||
 | 
			
		||||
@ -106,8 +106,7 @@ char *ecom_mac2str(char *ecom_mac)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fetch router-mac from extended community */
 | 
			
		||||
void bgp_attr_rmac(struct attr *attr,
 | 
			
		||||
		   struct ethaddr *rmac)
 | 
			
		||||
void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	struct ecommunity *ecom;
 | 
			
		||||
@ -126,8 +125,8 @@ void bgp_attr_rmac(struct attr *attr,
 | 
			
		||||
		type = *pnt++;
 | 
			
		||||
		sub_type = *pnt++;
 | 
			
		||||
 | 
			
		||||
		if (!(type == ECOMMUNITY_ENCODE_EVPN &&
 | 
			
		||||
		     sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
 | 
			
		||||
		if (!(type == ECOMMUNITY_ENCODE_EVPN
 | 
			
		||||
		      && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		memcpy(rmac, pnt, ETH_ALEN);
 | 
			
		||||
@ -139,8 +138,8 @@ void bgp_attr_rmac(struct attr *attr,
 | 
			
		||||
 */
 | 
			
		||||
uint8_t bgp_attr_default_gw(struct attr *attr)
 | 
			
		||||
{
 | 
			
		||||
	struct ecommunity	*ecom;
 | 
			
		||||
	int			i;
 | 
			
		||||
	struct ecommunity *ecom;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	ecom = attr->ecommunity;
 | 
			
		||||
	if (!ecom || !ecom->size)
 | 
			
		||||
@ -149,15 +148,15 @@ uint8_t bgp_attr_default_gw(struct attr *attr)
 | 
			
		||||
	/* If there is a default gw extendd community return true otherwise
 | 
			
		||||
	 * return 0 */
 | 
			
		||||
	for (i = 0; i < ecom->size; i++) {
 | 
			
		||||
		u_char		*pnt;
 | 
			
		||||
		u_char		type, sub_type;
 | 
			
		||||
		u_char *pnt;
 | 
			
		||||
		u_char type, sub_type;
 | 
			
		||||
 | 
			
		||||
		pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
 | 
			
		||||
		type = *pnt++;
 | 
			
		||||
		sub_type = *pnt++;
 | 
			
		||||
 | 
			
		||||
		if ((type == ECOMMUNITY_ENCODE_OPAQUE
 | 
			
		||||
		      && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
 | 
			
		||||
		     && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -222,7 +222,8 @@ static void set_community_string(struct community *com, bool make_json)
 | 
			
		||||
 | 
			
		||||
		if (make_json) {
 | 
			
		||||
			json_object_string_add(com->json, "string", "");
 | 
			
		||||
			json_object_object_add(com->json, "list", json_community_list);
 | 
			
		||||
			json_object_object_add(com->json, "list",
 | 
			
		||||
					       json_community_list);
 | 
			
		||||
		}
 | 
			
		||||
		com->str = str;
 | 
			
		||||
		return;
 | 
			
		||||
@ -277,24 +278,30 @@ static void set_community_string(struct community *com, bool make_json)
 | 
			
		||||
			strcpy(pnt, "internet");
 | 
			
		||||
			pnt += strlen("internet");
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string("internet");
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_string =
 | 
			
		||||
					json_object_new_string("internet");
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case COMMUNITY_NO_EXPORT:
 | 
			
		||||
			strcpy(pnt, "no-export");
 | 
			
		||||
			pnt += strlen("no-export");
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string("noExport");
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_string =
 | 
			
		||||
					json_object_new_string("noExport");
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case COMMUNITY_NO_ADVERTISE:
 | 
			
		||||
			strcpy(pnt, "no-advertise");
 | 
			
		||||
			pnt += strlen("no-advertise");
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string("noAdvertise");
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_string =
 | 
			
		||||
					json_object_new_string("noAdvertise");
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case COMMUNITY_LOCAL_AS:
 | 
			
		||||
@ -302,15 +309,18 @@ static void set_community_string(struct community *com, bool make_json)
 | 
			
		||||
			pnt += strlen("local-AS");
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string("localAs");
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case COMMUNITY_GSHUT:
 | 
			
		||||
			strcpy(pnt, "graceful-shutdown");
 | 
			
		||||
			pnt += strlen("graceful-shutdown");
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string("gracefulShutdown");
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_string = json_object_new_string(
 | 
			
		||||
					"gracefulShutdown");
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
@ -319,7 +329,8 @@ static void set_community_string(struct community *com, bool make_json)
 | 
			
		||||
			sprintf(pnt, "%u:%d", as, val);
 | 
			
		||||
			if (make_json) {
 | 
			
		||||
				json_string = json_object_new_string(pnt);
 | 
			
		||||
				json_object_array_add(json_community_list, json_string);
 | 
			
		||||
				json_object_array_add(json_community_list,
 | 
			
		||||
						      json_string);
 | 
			
		||||
			}
 | 
			
		||||
			pnt += strlen(pnt);
 | 
			
		||||
			break;
 | 
			
		||||
@ -545,7 +556,8 @@ community_gettoken(const char *buf, enum community_token *token, u_int32_t *val)
 | 
			
		||||
			p += strlen("local-AS");
 | 
			
		||||
			return p;
 | 
			
		||||
		}
 | 
			
		||||
		if (strncmp(p, "graceful-shutdown", strlen("graceful-shutdown")) == 0) {
 | 
			
		||||
		if (strncmp(p, "graceful-shutdown", strlen("graceful-shutdown"))
 | 
			
		||||
		    == 0) {
 | 
			
		||||
			*val = COMMUNITY_GSHUT;
 | 
			
		||||
			*token = community_token_gshut;
 | 
			
		||||
			p += strlen("graceful-shutdown");
 | 
			
		||||
@ -662,10 +674,10 @@ struct hash *community_hash(void)
 | 
			
		||||
/* Initialize comminity related hash. */
 | 
			
		||||
void community_init(void)
 | 
			
		||||
{
 | 
			
		||||
	comhash = hash_create(
 | 
			
		||||
		(unsigned int (*)(void *))community_hash_make,
 | 
			
		||||
		(int (*)(const void *, const void *))community_cmp,
 | 
			
		||||
		"BGP Community Hash");
 | 
			
		||||
	comhash =
 | 
			
		||||
		hash_create((unsigned int (*)(void *))community_hash_make,
 | 
			
		||||
			    (int (*)(const void *, const void *))community_cmp,
 | 
			
		||||
			    "BGP Community Hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void community_finish(void)
 | 
			
		||||
 | 
			
		||||
@ -542,7 +542,7 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
 | 
			
		||||
	} else
 | 
			
		||||
		reuse_time = 0;
 | 
			
		||||
 | 
			
		||||
/* Making formatted timer strings. */
 | 
			
		||||
	/* Making formatted timer strings. */
 | 
			
		||||
	if (reuse_time == 0) {
 | 
			
		||||
		if (use_json)
 | 
			
		||||
			json_object_int_add(json, "reuseTimerMsecs", 0);
 | 
			
		||||
 | 
			
		||||
@ -260,8 +260,7 @@ int ecommunity_cmp(const void *arg1, const void *arg2)
 | 
			
		||||
/* Initialize Extended Comminities related hash. */
 | 
			
		||||
void ecommunity_init(void)
 | 
			
		||||
{
 | 
			
		||||
	ecomhash = hash_create(ecommunity_hash_make,
 | 
			
		||||
			       ecommunity_cmp,
 | 
			
		||||
	ecomhash = hash_create(ecommunity_hash_make, ecommunity_cmp,
 | 
			
		||||
			       "BGP ecommunity hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -690,7 +689,7 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
 | 
			
		||||
				tunneltype = ntohs(tunneltype);
 | 
			
		||||
				len = sprintf(str_buf + str_pnt, "ET:%d",
 | 
			
		||||
					      tunneltype);
 | 
			
		||||
			}  else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) {
 | 
			
		||||
			} else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) {
 | 
			
		||||
				len = sprintf(str_buf + str_pnt,
 | 
			
		||||
					      "Default Gateway");
 | 
			
		||||
			} else
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										573
									
								
								bgpd/bgp_evpn.c
									
									
									
									
									
								
							
							
						
						
									
										573
									
								
								bgpd/bgp_evpn.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -55,12 +55,30 @@ static inline vni_t label2vni(mpls_label_t *label)
 | 
			
		||||
	return vni;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int advertise_type5_routes(struct bgp *bgp_vrf,
 | 
			
		||||
					 afi_t afi)
 | 
			
		||||
{
 | 
			
		||||
	if (!bgp_vrf->l3vni)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (afi == AFI_IP &&
 | 
			
		||||
	    CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (afi == AFI_IP6 &&
 | 
			
		||||
	    CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
 | 
			
		||||
					   struct prefix *p,
 | 
			
		||||
					   struct attr *src_attr,
 | 
			
		||||
					   afi_t afi, safi_t safi);
 | 
			
		||||
extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf,
 | 
			
		||||
					  struct prefix *p,
 | 
			
		||||
					   struct attr *src_attr, afi_t afi,
 | 
			
		||||
					   safi_t safi);
 | 
			
		||||
extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
 | 
			
		||||
					  afi_t afi, safi_t safi);
 | 
			
		||||
extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi,
 | 
			
		||||
					   safi_t safi);
 | 
			
		||||
@ -73,10 +91,9 @@ extern char *bgp_evpn_label2str(mpls_label_t *label, u_int32_t num_labels,
 | 
			
		||||
extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
 | 
			
		||||
extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json);
 | 
			
		||||
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
 | 
			
		||||
				   struct prefix_rd *prd,
 | 
			
		||||
				   mpls_label_t *label, u_int32_t num_labels,
 | 
			
		||||
				   struct attr *attr, int addpath_encode,
 | 
			
		||||
				   u_int32_t addpath_tx_id);
 | 
			
		||||
				   struct prefix_rd *prd, mpls_label_t *label,
 | 
			
		||||
				   u_int32_t num_labels, struct attr *attr,
 | 
			
		||||
				   int addpath_encode, u_int32_t addpath_tx_id);
 | 
			
		||||
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
 | 
			
		||||
			       struct bgp_nlri *packet, int withdraw);
 | 
			
		||||
extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
 | 
			
		||||
@ -91,8 +108,7 @@ extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
 | 
			
		||||
				    u_char flags);
 | 
			
		||||
extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id,
 | 
			
		||||
				    struct ethaddr *rmac,
 | 
			
		||||
				    struct in_addr originator_ip,
 | 
			
		||||
				    int filter);
 | 
			
		||||
				    struct in_addr originator_ip, int filter);
 | 
			
		||||
extern int bgp_evpn_local_l3vni_del(vni_t vni, vrf_id_t vrf_id);
 | 
			
		||||
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
 | 
			
		||||
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
 | 
			
		||||
 | 
			
		||||
@ -66,29 +66,34 @@ struct bgpevpn {
 | 
			
		||||
 | 
			
		||||
	struct bgp *bgp_vrf; /* back pointer to the vrf instance */
 | 
			
		||||
 | 
			
		||||
	/* Flag to indicate if we are advertising the g/w mac ip for this VNI*/
 | 
			
		||||
	u_int8_t advertise_gw_macip;
 | 
			
		||||
					   /* Flag to indicate if we are
 | 
			
		||||
					    * advertising the g/w mac ip for
 | 
			
		||||
					    * this VNI*/
 | 
			
		||||
					   u_int8_t advertise_gw_macip;
 | 
			
		||||
 | 
			
		||||
	/* Flag to indicate if we are advertising subnet for this VNI */
 | 
			
		||||
	u_int8_t advertise_subnet;
 | 
			
		||||
					   /* Flag to indicate if we are
 | 
			
		||||
					    * advertising subnet for this VNI */
 | 
			
		||||
					   u_int8_t advertise_subnet;
 | 
			
		||||
 | 
			
		||||
	/* Id for deriving the RD automatically for this VNI */
 | 
			
		||||
	u_int16_t rd_id;
 | 
			
		||||
					   /* Id for deriving the RD
 | 
			
		||||
					    * automatically for this VNI */
 | 
			
		||||
					   u_int16_t rd_id;
 | 
			
		||||
 | 
			
		||||
	/* RD for this VNI. */
 | 
			
		||||
	struct prefix_rd prd;
 | 
			
		||||
					   /* RD for this VNI. */
 | 
			
		||||
					   struct prefix_rd prd;
 | 
			
		||||
 | 
			
		||||
	/* Route type 3 field */
 | 
			
		||||
	struct in_addr originator_ip;
 | 
			
		||||
					   /* Route type 3 field */
 | 
			
		||||
					   struct in_addr originator_ip;
 | 
			
		||||
 | 
			
		||||
	/* Import and Export RTs. */
 | 
			
		||||
	struct list *import_rtl;
 | 
			
		||||
	struct list *export_rtl;
 | 
			
		||||
					   /* Import and Export RTs. */
 | 
			
		||||
					   struct list *import_rtl;
 | 
			
		||||
					   struct list *export_rtl;
 | 
			
		||||
 | 
			
		||||
	/* Route table for EVPN routes for this VNI. */
 | 
			
		||||
	struct bgp_table *route_table;
 | 
			
		||||
					   /* Route table for EVPN routes for
 | 
			
		||||
					    * this VNI. */
 | 
			
		||||
					   struct bgp_table *route_table;
 | 
			
		||||
 | 
			
		||||
	QOBJ_FIELDS
 | 
			
		||||
					   QOBJ_FIELDS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DECLARE_QOBJ_TYPE(bgpevpn)
 | 
			
		||||
@ -124,8 +129,7 @@ struct vrf_irt_node {
 | 
			
		||||
 | 
			
		||||
static inline int is_vrf_rd_configured(struct bgp *bgp_vrf)
 | 
			
		||||
{
 | 
			
		||||
	return (CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
			   BGP_VRF_RD_CFGD));
 | 
			
		||||
	return (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int bgp_evpn_vrf_rd_matches_existing(struct bgp *bgp_vrf,
 | 
			
		||||
@ -168,10 +172,10 @@ static inline void bgpevpn_unlink_from_l3vni(struct bgpevpn *vpn)
 | 
			
		||||
	/* bail if vpn is not associated to bgp_vrf */
 | 
			
		||||
	if (!vpn->bgp_vrf)
 | 
			
		||||
		return;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
 | 
			
		||||
	listnode_delete(vpn->bgp_vrf->l2vnis, vpn);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	/* remove the backpointer to the vrf instance */
 | 
			
		||||
	vpn->bgp_vrf = NULL;
 | 
			
		||||
}
 | 
			
		||||
@ -193,8 +197,7 @@ static inline void bgpevpn_link_to_l3vni(struct bgpevpn *vpn)
 | 
			
		||||
	listnode_add_sort(bgp_vrf->l2vnis, vpn);
 | 
			
		||||
 | 
			
		||||
	/* check if we are advertising two labels for this vpn */
 | 
			
		||||
	if (!CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
		       BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY))
 | 
			
		||||
	if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY))
 | 
			
		||||
		SET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -272,18 +275,24 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
 | 
			
		||||
	if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
 | 
			
		||||
		ip->family = AF_INET;
 | 
			
		||||
		ip->prefixlen = evp->prefix.ip_prefix_length;
 | 
			
		||||
		memcpy(&(ip->u.prefix4),
 | 
			
		||||
		       &(evp->prefix.ip.ip),
 | 
			
		||||
		memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
 | 
			
		||||
		       IPV4_MAX_BYTELEN);
 | 
			
		||||
	} else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
 | 
			
		||||
		ip->family = AF_INET6;
 | 
			
		||||
		ip->prefixlen = evp->prefix.ip_prefix_length;
 | 
			
		||||
		memcpy(&(ip->u.prefix6),
 | 
			
		||||
		       &(evp->prefix.ip.ip),
 | 
			
		||||
		memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
 | 
			
		||||
		       IPV6_MAX_BYTELEN);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int is_evpn_prefix_default(struct prefix *evp)
 | 
			
		||||
{
 | 
			
		||||
	if (evp->family != AF_EVPN)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return ((evp->u.prefix_evpn.ip_prefix_length  == 0) ? 1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
 | 
			
		||||
					       struct prefix *ip)
 | 
			
		||||
{
 | 
			
		||||
@ -291,14 +300,12 @@ static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
 | 
			
		||||
	if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
 | 
			
		||||
		ip->family = AF_INET;
 | 
			
		||||
		ip->prefixlen = IPV4_MAX_BITLEN;
 | 
			
		||||
		memcpy(&(ip->u.prefix4),
 | 
			
		||||
		       &(evp->prefix.ip.ip),
 | 
			
		||||
		memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
 | 
			
		||||
		       IPV4_MAX_BYTELEN);
 | 
			
		||||
	} else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
 | 
			
		||||
		ip->family = AF_INET6;
 | 
			
		||||
		ip->prefixlen = IPV6_MAX_BITLEN;
 | 
			
		||||
		memcpy(&(ip->u.prefix6),
 | 
			
		||||
		       &(evp->prefix.ip.ip),
 | 
			
		||||
		memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
 | 
			
		||||
		       IPV6_MAX_BYTELEN);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -353,24 +360,21 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
 | 
			
		||||
	p->prefix.ip.ipaddr_v4 = originator_ip;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int advertise_type5_routes(struct bgp *bgp_vrf,
 | 
			
		||||
					 afi_t afi)
 | 
			
		||||
static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
 | 
			
		||||
					     safi_t safi)
 | 
			
		||||
{
 | 
			
		||||
	if (!bgp_vrf->l3vni)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (afi == AFI_IP &&
 | 
			
		||||
	    CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
 | 
			
		||||
	    CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (afi == AFI_IP6 &&
 | 
			
		||||
	    CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
 | 
			
		||||
	else if (afi == AFI_IP6 &&
 | 
			
		||||
		 CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			    BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*);
 | 
			
		||||
extern void evpn_rt_delete_auto(struct bgp *, vni_t, struct list *);
 | 
			
		||||
extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf,
 | 
			
		||||
						 struct ecommunity *ecomadd);
 | 
			
		||||
extern void bgp_evpn_unconfigure_export_rt_for_vrf(struct bgp *bgp_vrf,
 | 
			
		||||
 | 
			
		||||
@ -53,8 +53,7 @@ struct vni_walk_ctx {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_CUMULUS)
 | 
			
		||||
static void display_vrf_import_rt(struct vty *vty,
 | 
			
		||||
				  struct vrf_irt_node *irt,
 | 
			
		||||
static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
 | 
			
		||||
				  json_object *json)
 | 
			
		||||
{
 | 
			
		||||
	u_char *pnt;
 | 
			
		||||
@ -138,8 +137,7 @@ static void display_vrf_import_rt(struct vty *vty,
 | 
			
		||||
			json_object_array_add(
 | 
			
		||||
				json_vrfs,
 | 
			
		||||
				json_object_new_string(
 | 
			
		||||
						vrf_id_to_name(
 | 
			
		||||
							tmp_bgp_vrf->vrf_id)));
 | 
			
		||||
					vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
 | 
			
		||||
		else
 | 
			
		||||
			vty_out(vty, "  %s\n",
 | 
			
		||||
				vrf_id_to_name(tmp_bgp_vrf->vrf_id));
 | 
			
		||||
@ -151,8 +149,7 @@ static void display_vrf_import_rt(struct vty *vty,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void show_vrf_import_rt_entry(struct hash_backet *backet,
 | 
			
		||||
				     void *args[])
 | 
			
		||||
static void show_vrf_import_rt_entry(struct hash_backet *backet, void *args[])
 | 
			
		||||
{
 | 
			
		||||
	json_object *json = NULL;
 | 
			
		||||
	struct vty *vty = NULL;
 | 
			
		||||
@ -604,7 +601,7 @@ static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
			   json_object *json)
 | 
			
		||||
			     json_object *json)
 | 
			
		||||
{
 | 
			
		||||
	json_object *json_vni;
 | 
			
		||||
	json_object *json_import_rtl;
 | 
			
		||||
@ -639,8 +636,7 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
			json_vni, "rd",
 | 
			
		||||
			prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
 | 
			
		||||
	} else {
 | 
			
		||||
		vty_out(vty, "%-1s %-10u %-4s %-21s",
 | 
			
		||||
			buf1, bgp->l3vni, "L3",
 | 
			
		||||
		vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
 | 
			
		||||
			prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -748,8 +744,7 @@ static void show_vni_entry(struct hash_backet *backet, void *args[])
 | 
			
		||||
			json_vni, "rd",
 | 
			
		||||
			prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
 | 
			
		||||
	} else {
 | 
			
		||||
		vty_out(vty, "%-1s %-10u %-4s %-21s",
 | 
			
		||||
			buf1, vpn->vni, "L2",
 | 
			
		||||
		vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
 | 
			
		||||
			prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1430,8 +1425,7 @@ DEFUN(evpnrt5_network,
 | 
			
		||||
 | 
			
		||||
	return bgp_static_set_safi(
 | 
			
		||||
		AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
 | 
			
		||||
		argv[idx_route_distinguisher]->arg, argv[idx_label]->arg,
 | 
			
		||||
		NULL,
 | 
			
		||||
		argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
 | 
			
		||||
		BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
 | 
			
		||||
		argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
 | 
			
		||||
		argv[idx_routermac]->arg);
 | 
			
		||||
@ -1632,8 +1626,7 @@ static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
 | 
			
		||||
/*
 | 
			
		||||
 * Configure RD for VRF
 | 
			
		||||
 */
 | 
			
		||||
static void evpn_configure_vrf_rd(struct bgp *bgp_vrf,
 | 
			
		||||
				  struct prefix_rd *rd)
 | 
			
		||||
static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
 | 
			
		||||
{
 | 
			
		||||
	/* If we have already advertise type-5 routes with a diffrent RD, we
 | 
			
		||||
	 * have to delete and withdraw them firs
 | 
			
		||||
@ -1777,8 +1770,7 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
 | 
			
		||||
 * Display import RT mapping to VRFs (vty handler)
 | 
			
		||||
 * bgp_def: default bgp instance
 | 
			
		||||
 */
 | 
			
		||||
static void evpn_show_vrf_import_rts(struct vty *vty,
 | 
			
		||||
				     struct bgp *bgp_def,
 | 
			
		||||
static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_def,
 | 
			
		||||
				     json_object *json)
 | 
			
		||||
{
 | 
			
		||||
	void *args[2];
 | 
			
		||||
@ -1787,8 +1779,8 @@ static void evpn_show_vrf_import_rts(struct vty *vty,
 | 
			
		||||
	args[1] = json;
 | 
			
		||||
 | 
			
		||||
	hash_iterate(bgp_def->vrf_import_rt_hash,
 | 
			
		||||
		     (void (*)(struct hash_backet *, void *))
 | 
			
		||||
		     show_vrf_import_rt_entry,
 | 
			
		||||
		     (void (*)(struct hash_backet *,
 | 
			
		||||
			       void *))show_vrf_import_rt_entry,
 | 
			
		||||
		     args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2364,8 +2356,7 @@ static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
	if (!json) {
 | 
			
		||||
		vty_out(vty, "Flags: * - Kernel\n");
 | 
			
		||||
		vty_out(vty, "  %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
 | 
			
		||||
			"Type", "RD", "Import RT",
 | 
			
		||||
			"Export RT", "Tenant VRF");
 | 
			
		||||
			"Type", "RD", "Import RT", "Export RT", "Tenant VRF");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* print all L2 VNIS */
 | 
			
		||||
@ -2378,7 +2369,6 @@ static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
	/* print all L3 VNIs */
 | 
			
		||||
	for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
 | 
			
		||||
		show_l3vni_entry(vty, bgp_temp, json);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -2426,6 +2416,48 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp,
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * evpn - enable advertisement of default g/w
 | 
			
		||||
 */
 | 
			
		||||
static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
 | 
			
		||||
					       afi_t afi, int add)
 | 
			
		||||
{
 | 
			
		||||
	struct prefix ip_prefix;
 | 
			
		||||
	safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
 | 
			
		||||
 | 
			
		||||
	/* form the default prefix 0.0.0.0/0 */
 | 
			
		||||
	memset(&ip_prefix, 0, sizeof(struct prefix));
 | 
			
		||||
	ip_prefix.family = afi2family(afi);
 | 
			
		||||
	ip_prefix.prefixlen = 0;
 | 
			
		||||
 | 
			
		||||
	if (add) {
 | 
			
		||||
		/* bail if we are already advertising default route */
 | 
			
		||||
		if (evpn_default_originate_set(bgp_vrf, afi, safi))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		if (afi == AFI_IP)
 | 
			
		||||
			SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
				 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
 | 
			
		||||
		else if (afi == AFI_IP6)
 | 
			
		||||
			SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
				 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
 | 
			
		||||
		bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
 | 
			
		||||
					       NULL, afi, safi);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* bail out if we havent advertised the default route */
 | 
			
		||||
		if (!evpn_default_originate_set(bgp_vrf, afi, safi))
 | 
			
		||||
			return;
 | 
			
		||||
		if (afi == AFI_IP)
 | 
			
		||||
			UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
				   BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
 | 
			
		||||
		else if (afi == AFI_IP6)
 | 
			
		||||
			UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
				   BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
 | 
			
		||||
		bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
 | 
			
		||||
					      afi, safi);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * evpn - enable advertisement of default g/w
 | 
			
		||||
 */
 | 
			
		||||
@ -2442,8 +2474,7 @@ static void evpn_set_advertise_subnet(struct bgp *bgp,
 | 
			
		||||
/*
 | 
			
		||||
 * evpn - disable advertisement of default g/w
 | 
			
		||||
 */
 | 
			
		||||
static void evpn_unset_advertise_subnet(struct bgp *bgp,
 | 
			
		||||
					struct bgpevpn *vpn)
 | 
			
		||||
static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
 | 
			
		||||
{
 | 
			
		||||
	if (!vpn->advertise_subnet)
 | 
			
		||||
		return;
 | 
			
		||||
@ -2624,6 +2655,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (bgp_evpn_default_originate,
 | 
			
		||||
       bgp_evpn_default_originate_cmd,
 | 
			
		||||
       "default-originate <ipv4 | ipv6>",
 | 
			
		||||
       "originate a default route\n"
 | 
			
		||||
       "ipv4 address family\n"
 | 
			
		||||
       "ipv6 address family\n")
 | 
			
		||||
{
 | 
			
		||||
	afi_t afi = 0;
 | 
			
		||||
	int idx_afi = 0;
 | 
			
		||||
	struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
 | 
			
		||||
 | 
			
		||||
	if (!bgp_vrf)
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
 | 
			
		||||
	evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (no_bgp_evpn_default_originate,
 | 
			
		||||
       no_bgp_evpn_default_originate_cmd,
 | 
			
		||||
       "no default-originate <ipv4 | ipv6>",
 | 
			
		||||
       NO_STR
 | 
			
		||||
       "withdraw a default route\n"
 | 
			
		||||
       "ipv4 address family\n"
 | 
			
		||||
       "ipv6 address family\n")
 | 
			
		||||
{
 | 
			
		||||
	afi_t afi = 0;
 | 
			
		||||
	int idx_afi = 0;
 | 
			
		||||
	struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
 | 
			
		||||
 | 
			
		||||
	if (!bgp_vrf)
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
 | 
			
		||||
	evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (bgp_evpn_advertise_vni_subnet,
 | 
			
		||||
       bgp_evpn_advertise_vni_subnet_cmd,
 | 
			
		||||
       "advertise-subnet",
 | 
			
		||||
@ -2643,14 +2711,6 @@ DEFUN (bgp_evpn_advertise_vni_subnet,
 | 
			
		||||
	if (!bgp_vrf)
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
 | 
			
		||||
	if (!(advertise_type5_routes(bgp_vrf, AFI_IP) ||
 | 
			
		||||
	      advertise_type5_routes(bgp_vrf, AFI_IP6))) {
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"%%Please enable ip prefix advertisement under l2vpn evpn in %s",
 | 
			
		||||
			vrf_id_to_name(bgp_vrf->vrf_id));
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	evpn_set_advertise_subnet(bgp, vpn);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@ -2699,7 +2759,8 @@ DEFUN (bgp_evpn_advertise_type5,
 | 
			
		||||
		if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
 | 
			
		||||
			rmap_changed = 1;
 | 
			
		||||
		else if (strcmp(argv[idx_rmap + 1]->arg,
 | 
			
		||||
				bgp_vrf->adv_cmd_rmap[afi][safi].name) != 0)
 | 
			
		||||
				bgp_vrf->adv_cmd_rmap[afi][safi].name)
 | 
			
		||||
			 != 0)
 | 
			
		||||
			rmap_changed = 1;
 | 
			
		||||
	} else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
 | 
			
		||||
		rmap_changed = 1;
 | 
			
		||||
@ -2722,21 +2783,23 @@ DEFUN (bgp_evpn_advertise_type5,
 | 
			
		||||
		/* if we are already advertising ipv4 prefix as type-5
 | 
			
		||||
		 * nothing to do
 | 
			
		||||
		 */
 | 
			
		||||
		if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
						BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
 | 
			
		||||
		if (!rmap_changed &&
 | 
			
		||||
		    CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			       BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
 | 
			
		||||
			return CMD_WARNING;
 | 
			
		||||
		SET_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
			 BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
 | 
			
		||||
		SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
 | 
			
		||||
	} else {
 | 
			
		||||
 | 
			
		||||
		/* if we are already advertising ipv6 prefix as type-5
 | 
			
		||||
		 * nothing to do
 | 
			
		||||
		 */
 | 
			
		||||
		if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
						BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
 | 
			
		||||
		if (!rmap_changed &&
 | 
			
		||||
		    CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			       BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
 | 
			
		||||
			return CMD_WARNING;
 | 
			
		||||
		SET_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
			 BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
 | 
			
		||||
		SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rmap_changed) {
 | 
			
		||||
@ -2752,8 +2815,7 @@ DEFUN (bgp_evpn_advertise_type5,
 | 
			
		||||
	/* set the route-map for advertise command */
 | 
			
		||||
	if (ret && argv[idx_rmap + 1]->arg) {
 | 
			
		||||
		bgp_vrf->adv_cmd_rmap[afi][safi].name =
 | 
			
		||||
			XSTRDUP(MTYPE_ROUTE_MAP_NAME,
 | 
			
		||||
				argv[idx_rmap + 1]->arg);
 | 
			
		||||
			XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
 | 
			
		||||
		bgp_vrf->adv_cmd_rmap[afi][safi].map =
 | 
			
		||||
			route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
 | 
			
		||||
	}
 | 
			
		||||
@ -2780,7 +2842,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
 | 
			
		||||
	argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
 | 
			
		||||
	argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
 | 
			
		||||
 | 
			
		||||
	if (!(afi == AFI_IP) || (afi == AFI_IP6)) {
 | 
			
		||||
	if (!(afi == AFI_IP || afi == AFI_IP6)) {
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"%%only ipv4 or ipv6 address families are supported");
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
@ -2794,25 +2856,25 @@ DEFUN (no_bgp_evpn_advertise_type5,
 | 
			
		||||
 | 
			
		||||
	if (afi == AFI_IP) {
 | 
			
		||||
 | 
			
		||||
		/* if we are already advertising ipv4 prefix as type-5
 | 
			
		||||
		/* if we are not advertising ipv4 prefix as type-5
 | 
			
		||||
		 * nothing to do
 | 
			
		||||
		 */
 | 
			
		||||
		if (CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
			       BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
 | 
			
		||||
		if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			       BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
 | 
			
		||||
			bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
 | 
			
		||||
			UNSET_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
				   BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
 | 
			
		||||
			UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
				   BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
 | 
			
		||||
		/* if we are already advertising ipv6 prefix as type-5
 | 
			
		||||
		/* if we are not advertising ipv6 prefix as type-5
 | 
			
		||||
		 * nothing to do
 | 
			
		||||
		 */
 | 
			
		||||
		if (CHECK_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
			       BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
 | 
			
		||||
		if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
			       BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
 | 
			
		||||
			bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
 | 
			
		||||
			UNSET_FLAG(bgp_vrf->vrf_flags,
 | 
			
		||||
				   BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
 | 
			
		||||
				   BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -2879,16 +2941,15 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
 | 
			
		||||
						       ? "Enabled"
 | 
			
		||||
						       : "Disabled");
 | 
			
		||||
			json_object_string_add(json, "advertiseAllVnis",
 | 
			
		||||
					       is_evpn_enabled()
 | 
			
		||||
						       ? "Enabled"
 | 
			
		||||
						       : "Disabled");
 | 
			
		||||
					       is_evpn_enabled() ? "Enabled"
 | 
			
		||||
								 : "Disabled");
 | 
			
		||||
			json_object_int_add(json, "numVnis", num_vnis);
 | 
			
		||||
			json_object_int_add(json, "numL2Vnis", num_l2vnis);
 | 
			
		||||
			json_object_int_add(json, "numL3Vnis", num_l3vnis);
 | 
			
		||||
		} else {
 | 
			
		||||
			vty_out(vty, "Advertise Gateway Macip: %s\n",
 | 
			
		||||
				bgp_def->advertise_gw_macip ? "Enabled"
 | 
			
		||||
							: "Disabled");
 | 
			
		||||
							    : "Disabled");
 | 
			
		||||
			vty_out(vty, "Advertise All VNI flag: %s\n",
 | 
			
		||||
				is_evpn_enabled() ? "Enabled" : "Disabled");
 | 
			
		||||
			vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
 | 
			
		||||
@ -3478,8 +3539,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
 | 
			
		||||
 | 
			
		||||
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
 | 
			
		||||
	     "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
 | 
			
		||||
	     "Summary of BGP neighbor status\n"
 | 
			
		||||
	     JSON_STR)
 | 
			
		||||
	     "Summary of BGP neighbor status\n" JSON_STR)
 | 
			
		||||
 | 
			
		||||
ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
 | 
			
		||||
	     "show bgp evpn route [type <macip|multicast>]",
 | 
			
		||||
@ -3855,13 +3915,11 @@ DEFUN (show_bgp_vrf_l3vni_info,
 | 
			
		||||
	bgp = bgp_lookup_by_name(name);
 | 
			
		||||
	if (!bgp) {
 | 
			
		||||
		if (!uj)
 | 
			
		||||
			vty_out(vty, "BGP instance for VRF %s not found",
 | 
			
		||||
				name);
 | 
			
		||||
			vty_out(vty, "BGP instance for VRF %s not found", name);
 | 
			
		||||
		else {
 | 
			
		||||
			json_object_string_add(json, "warning",
 | 
			
		||||
					       "BGP instance not found");
 | 
			
		||||
			vty_out(vty, "%s\n",
 | 
			
		||||
				json_object_to_json_string(json));
 | 
			
		||||
			vty_out(vty, "%s\n", json_object_to_json_string(json));
 | 
			
		||||
			json_object_free(json);
 | 
			
		||||
		}
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
@ -3869,15 +3927,15 @@ DEFUN (show_bgp_vrf_l3vni_info,
 | 
			
		||||
 | 
			
		||||
	if (!json) {
 | 
			
		||||
		vty_out(vty, "BGP VRF: %s\n", name);
 | 
			
		||||
		vty_out(vty, "  Local-Ip: %s\n",
 | 
			
		||||
			inet_ntoa(bgp->originator_ip));
 | 
			
		||||
		vty_out(vty, "  Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
 | 
			
		||||
		vty_out(vty, "  L3-VNI: %u\n", bgp->l3vni);
 | 
			
		||||
		vty_out(vty, "  Rmac: %s\n",
 | 
			
		||||
			prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
 | 
			
		||||
		vty_out(vty, "  VNI Filter: %s\n",
 | 
			
		||||
			CHECK_FLAG(bgp->vrf_flags,
 | 
			
		||||
				   BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY) ?
 | 
			
		||||
				"prefix-routes-only" : "none");
 | 
			
		||||
				   BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
 | 
			
		||||
				? "prefix-routes-only"
 | 
			
		||||
				: "none");
 | 
			
		||||
		vty_out(vty, "  L2-VNI List:\n");
 | 
			
		||||
		vty_out(vty, "    ");
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
 | 
			
		||||
@ -3900,13 +3958,15 @@ DEFUN (show_bgp_vrf_l3vni_info,
 | 
			
		||||
		json_object_string_add(json, "local-ip",
 | 
			
		||||
				       inet_ntoa(bgp->originator_ip));
 | 
			
		||||
		json_object_int_add(json, "l3vni", bgp->l3vni);
 | 
			
		||||
		json_object_string_add(json, "rmac",
 | 
			
		||||
				       prefix_mac2str(&bgp->rmac, buf,
 | 
			
		||||
						      sizeof(buf)));
 | 
			
		||||
		json_object_string_add(json, "vniFilter",
 | 
			
		||||
				       CHECK_FLAG(bgp->vrf_flags,
 | 
			
		||||
						  BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
 | 
			
		||||
				       ? "prefix-routes-only" : "none");
 | 
			
		||||
		json_object_string_add(
 | 
			
		||||
			json, "rmac",
 | 
			
		||||
			prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
 | 
			
		||||
		json_object_string_add(
 | 
			
		||||
			json, "vniFilter",
 | 
			
		||||
			CHECK_FLAG(bgp->vrf_flags,
 | 
			
		||||
				   BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
 | 
			
		||||
				? "prefix-routes-only"
 | 
			
		||||
				: "none");
 | 
			
		||||
		/* list of l2vnis */
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
 | 
			
		||||
			json_object_array_add(json_vnis,
 | 
			
		||||
@ -3915,21 +3975,20 @@ DEFUN (show_bgp_vrf_l3vni_info,
 | 
			
		||||
 | 
			
		||||
		/* export rts */
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
 | 
			
		||||
			json_object_array_add(json_export_rts,
 | 
			
		||||
					      json_object_new_string(
 | 
			
		||||
							ecommunity_str(ecom)));
 | 
			
		||||
			json_object_array_add(
 | 
			
		||||
				json_export_rts,
 | 
			
		||||
				json_object_new_string(ecommunity_str(ecom)));
 | 
			
		||||
		json_object_object_add(json, "export-rts", json_export_rts);
 | 
			
		||||
 | 
			
		||||
		/* import rts */
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
 | 
			
		||||
			json_object_array_add(json_import_rts,
 | 
			
		||||
					      json_object_new_string(
 | 
			
		||||
							ecommunity_str(ecom)));
 | 
			
		||||
			json_object_array_add(
 | 
			
		||||
				json_import_rts,
 | 
			
		||||
				json_object_new_string(ecommunity_str(ecom)));
 | 
			
		||||
		json_object_object_add(json, "import-rts", json_import_rts);
 | 
			
		||||
		json_object_string_add(
 | 
			
		||||
			json, "rd",
 | 
			
		||||
			prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (uj) {
 | 
			
		||||
@ -3979,8 +4038,7 @@ DEFUN (bgp_evpn_vrf_rt,
 | 
			
		||||
		ecommunity_str(ecomadd);
 | 
			
		||||
 | 
			
		||||
		/* Do nothing if we already have this import route-target */
 | 
			
		||||
		if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
 | 
			
		||||
						  ecomadd))
 | 
			
		||||
		if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
 | 
			
		||||
			bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -3995,8 +4053,7 @@ DEFUN (bgp_evpn_vrf_rt,
 | 
			
		||||
		ecommunity_str(ecomadd);
 | 
			
		||||
 | 
			
		||||
		/* Do nothing if we already have this export route-target */
 | 
			
		||||
		if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
 | 
			
		||||
						  ecomadd))
 | 
			
		||||
		if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
 | 
			
		||||
			bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -4324,12 +4381,22 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
 | 
			
		||||
	if (bgp->advertise_gw_macip)
 | 
			
		||||
		vty_out(vty, "  advertise-default-gw\n");
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
 | 
			
		||||
	if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
 | 
			
		||||
		vty_out(vty, "  advertise ipv4 unicast\n");
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
 | 
			
		||||
	if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
 | 
			
		||||
		vty_out(vty, "  advertise ipv6 unicast\n");
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
 | 
			
		||||
		vty_out(vty, "  default-originate ipv4\n");
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
 | 
			
		||||
		       BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
 | 
			
		||||
		vty_out(vty, "  default-originate ipv6\n");
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
 | 
			
		||||
		vty_out(vty, "   rd %s\n",
 | 
			
		||||
			prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
 | 
			
		||||
@ -4344,8 +4411,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
 | 
			
		||||
				       ecom)) {
 | 
			
		||||
			ecom_str = ecommunity_ecom2str(
 | 
			
		||||
				ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 | 
			
		||||
			vty_out(vty, "   route-target import %s\n",
 | 
			
		||||
				ecom_str);
 | 
			
		||||
			vty_out(vty, "   route-target import %s\n", ecom_str);
 | 
			
		||||
			XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -4360,8 +4426,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
 | 
			
		||||
				       ecom)) {
 | 
			
		||||
			ecom_str = ecommunity_ecom2str(
 | 
			
		||||
				ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 | 
			
		||||
			vty_out(vty, "   route-target export %s\n",
 | 
			
		||||
				ecom_str);
 | 
			
		||||
			vty_out(vty, "   route-target export %s\n", ecom_str);
 | 
			
		||||
			XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -4394,6 +4459,8 @@ void bgp_ethernetvpn_init(void)
 | 
			
		||||
	install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
 | 
			
		||||
	install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
 | 
			
		||||
	install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
 | 
			
		||||
	install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
 | 
			
		||||
	install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
 | 
			
		||||
 | 
			
		||||
	/* "show bgp l2vpn evpn" commands. */
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
 | 
			
		||||
 | 
			
		||||
@ -1056,8 +1056,8 @@ int bgp_stop(struct peer *peer)
 | 
			
		||||
			UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
 | 
			
		||||
 | 
			
		||||
			for (afi = AFI_IP; afi < AFI_MAX; afi++)
 | 
			
		||||
				for (safi = SAFI_UNICAST;
 | 
			
		||||
				     safi <= SAFI_MPLS_VPN; safi++)
 | 
			
		||||
				for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN;
 | 
			
		||||
				     safi++)
 | 
			
		||||
					peer->nsf[afi][safi] = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -1377,12 +1377,11 @@ int bgp_start(struct peer *peer)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (peer->bgp &&
 | 
			
		||||
	    peer->bgp->vrf_id == VRF_UNKNOWN) {
 | 
			
		||||
	if (peer->bgp && peer->bgp->vrf_id == VRF_UNKNOWN) {
 | 
			
		||||
		if (bgp_debug_neighbor_events(peer))
 | 
			
		||||
			zlog_err(
 | 
			
		||||
				 "%s [FSM] In a VRF that is not initialised yet",
 | 
			
		||||
				 peer->host);
 | 
			
		||||
				"%s [FSM] In a VRF that is not initialised yet",
 | 
			
		||||
				peer->host);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1518,9 +1517,8 @@ static int bgp_establish(struct peer *peer)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (other == peer)
 | 
			
		||||
		ret =
 | 
			
		||||
			1; /* bgp_establish specific code when xfer_conn
 | 
			
		||||
			      happens. */
 | 
			
		||||
		ret = 1; /* bgp_establish specific code when xfer_conn
 | 
			
		||||
			    happens. */
 | 
			
		||||
 | 
			
		||||
	/* Reset capability open status flag. */
 | 
			
		||||
	if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
 | 
			
		||||
 | 
			
		||||
@ -290,8 +290,8 @@ static uint16_t bgp_write(struct peer *peer)
 | 
			
		||||
	uint16_t status = 0;
 | 
			
		||||
	uint32_t wpkt_quanta_old;
 | 
			
		||||
 | 
			
		||||
	wpkt_quanta_old =
 | 
			
		||||
	    atomic_load_explicit(&peer->bgp->wpkt_quanta, memory_order_relaxed);
 | 
			
		||||
	wpkt_quanta_old = atomic_load_explicit(&peer->bgp->wpkt_quanta,
 | 
			
		||||
					       memory_order_relaxed);
 | 
			
		||||
 | 
			
		||||
	while (count < wpkt_quanta_old && (s = stream_fifo_head(peer->obuf))) {
 | 
			
		||||
		int writenum;
 | 
			
		||||
@ -402,7 +402,7 @@ static uint16_t bgp_read(struct peer *peer)
 | 
			
		||||
	/* EAGAIN or EWOULDBLOCK; come back later */
 | 
			
		||||
	if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
 | 
			
		||||
		SET_FLAG(status, BGP_IO_TRANS_ERR);
 | 
			
		||||
	/* Fatal error; tear down session */
 | 
			
		||||
		/* Fatal error; tear down session */
 | 
			
		||||
	} else if (nbytes < 0) {
 | 
			
		||||
		zlog_err("%s [Error] bgp_read_packet error: %s", peer->host,
 | 
			
		||||
			 safe_strerror(errno));
 | 
			
		||||
@ -417,7 +417,7 @@ static uint16_t bgp_read(struct peer *peer)
 | 
			
		||||
 | 
			
		||||
		BGP_EVENT_ADD(peer, TCP_fatal_error);
 | 
			
		||||
		SET_FLAG(status, BGP_IO_FATAL_ERR);
 | 
			
		||||
	/* Received EOF / TCP session closed */
 | 
			
		||||
		/* Received EOF / TCP session closed */
 | 
			
		||||
	} else if (nbytes == 0) {
 | 
			
		||||
		if (bgp_debug_neighbor_events(peer))
 | 
			
		||||
			zlog_debug("%s [Event] BGP connection closed fd %d",
 | 
			
		||||
@ -485,8 +485,8 @@ static bool validate_header(struct peer *peer)
 | 
			
		||||
				   type);
 | 
			
		||||
 | 
			
		||||
		bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR,
 | 
			
		||||
					  BGP_NOTIFY_HEADER_BAD_MESTYPE,
 | 
			
		||||
					  &type, 1);
 | 
			
		||||
					  BGP_NOTIFY_HEADER_BAD_MESTYPE, &type,
 | 
			
		||||
					  1);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -506,14 +506,14 @@ static bool validate_header(struct peer *peer)
 | 
			
		||||
			zlog_debug("%s bad message length - %d for %s",
 | 
			
		||||
				   peer->host, size,
 | 
			
		||||
				   type == 128 ? "ROUTE-REFRESH"
 | 
			
		||||
					       : bgp_type_str[(int) type]);
 | 
			
		||||
					       : bgp_type_str[(int)type]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint16_t nsize = htons(size);
 | 
			
		||||
 | 
			
		||||
		bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR,
 | 
			
		||||
					  BGP_NOTIFY_HEADER_BAD_MESLEN,
 | 
			
		||||
					  (unsigned char *) &nsize, 2);
 | 
			
		||||
					  (unsigned char *)&nsize, 2);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -174,13 +174,11 @@ struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
 | 
			
		||||
				    struct lcommunity *lcom2)
 | 
			
		||||
{
 | 
			
		||||
	if (lcom1->val)
 | 
			
		||||
		lcom1->val =
 | 
			
		||||
			XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val,
 | 
			
		||||
				 lcom_length(lcom1) + lcom_length(lcom2));
 | 
			
		||||
		lcom1->val = XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val,
 | 
			
		||||
				      lcom_length(lcom1) + lcom_length(lcom2));
 | 
			
		||||
	else
 | 
			
		||||
		lcom1->val =
 | 
			
		||||
			XMALLOC(MTYPE_LCOMMUNITY_VAL,
 | 
			
		||||
				lcom_length(lcom1) + lcom_length(lcom2));
 | 
			
		||||
		lcom1->val = XMALLOC(MTYPE_LCOMMUNITY_VAL,
 | 
			
		||||
				     lcom_length(lcom1) + lcom_length(lcom2));
 | 
			
		||||
 | 
			
		||||
	memcpy(lcom1->val + lcom_length(lcom1), lcom2->val, lcom_length(lcom2));
 | 
			
		||||
	lcom1->size += lcom2->size;
 | 
			
		||||
@ -243,8 +241,7 @@ int lcommunity_cmp(const void *arg1, const void *arg2)
 | 
			
		||||
	const struct lcommunity *lcom2 = arg2;
 | 
			
		||||
 | 
			
		||||
	return (lcom1->size == lcom2->size
 | 
			
		||||
		&& memcmp(lcom1->val, lcom2->val, lcom_length(lcom1))
 | 
			
		||||
			   == 0);
 | 
			
		||||
		&& memcmp(lcom1->val, lcom2->val, lcom_length(lcom1)) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return communities hash.  */
 | 
			
		||||
@ -256,8 +253,7 @@ struct hash *lcommunity_hash(void)
 | 
			
		||||
/* Initialize Large Comminities related hash. */
 | 
			
		||||
void lcommunity_init(void)
 | 
			
		||||
{
 | 
			
		||||
	lcomhash = hash_create(lcommunity_hash_make,
 | 
			
		||||
			       lcommunity_cmp,
 | 
			
		||||
	lcomhash = hash_create(lcommunity_hash_make, lcommunity_cmp,
 | 
			
		||||
			       "BGP lcommunity hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -462,8 +458,8 @@ int lcommunity_match(const struct lcommunity *lcom1,
 | 
			
		||||
 | 
			
		||||
	/* Every community on com2 needs to be on com1 for this to match */
 | 
			
		||||
	while (i < lcom1->size && j < lcom2->size) {
 | 
			
		||||
		if (memcmp(lcom1->val + (i * LCOMMUNITY_SIZE), lcom2->val + (j * LCOMMUNITY_SIZE),
 | 
			
		||||
			   LCOMMUNITY_SIZE)
 | 
			
		||||
		if (memcmp(lcom1->val + (i * LCOMMUNITY_SIZE),
 | 
			
		||||
			   lcom2->val + (j * LCOMMUNITY_SIZE), LCOMMUNITY_SIZE)
 | 
			
		||||
		    == 0)
 | 
			
		||||
			j++;
 | 
			
		||||
		i++;
 | 
			
		||||
@ -499,8 +495,8 @@ void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr)
 | 
			
		||||
 | 
			
		||||
			if (lcom->size > 0)
 | 
			
		||||
				lcom->val =
 | 
			
		||||
					XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom->val,
 | 
			
		||||
						 lcom_length(lcom));
 | 
			
		||||
					XREALLOC(MTYPE_LCOMMUNITY_VAL,
 | 
			
		||||
						 lcom->val, lcom_length(lcom));
 | 
			
		||||
			else {
 | 
			
		||||
				XFREE(MTYPE_LCOMMUNITY_VAL, lcom->val);
 | 
			
		||||
				lcom->val = NULL;
 | 
			
		||||
 | 
			
		||||
@ -105,9 +105,8 @@ static struct quagga_signal_t bgp_signals[] = {
 | 
			
		||||
static int retain_mode = 0;
 | 
			
		||||
 | 
			
		||||
/* privileges */
 | 
			
		||||
static zebra_capabilities_t _caps_p[] = {
 | 
			
		||||
	ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN
 | 
			
		||||
};
 | 
			
		||||
static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_NET_RAW,
 | 
			
		||||
					 ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN};
 | 
			
		||||
 | 
			
		||||
struct zebra_privs_t bgpd_privs = {
 | 
			
		||||
#if defined(FRR_USER) && defined(FRR_GROUP)
 | 
			
		||||
 | 
			
		||||
@ -141,16 +141,17 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
 | 
			
		||||
					&bi2->attr->mp_nexthop_global);
 | 
			
		||||
				break;
 | 
			
		||||
			case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
 | 
			
		||||
				addr1 = (bi1->attr->mp_nexthop_prefer_global) ?
 | 
			
		||||
					bi1->attr->mp_nexthop_global
 | 
			
		||||
					: bi1->attr->mp_nexthop_local;
 | 
			
		||||
				addr2 = (bi2->attr->mp_nexthop_prefer_global) ?
 | 
			
		||||
					bi2->attr->mp_nexthop_global
 | 
			
		||||
					: bi2->attr->mp_nexthop_local;
 | 
			
		||||
				addr1 = (bi1->attr->mp_nexthop_prefer_global)
 | 
			
		||||
						? bi1->attr->mp_nexthop_global
 | 
			
		||||
						: bi1->attr->mp_nexthop_local;
 | 
			
		||||
				addr2 = (bi2->attr->mp_nexthop_prefer_global)
 | 
			
		||||
						? bi2->attr->mp_nexthop_global
 | 
			
		||||
						: bi2->attr->mp_nexthop_local;
 | 
			
		||||
 | 
			
		||||
				if (!bi1->attr->mp_nexthop_prefer_global &&
 | 
			
		||||
				    !bi2->attr->mp_nexthop_prefer_global)
 | 
			
		||||
					compare = !bgp_interface_same(bi1->peer->ifp, bi2->peer->ifp);
 | 
			
		||||
				if (!bi1->attr->mp_nexthop_prefer_global
 | 
			
		||||
				    && !bi2->attr->mp_nexthop_prefer_global)
 | 
			
		||||
					compare = !bgp_interface_same(
 | 
			
		||||
						bi1->peer->ifp, bi2->peer->ifp);
 | 
			
		||||
 | 
			
		||||
				if (!compare)
 | 
			
		||||
					compare = IPV6_ADDR_CMP(&addr1, &addr2);
 | 
			
		||||
 | 
			
		||||
@ -447,8 +447,8 @@ static char *bgp_get_bound_name(struct peer *peer)
 | 
			
		||||
{
 | 
			
		||||
	char *name = NULL;
 | 
			
		||||
 | 
			
		||||
	if ((peer->bgp->vrf_id == VRF_DEFAULT) &&
 | 
			
		||||
	    !peer->ifname && !peer->conf_if)
 | 
			
		||||
	if ((peer->bgp->vrf_id == VRF_DEFAULT) && !peer->ifname
 | 
			
		||||
	    && !peer->conf_if)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (peer->su.sa.sa_family != AF_INET
 | 
			
		||||
@ -673,8 +673,7 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
 | 
			
		||||
	listener->fd = sock;
 | 
			
		||||
 | 
			
		||||
	/* this socket needs a change of ns. record bgp back pointer */
 | 
			
		||||
	if (bgp->vrf_id != VRF_DEFAULT &&
 | 
			
		||||
	    vrf_is_mapped_on_netns(bgp->vrf_id))
 | 
			
		||||
	if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
 | 
			
		||||
		listener->bgp = bgp;
 | 
			
		||||
 | 
			
		||||
	memcpy(&listener->su, sa, salen);
 | 
			
		||||
@ -704,8 +703,8 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
 | 
			
		||||
 | 
			
		||||
	if (bgpd_privs.change(ZPRIVS_RAISE))
 | 
			
		||||
		zlog_err("Can't raise privileges");
 | 
			
		||||
	ret = vrf_getaddrinfo(address, port_str, &req,
 | 
			
		||||
			      &ainfo_save, bgp->vrf_id);
 | 
			
		||||
	ret = vrf_getaddrinfo(address, port_str, &req, &ainfo_save,
 | 
			
		||||
			      bgp->vrf_id);
 | 
			
		||||
	if (bgpd_privs.change(ZPRIVS_LOWER))
 | 
			
		||||
		zlog_err("Can't lower privileges");
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
@ -723,8 +722,7 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
 | 
			
		||||
		if (bgpd_privs.change(ZPRIVS_RAISE))
 | 
			
		||||
			zlog_err("Can't raise privileges");
 | 
			
		||||
		sock = vrf_socket(ainfo->ai_family, ainfo->ai_socktype,
 | 
			
		||||
				  ainfo->ai_protocol, bgp->vrf_id,
 | 
			
		||||
				  NULL);
 | 
			
		||||
				  ainfo->ai_protocol, bgp->vrf_id, NULL);
 | 
			
		||||
		if (bgpd_privs.change(ZPRIVS_LOWER))
 | 
			
		||||
			zlog_err("Can't lower privileges");
 | 
			
		||||
		if (sock < 0) {
 | 
			
		||||
@ -736,8 +734,8 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
 | 
			
		||||
		 * ttl=255 */
 | 
			
		||||
		sockopt_ttl(ainfo->ai_family, sock, MAXTTL);
 | 
			
		||||
 | 
			
		||||
		ret = bgp_listener(sock, ainfo->ai_addr,
 | 
			
		||||
				   ainfo->ai_addrlen, bgp);
 | 
			
		||||
		ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen,
 | 
			
		||||
				   bgp);
 | 
			
		||||
		if (ret == 0)
 | 
			
		||||
			++count;
 | 
			
		||||
		else
 | 
			
		||||
@ -745,8 +743,9 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
 | 
			
		||||
	}
 | 
			
		||||
	freeaddrinfo(ainfo_save);
 | 
			
		||||
	if (count == 0) {
 | 
			
		||||
		zlog_err("%s: no usable addresses please check other programs usage of specified port %d",
 | 
			
		||||
			 __func__, port);
 | 
			
		||||
		zlog_err(
 | 
			
		||||
			"%s: no usable addresses please check other programs usage of specified port %d",
 | 
			
		||||
			__func__, port);
 | 
			
		||||
		zlog_err("%s: Program cannot continue", __func__);
 | 
			
		||||
		exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -122,8 +122,7 @@ static int bgp_tip_hash_cmp(const void *p1, const void *p2)
 | 
			
		||||
 | 
			
		||||
void bgp_tip_hash_init(struct bgp *bgp)
 | 
			
		||||
{
 | 
			
		||||
	bgp->tip_hash = hash_create(bgp_tip_hash_key_make,
 | 
			
		||||
				    bgp_tip_hash_cmp,
 | 
			
		||||
	bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
 | 
			
		||||
				    "BGP TIP hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -204,9 +203,9 @@ static int bgp_address_hash_cmp(const void *p1, const void *p2)
 | 
			
		||||
 | 
			
		||||
void bgp_address_init(struct bgp *bgp)
 | 
			
		||||
{
 | 
			
		||||
	bgp->address_hash = hash_create(bgp_address_hash_key_make,
 | 
			
		||||
					bgp_address_hash_cmp,
 | 
			
		||||
					"BGP Address Hash");
 | 
			
		||||
	bgp->address_hash =
 | 
			
		||||
		hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
 | 
			
		||||
			    "BGP Address Hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bgp_address_destroy(struct bgp *bgp)
 | 
			
		||||
@ -448,16 +447,14 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
 | 
			
		||||
	rn1 = rn2 = NULL;
 | 
			
		||||
 | 
			
		||||
	bgp = SUBGRP_INST(subgrp);
 | 
			
		||||
	rn1 = bgp_node_match(bgp->connected_table[AFI_IP],
 | 
			
		||||
			     &np);
 | 
			
		||||
	rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
 | 
			
		||||
	if (!rn1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	SUBGRP_FOREACH_PEER(subgrp, paf) {
 | 
			
		||||
	SUBGRP_FOREACH_PEER (subgrp, paf) {
 | 
			
		||||
		p.u.prefix4 = paf->peer->su.sin.sin_addr;
 | 
			
		||||
 | 
			
		||||
		rn2 = bgp_node_match(bgp->connected_table[AFI_IP],
 | 
			
		||||
				     &p);
 | 
			
		||||
		rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
 | 
			
		||||
		if (rn1 == rn2) {
 | 
			
		||||
			bgp_unlock_node(rn1);
 | 
			
		||||
			bgp_unlock_node(rn2);
 | 
			
		||||
@ -472,8 +469,7 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bgp_show_nexthops_detail(struct vty *vty,
 | 
			
		||||
				     struct bgp *bgp,
 | 
			
		||||
static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
				     struct bgp_nexthop_cache *bnc)
 | 
			
		||||
{
 | 
			
		||||
	char buf[PREFIX2STR_BUFFER];
 | 
			
		||||
@ -483,39 +479,35 @@ static void bgp_show_nexthops_detail(struct vty *vty,
 | 
			
		||||
		switch (nexthop->type) {
 | 
			
		||||
		case NEXTHOP_TYPE_IPV6:
 | 
			
		||||
			vty_out(vty, "  gate %s\n",
 | 
			
		||||
				inet_ntop(AF_INET6, &nexthop->gate.ipv6,
 | 
			
		||||
					  buf, sizeof(buf)));
 | 
			
		||||
				inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
 | 
			
		||||
					  sizeof(buf)));
 | 
			
		||||
			break;
 | 
			
		||||
		case NEXTHOP_TYPE_IPV6_IFINDEX:
 | 
			
		||||
			vty_out(vty, "  gate %s, if %s\n",
 | 
			
		||||
				inet_ntop(AF_INET6, &nexthop->gate.ipv6,
 | 
			
		||||
					  buf, sizeof(buf)),
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex,
 | 
			
		||||
					       bgp->vrf_id));
 | 
			
		||||
				inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
 | 
			
		||||
					  sizeof(buf)),
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
 | 
			
		||||
			break;
 | 
			
		||||
		case NEXTHOP_TYPE_IPV4:
 | 
			
		||||
			vty_out(vty, "  gate %s\n",
 | 
			
		||||
				inet_ntop(AF_INET, &nexthop->gate.ipv4,
 | 
			
		||||
					  buf, sizeof(buf)));
 | 
			
		||||
				inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
 | 
			
		||||
					  sizeof(buf)));
 | 
			
		||||
			break;
 | 
			
		||||
		case NEXTHOP_TYPE_IFINDEX:
 | 
			
		||||
			vty_out(vty, "  if %s\n",
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex,
 | 
			
		||||
					       bgp->vrf_id));
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
 | 
			
		||||
			break;
 | 
			
		||||
		case NEXTHOP_TYPE_IPV4_IFINDEX:
 | 
			
		||||
			vty_out(vty, "  gate %s, if %s\n",
 | 
			
		||||
				inet_ntop(AF_INET, &nexthop->gate.ipv4,
 | 
			
		||||
					  buf, sizeof(buf)),
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex,
 | 
			
		||||
					       bgp->vrf_id));
 | 
			
		||||
				inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
 | 
			
		||||
					  sizeof(buf)),
 | 
			
		||||
				ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
 | 
			
		||||
			break;
 | 
			
		||||
		case NEXTHOP_TYPE_BLACKHOLE:
 | 
			
		||||
			vty_out(vty, "  blackhole\n");
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"  invalid nexthop type %u\n",
 | 
			
		||||
			vty_out(vty, "  invalid nexthop type %u\n",
 | 
			
		||||
				nexthop->type);
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
@ -549,7 +541,7 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
 | 
			
		||||
 | 
			
		||||
					bgp_show_nexthops_detail(vty, bgp, bnc);
 | 
			
		||||
 | 
			
		||||
				} else{
 | 
			
		||||
				} else {
 | 
			
		||||
					vty_out(vty, " %s invalid\n",
 | 
			
		||||
						inet_ntop(rn->p.family,
 | 
			
		||||
							  &rn->p.u.prefix, buf,
 | 
			
		||||
 | 
			
		||||
@ -546,14 +546,14 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	p = &(bnc->node->p);
 | 
			
		||||
	if ((command == ZEBRA_NEXTHOP_REGISTER ||
 | 
			
		||||
	     command == ZEBRA_IMPORT_ROUTE_REGISTER) &&
 | 
			
		||||
	    (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
 | 
			
		||||
	     || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
 | 
			
		||||
	if ((command == ZEBRA_NEXTHOP_REGISTER
 | 
			
		||||
	     || command == ZEBRA_IMPORT_ROUTE_REGISTER)
 | 
			
		||||
	    && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
 | 
			
		||||
		|| CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
 | 
			
		||||
		exact_match = true;
 | 
			
		||||
 | 
			
		||||
	ret = zclient_send_rnh(zclient, command, p,
 | 
			
		||||
			       exact_match, bnc->bgp->vrf_id);
 | 
			
		||||
	ret = zclient_send_rnh(zclient, command, p, exact_match,
 | 
			
		||||
			       bnc->bgp->vrf_id);
 | 
			
		||||
	/* TBD: handle the failure */
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
 | 
			
		||||
 | 
			
		||||
@ -1573,9 +1573,8 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
 | 
			
		||||
	 * Non-MP IPv4/Unicast EoR is a completely empty UPDATE
 | 
			
		||||
	 * and MP EoR should have only an empty MP_UNREACH
 | 
			
		||||
	 */
 | 
			
		||||
	if ((!update_len && !withdraw_len &&
 | 
			
		||||
	     nlris[NLRI_MP_UPDATE].length == 0) ||
 | 
			
		||||
	    (attr_parse_ret == BGP_ATTR_PARSE_EOR)) {
 | 
			
		||||
	if ((!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0)
 | 
			
		||||
	    || (attr_parse_ret == BGP_ATTR_PARSE_EOR)) {
 | 
			
		||||
		afi_t afi = 0;
 | 
			
		||||
		safi_t safi;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1967,9 +1967,8 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp,
 | 
			
		||||
						 : NULL);
 | 
			
		||||
 | 
			
		||||
	/* First update is deferred until ORF or ROUTE-REFRESH is received */
 | 
			
		||||
	if (onlypeer
 | 
			
		||||
	    && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
 | 
			
		||||
			  PEER_STATUS_ORF_WAIT_REFRESH))
 | 
			
		||||
	if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
 | 
			
		||||
				   PEER_STATUS_ORF_WAIT_REFRESH))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	memset(&attr, 0, sizeof(struct attr));
 | 
			
		||||
@ -2228,10 +2227,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
 | 
			
		||||
 | 
			
		||||
	/* advertise/withdraw type-5 routes */
 | 
			
		||||
	if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
 | 
			
		||||
		if (new_select)
 | 
			
		||||
			bgp_evpn_advertise_type5_route(
 | 
			
		||||
				bgp, &rn->p, new_select->attr, afi, safi);
 | 
			
		||||
		else if (old_select)
 | 
			
		||||
		if (advertise_type5_routes(bgp, afi) && new_select &&
 | 
			
		||||
		    (!new_select->extra || !new_select->extra->parent))
 | 
			
		||||
			bgp_evpn_advertise_type5_route(bgp, &rn->p,
 | 
			
		||||
						       new_select->attr,
 | 
			
		||||
						       afi, safi);
 | 
			
		||||
		else if (advertise_type5_routes(bgp, afi) && old_select &&
 | 
			
		||||
		         (!old_select->extra || !old_select->extra->parent))
 | 
			
		||||
			bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -6839,10 +6841,9 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
 | 
			
		||||
		bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN,
 | 
			
		||||
					use_json, json);
 | 
			
		||||
	else
 | 
			
		||||
		vty_out(vty, "%s ",
 | 
			
		||||
			bgp_damp_reuse_time_vty(vty, binfo, timebuf,
 | 
			
		||||
						BGP_UPTIME_LEN, use_json,
 | 
			
		||||
						json));
 | 
			
		||||
		vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf,
 | 
			
		||||
							    BGP_UPTIME_LEN,
 | 
			
		||||
							    use_json, json));
 | 
			
		||||
 | 
			
		||||
	/* Print attribute */
 | 
			
		||||
	attr = binfo->attr;
 | 
			
		||||
@ -6921,9 +6922,8 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
 | 
			
		||||
		peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
 | 
			
		||||
			    json);
 | 
			
		||||
	else
 | 
			
		||||
		vty_out(vty, "%s ",
 | 
			
		||||
			peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0,
 | 
			
		||||
				    NULL));
 | 
			
		||||
		vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
 | 
			
		||||
						BGP_UPTIME_LEN, 0, NULL));
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
 | 
			
		||||
	    && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) {
 | 
			
		||||
@ -8029,9 +8029,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!use_json && header) {
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"BGP table version is %" PRIu64
 | 
			
		||||
					", local router ID is %s\n",
 | 
			
		||||
				vty_out(vty, "BGP table version is %" PRIu64
 | 
			
		||||
					     ", local router ID is %s\n",
 | 
			
		||||
					table->version,
 | 
			
		||||
					inet_ntoa(bgp->router_id));
 | 
			
		||||
				vty_out(vty, BGP_SHOW_SCODE_HEADER);
 | 
			
		||||
@ -8513,9 +8512,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
		if (display)
 | 
			
		||||
			json_object_object_add(json, "paths", json_paths);
 | 
			
		||||
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!display) {
 | 
			
		||||
@ -9590,9 +9588,8 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
 | 
			
		||||
				json, "recommended",
 | 
			
		||||
				"Please report this bug, with the above command output");
 | 
			
		||||
		}
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	} else {
 | 
			
		||||
 | 
			
		||||
@ -9826,9 +9823,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
 | 
			
		||||
					       "bgpOriginatingDefaultNetwork",
 | 
			
		||||
					       "0.0.0.0");
 | 
			
		||||
		} else {
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"BGP table version is %" PRIu64
 | 
			
		||||
				", local router ID is %s\n",
 | 
			
		||||
			vty_out(vty, "BGP table version is %" PRIu64
 | 
			
		||||
				     ", local router ID is %s\n",
 | 
			
		||||
				table->version, inet_ntoa(bgp->router_id));
 | 
			
		||||
			vty_out(vty, BGP_SHOW_SCODE_HEADER);
 | 
			
		||||
			vty_out(vty, BGP_SHOW_OCODE_HEADER);
 | 
			
		||||
@ -9971,9 +9967,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
 | 
			
		||||
				output_count);
 | 
			
		||||
	}
 | 
			
		||||
	if (use_json) {
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -104,10 +104,8 @@ struct bgp_info_extra {
 | 
			
		||||
				struct in6_addr addr6;
 | 
			
		||||
			} un; /* cached un address */
 | 
			
		||||
			time_t create_time;
 | 
			
		||||
			struct
 | 
			
		||||
				prefix
 | 
			
		||||
					aux_prefix; /* AFI_L2VPN: the IP addr,
 | 
			
		||||
						       if family set */
 | 
			
		||||
			struct prefix aux_prefix; /* AFI_L2VPN: the IP addr,
 | 
			
		||||
						     if family set */
 | 
			
		||||
		} import;
 | 
			
		||||
 | 
			
		||||
	} vnc;
 | 
			
		||||
 | 
			
		||||
@ -594,6 +594,24 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
 | 
			
		||||
	route_match_ip_route_source_prefix_list_compile,
 | 
			
		||||
	route_match_ip_route_source_prefix_list_free};
 | 
			
		||||
 | 
			
		||||
/* `match evpn default-route' */
 | 
			
		||||
 | 
			
		||||
/* Match function should return 1 if match is success else 0 */
 | 
			
		||||
static route_map_result_t route_match_evpn_default_route(void *rule,
 | 
			
		||||
							 struct prefix *p,
 | 
			
		||||
							 route_map_object_t
 | 
			
		||||
							 type, void *object)
 | 
			
		||||
{
 | 
			
		||||
	if (type == RMAP_BGP && is_evpn_prefix_default(p))
 | 
			
		||||
		return RMAP_MATCH;
 | 
			
		||||
 | 
			
		||||
	return RMAP_NOMATCH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Route map commands for default-route matching. */
 | 
			
		||||
struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
 | 
			
		||||
	"evpn default-route", route_match_evpn_default_route, NULL, NULL};
 | 
			
		||||
 | 
			
		||||
/* `match mac address MAC_ACCESS_LIST' */
 | 
			
		||||
 | 
			
		||||
/* Match function should return 1 if match is success else return
 | 
			
		||||
@ -742,8 +760,7 @@ static void route_match_evpn_route_type_free(void *rule)
 | 
			
		||||
/* Route map commands for evpn route-type  matching. */
 | 
			
		||||
struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
 | 
			
		||||
	"evpn route-type", route_match_evpn_route_type,
 | 
			
		||||
	route_match_evpn_route_type_compile,
 | 
			
		||||
	route_match_evpn_route_type_free};
 | 
			
		||||
	route_match_evpn_route_type_compile, route_match_evpn_route_type_free};
 | 
			
		||||
 | 
			
		||||
/* `match local-preference LOCAL-PREF' */
 | 
			
		||||
 | 
			
		||||
@ -3079,12 +3096,13 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
 | 
			
		||||
 | 
			
		||||
	/* for type5 command route-maps */
 | 
			
		||||
	FOREACH_AFI_SAFI (afi, safi) {
 | 
			
		||||
		if (bgp->adv_cmd_rmap[afi][safi].name &&
 | 
			
		||||
		    strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name) == 0) {
 | 
			
		||||
		if (bgp->adv_cmd_rmap[afi][safi].name
 | 
			
		||||
		    && strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
 | 
			
		||||
			       == 0) {
 | 
			
		||||
			if (BGP_DEBUG(zebra, ZEBRA))
 | 
			
		||||
				zlog_debug(
 | 
			
		||||
					   "Processing route_map %s update on advertise type5 route command",
 | 
			
		||||
					   rmap_name);
 | 
			
		||||
					"Processing route_map %s update on advertise type5 route command",
 | 
			
		||||
					rmap_name);
 | 
			
		||||
			bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
 | 
			
		||||
			bgp_evpn_advertise_type5_routes(bgp, afi, safi);
 | 
			
		||||
		}
 | 
			
		||||
@ -3249,6 +3267,29 @@ DEFUN (no_match_evpn_vni,
 | 
			
		||||
				      RMAP_EVENT_MATCH_DELETED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (match_evpn_default_route,
 | 
			
		||||
       match_evpn_default_route_cmd,
 | 
			
		||||
       "match evpn default-route",
 | 
			
		||||
       MATCH_STR
 | 
			
		||||
       EVPN_HELP_STR
 | 
			
		||||
       "default EVPN type-5 route\n")
 | 
			
		||||
{
 | 
			
		||||
	return bgp_route_match_add(vty, "evpn default-route", NULL,
 | 
			
		||||
				   RMAP_EVENT_MATCH_ADDED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (no_match_evpn_default_route,
 | 
			
		||||
       no_match_evpn_default_route_cmd,
 | 
			
		||||
       "no match evpn default-route",
 | 
			
		||||
       NO_STR
 | 
			
		||||
       MATCH_STR
 | 
			
		||||
       EVPN_HELP_STR
 | 
			
		||||
       "default EVPN type-5 route\n")
 | 
			
		||||
{
 | 
			
		||||
	return bgp_route_match_delete(vty, "evpn default-route", NULL,
 | 
			
		||||
				      RMAP_EVENT_MATCH_DELETED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (match_peer,
 | 
			
		||||
       match_peer_cmd,
 | 
			
		||||
       "match peer <A.B.C.D|X:X::X:X|WORD>",
 | 
			
		||||
@ -4628,6 +4669,7 @@ void bgp_route_map_init(void)
 | 
			
		||||
	route_map_install_match(&route_match_mac_address_cmd);
 | 
			
		||||
	route_map_install_match(&route_match_evpn_vni_cmd);
 | 
			
		||||
	route_map_install_match(&route_match_evpn_route_type_cmd);
 | 
			
		||||
	route_map_install_match(&route_match_evpn_default_route_cmd);
 | 
			
		||||
 | 
			
		||||
	route_map_install_set(&route_set_ip_nexthop_cmd);
 | 
			
		||||
	route_map_install_set(&route_set_local_pref_cmd);
 | 
			
		||||
@ -4664,6 +4706,8 @@ void bgp_route_map_init(void)
 | 
			
		||||
	install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
 | 
			
		||||
	install_element(RMAP_NODE, &match_evpn_route_type_cmd);
 | 
			
		||||
	install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
 | 
			
		||||
	install_element(RMAP_NODE, &match_evpn_default_route_cmd);
 | 
			
		||||
	install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(RMAP_NODE, &match_aspath_cmd);
 | 
			
		||||
	install_element(RMAP_NODE, &no_match_aspath_cmd);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										133
									
								
								bgpd/bgp_rpki.c
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								bgpd/bgp_rpki.c
									
									
									
									
									
								
							@ -1,9 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * BGP RPKI
 | 
			
		||||
 * Copyright (C) 2013 Michael Mester (m.mester@fu-berlin.de), for FU Berlin
 | 
			
		||||
 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU Berlin
 | 
			
		||||
 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW Hamburg
 | 
			
		||||
 * Copyright (C) 2017 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW Hamburg
 | 
			
		||||
 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU
 | 
			
		||||
 * Berlin
 | 
			
		||||
 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
 | 
			
		||||
 * Hamburg
 | 
			
		||||
 * Copyright (C) 2017 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW
 | 
			
		||||
 * Hamburg
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of FRRouting.
 | 
			
		||||
 *
 | 
			
		||||
@ -77,14 +80,14 @@ DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group")
 | 
			
		||||
#define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
 | 
			
		||||
 | 
			
		||||
struct cache {
 | 
			
		||||
       enum { TCP, SSH } type;
 | 
			
		||||
       struct tr_socket *tr_socket;
 | 
			
		||||
       union {
 | 
			
		||||
	enum { TCP, SSH } type;
 | 
			
		||||
	struct tr_socket *tr_socket;
 | 
			
		||||
	union {
 | 
			
		||||
		struct tr_tcp_config *tcp_config;
 | 
			
		||||
		struct tr_ssh_config *ssh_config;
 | 
			
		||||
       } tr_config;
 | 
			
		||||
       struct rtr_socket *rtr_socket;
 | 
			
		||||
       uint8_t preference;
 | 
			
		||||
	} tr_config;
 | 
			
		||||
	struct rtr_socket *rtr_socket;
 | 
			
		||||
	uint8_t preference;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum return_values { SUCCESS = 0, ERROR = -1 };
 | 
			
		||||
@ -105,27 +108,22 @@ static void overwrite_exit_commands(void);
 | 
			
		||||
static void free_cache(struct cache *cache);
 | 
			
		||||
static struct rtr_mgr_group *get_groups(void);
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
static int add_ssh_cache(const char *host,
 | 
			
		||||
			 const unsigned int port,
 | 
			
		||||
			 const char *username,
 | 
			
		||||
			 const char *client_privkey_path,
 | 
			
		||||
static int add_ssh_cache(const char *host, const unsigned int port,
 | 
			
		||||
			 const char *username, const char *client_privkey_path,
 | 
			
		||||
			 const char *client_pubkey_path,
 | 
			
		||||
			 const char *server_pubkey_path,
 | 
			
		||||
			 const uint8_t preference);
 | 
			
		||||
#endif
 | 
			
		||||
static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
 | 
			
		||||
static struct cache *find_cache(const uint8_t preference);
 | 
			
		||||
static int add_tcp_cache(const char *host,
 | 
			
		||||
			 const char *port,
 | 
			
		||||
static int add_tcp_cache(const char *host, const char *port,
 | 
			
		||||
			 const uint8_t preference);
 | 
			
		||||
static void print_record(const struct pfx_record *record, void *data);
 | 
			
		||||
static int is_synchronized(void);
 | 
			
		||||
static int is_running(void);
 | 
			
		||||
static void route_match_free(void *rule);
 | 
			
		||||
static route_map_result_t route_match(void *rule,
 | 
			
		||||
				      struct prefix *prefix,
 | 
			
		||||
				      route_map_object_t type,
 | 
			
		||||
				      void *object);
 | 
			
		||||
static route_map_result_t route_match(void *rule, struct prefix *prefix,
 | 
			
		||||
				      route_map_object_t type, void *object);
 | 
			
		||||
static void *route_match_compile(const char *arg);
 | 
			
		||||
 | 
			
		||||
static struct rtr_mgr_config *rtr_config;
 | 
			
		||||
@ -139,9 +137,8 @@ static unsigned int timeout;
 | 
			
		||||
static unsigned int initial_synchronisation_timeout;
 | 
			
		||||
 | 
			
		||||
static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
 | 
			
		||||
static struct route_map_rule_cmd route_match_rpki_cmd = {"rpki", route_match,
 | 
			
		||||
						  route_match_compile,
 | 
			
		||||
						  route_match_free};
 | 
			
		||||
static struct route_map_rule_cmd route_match_rpki_cmd = {
 | 
			
		||||
	"rpki", route_match, route_match_compile, route_match_free};
 | 
			
		||||
 | 
			
		||||
static void *malloc_wrapper(size_t size)
 | 
			
		||||
{
 | 
			
		||||
@ -162,8 +159,7 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
 | 
			
		||||
				struct prefix *prefix);
 | 
			
		||||
 | 
			
		||||
static route_map_result_t route_match(void *rule, struct prefix *prefix,
 | 
			
		||||
				      route_map_object_t type,
 | 
			
		||||
				      void *object)
 | 
			
		||||
				      route_map_object_t type, void *object)
 | 
			
		||||
{
 | 
			
		||||
	int *rpki_status = rule;
 | 
			
		||||
	struct bgp_info *bgp_info;
 | 
			
		||||
@ -285,7 +281,7 @@ static int bgp_rpki_init(struct thread_master *master)
 | 
			
		||||
	rtr_is_running = 0;
 | 
			
		||||
 | 
			
		||||
	cache_list = list_new();
 | 
			
		||||
	cache_list->del = (void (*)(void *)) &free_cache;
 | 
			
		||||
	cache_list->del = (void (*)(void *)) & free_cache;
 | 
			
		||||
 | 
			
		||||
	polling_period = POLLING_PERIOD_DEFAULT;
 | 
			
		||||
	expire_interval = EXPIRE_INTERVAL_DEFAULT;
 | 
			
		||||
@ -307,9 +303,7 @@ static int bgp_rpki_fini(void)
 | 
			
		||||
 | 
			
		||||
static int bgp_rpki_module_init(void)
 | 
			
		||||
{
 | 
			
		||||
	lrtr_set_alloc_functions(malloc_wrapper,
 | 
			
		||||
				 realloc_wrapper,
 | 
			
		||||
				 free_wrapper);
 | 
			
		||||
	lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
 | 
			
		||||
 | 
			
		||||
	hook_register(frr_late_init, bgp_rpki_init);
 | 
			
		||||
	hook_register(frr_early_fini, &bgp_rpki_fini);
 | 
			
		||||
@ -332,8 +326,8 @@ static int start(void)
 | 
			
		||||
	struct rtr_mgr_group *groups = get_groups();
 | 
			
		||||
 | 
			
		||||
	ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
 | 
			
		||||
			   expire_interval, retry_interval,
 | 
			
		||||
			   NULL, NULL, NULL, NULL);
 | 
			
		||||
			   expire_interval, retry_interval, NULL, NULL, NULL,
 | 
			
		||||
			   NULL);
 | 
			
		||||
	if (ret == RTR_ERROR) {
 | 
			
		||||
		RPKI_DEBUG("Init rtr_mgr failed.");
 | 
			
		||||
		return ERROR;
 | 
			
		||||
@ -447,8 +441,8 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
 | 
			
		||||
		if (as_segment->type == AS_SEQUENCE) {
 | 
			
		||||
			// Get rightmost asn
 | 
			
		||||
			as_number = as_segment->as[as_segment->length - 1];
 | 
			
		||||
		} else if (as_segment->type == AS_CONFED_SEQUENCE ||
 | 
			
		||||
			   as_segment->type == AS_CONFED_SET) {
 | 
			
		||||
		} else if (as_segment->type == AS_CONFED_SEQUENCE
 | 
			
		||||
			   || as_segment->type == AS_CONFED_SET) {
 | 
			
		||||
			// Set own as number
 | 
			
		||||
			as_number = peer->bgp->as;
 | 
			
		||||
		} else {
 | 
			
		||||
@ -520,16 +514,15 @@ static int add_cache(struct cache *cache)
 | 
			
		||||
 | 
			
		||||
	listnode_add(cache_list, cache);
 | 
			
		||||
 | 
			
		||||
	if (rtr_is_running &&
 | 
			
		||||
	    rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
 | 
			
		||||
	if (rtr_is_running
 | 
			
		||||
	    && rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
 | 
			
		||||
		return ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int add_tcp_cache(const char *host,
 | 
			
		||||
			 const char *port,
 | 
			
		||||
static int add_tcp_cache(const char *host, const char *port,
 | 
			
		||||
			 const uint8_t preference)
 | 
			
		||||
{
 | 
			
		||||
	struct rtr_socket *rtr_socket;
 | 
			
		||||
@ -556,10 +549,8 @@ static int add_tcp_cache(const char *host,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
static int add_ssh_cache(const char *host,
 | 
			
		||||
			 const unsigned int port,
 | 
			
		||||
			 const char *username,
 | 
			
		||||
			 const char *client_privkey_path,
 | 
			
		||||
static int add_ssh_cache(const char *host, const unsigned int port,
 | 
			
		||||
			 const char *username, const char *client_privkey_path,
 | 
			
		||||
			 const char *client_pubkey_path,
 | 
			
		||||
			 const char *server_pubkey_path,
 | 
			
		||||
			 const uint8_t preference)
 | 
			
		||||
@ -577,8 +568,8 @@ static int add_ssh_cache(const char *host,
 | 
			
		||||
	ssh_config->bindaddr = NULL;
 | 
			
		||||
 | 
			
		||||
	ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
 | 
			
		||||
	ssh_config->client_privkey_path = XSTRDUP(
 | 
			
		||||
			MTYPE_BGP_RPKI_CACHE, client_privkey_path);
 | 
			
		||||
	ssh_config->client_privkey_path =
 | 
			
		||||
		XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
 | 
			
		||||
	ssh_config->server_hostkey_path =
 | 
			
		||||
		XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
 | 
			
		||||
 | 
			
		||||
@ -597,16 +588,13 @@ static int add_ssh_cache(const char *host,
 | 
			
		||||
static void free_cache(struct cache *cache)
 | 
			
		||||
{
 | 
			
		||||
	if (cache->type == TCP) {
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE,
 | 
			
		||||
		      cache->tr_config.tcp_config->host);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE,
 | 
			
		||||
		      cache->tr_config.tcp_config->port);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
 | 
			
		||||
	}
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
	else {
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE,
 | 
			
		||||
		      cache->tr_config.ssh_config->host);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE,
 | 
			
		||||
		      cache->tr_config.ssh_config->username);
 | 
			
		||||
		XFREE(MTYPE_BGP_RPKI_CACHE,
 | 
			
		||||
@ -644,22 +632,17 @@ static int config_write(struct vty *vty)
 | 
			
		||||
#endif
 | 
			
		||||
			case TCP:
 | 
			
		||||
				tcp_config = cache->tr_config.tcp_config;
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"  rpki cache %s %s ",
 | 
			
		||||
					tcp_config->host,
 | 
			
		||||
					tcp_config->port);
 | 
			
		||||
				vty_out(vty, "  rpki cache %s %s ",
 | 
			
		||||
					tcp_config->host, tcp_config->port);
 | 
			
		||||
				break;
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
			case SSH:
 | 
			
		||||
				ssh_config = cache->tr_config.ssh_config;
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"  rpki cache %s %u %s %s %s ",
 | 
			
		||||
					ssh_config->host,
 | 
			
		||||
					ssh_config->port,
 | 
			
		||||
				vty_out(vty, "  rpki cache %s %u %s %s %s ",
 | 
			
		||||
					ssh_config->host, ssh_config->port,
 | 
			
		||||
					ssh_config->username,
 | 
			
		||||
					ssh_config->client_privkey_path,
 | 
			
		||||
					ssh_config->server_hostkey_path
 | 
			
		||||
							!= NULL
 | 
			
		||||
					ssh_config->server_hostkey_path != NULL
 | 
			
		||||
						? ssh_config
 | 
			
		||||
							  ->server_hostkey_path
 | 
			
		||||
						: " ");
 | 
			
		||||
@ -694,7 +677,8 @@ DEFUN (bgp_rpki_start,
 | 
			
		||||
       "start rpki support\n")
 | 
			
		||||
{
 | 
			
		||||
	if (listcount(cache_list) == 0)
 | 
			
		||||
		vty_out(vty, "Could not start rpki because no caches are configured\n");
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"Could not start rpki because no caches are configured\n");
 | 
			
		||||
 | 
			
		||||
	if (!is_running()) {
 | 
			
		||||
		if (start() == ERROR) {
 | 
			
		||||
@ -855,9 +839,9 @@ DEFPY (rpki_cache,
 | 
			
		||||
	// use ssh connection
 | 
			
		||||
	if (ssh_uname) {
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
		return_value = add_ssh_cache(
 | 
			
		||||
			cache, sshport, ssh_uname, ssh_privkey, ssh_pubkey,
 | 
			
		||||
			server_pubkey, preference);
 | 
			
		||||
		return_value =
 | 
			
		||||
			add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
 | 
			
		||||
				      ssh_pubkey, server_pubkey, preference);
 | 
			
		||||
#else
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"ssh sockets are not supported. "
 | 
			
		||||
@ -923,8 +907,7 @@ DEFUN (show_rpki_prefix_table,
 | 
			
		||||
	struct cache *cache;
 | 
			
		||||
 | 
			
		||||
	for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"host: %s port: %s\n",
 | 
			
		||||
		vty_out(vty, "host: %s port: %s\n",
 | 
			
		||||
			cache->tr_config.tcp_config->host,
 | 
			
		||||
			cache->tr_config.tcp_config->port);
 | 
			
		||||
	}
 | 
			
		||||
@ -947,8 +930,7 @@ DEFUN (show_rpki_cache_server,
 | 
			
		||||
	struct cache *cache;
 | 
			
		||||
 | 
			
		||||
	for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"host: %s port: %s\n",
 | 
			
		||||
		vty_out(vty, "host: %s port: %s\n",
 | 
			
		||||
			cache->tr_config.tcp_config->host,
 | 
			
		||||
			cache->tr_config.tcp_config->port);
 | 
			
		||||
	}
 | 
			
		||||
@ -973,8 +955,7 @@ DEFUN (show_rpki_cache_connection,
 | 
			
		||||
			return CMD_SUCCESS;
 | 
			
		||||
		}
 | 
			
		||||
		vty_out(vty, "Connected to group %d\n", group->preference);
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node,
 | 
			
		||||
					  cache)) {
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
 | 
			
		||||
			if (cache->preference == group->preference) {
 | 
			
		||||
				struct tr_tcp_config *tcp_config;
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
@ -984,8 +965,7 @@ DEFUN (show_rpki_cache_connection,
 | 
			
		||||
				switch (cache->type) {
 | 
			
		||||
				case TCP:
 | 
			
		||||
					tcp_config =
 | 
			
		||||
						cache->tr_config
 | 
			
		||||
							.tcp_config;
 | 
			
		||||
						cache->tr_config.tcp_config;
 | 
			
		||||
					vty_out(vty,
 | 
			
		||||
						"rpki tcp cache %s %s pref %hhu\n",
 | 
			
		||||
						tcp_config->host,
 | 
			
		||||
@ -996,8 +976,7 @@ DEFUN (show_rpki_cache_connection,
 | 
			
		||||
#if defined(FOUND_SSH)
 | 
			
		||||
				case SSH:
 | 
			
		||||
					ssh_config =
 | 
			
		||||
						cache->tr_config
 | 
			
		||||
							.ssh_config;
 | 
			
		||||
						cache->tr_config.ssh_config;
 | 
			
		||||
					vty_out(vty,
 | 
			
		||||
						"rpki ssh cache %s %u pref %hhu\n",
 | 
			
		||||
						ssh_config->host,
 | 
			
		||||
@ -1142,9 +1121,9 @@ static void overwrite_exit_commands(void)
 | 
			
		||||
	for (i = 0; i < cmd_vector->active; ++i) {
 | 
			
		||||
		struct cmd_element *cmd = vector_lookup(cmd_vector, i);
 | 
			
		||||
 | 
			
		||||
		if (strcmp(cmd->string, "exit") == 0 ||
 | 
			
		||||
		    strcmp(cmd->string, "quit") == 0 ||
 | 
			
		||||
		    strcmp(cmd->string, "end") == 0) {
 | 
			
		||||
		if (strcmp(cmd->string, "exit") == 0
 | 
			
		||||
		    || strcmp(cmd->string, "quit") == 0
 | 
			
		||||
		    || strcmp(cmd->string, "end") == 0) {
 | 
			
		||||
			uninstall_element(RPKI_NODE, cmd);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -1156,7 +1135,7 @@ static void overwrite_exit_commands(void)
 | 
			
		||||
 | 
			
		||||
static void install_cli_commands(void)
 | 
			
		||||
{
 | 
			
		||||
	//TODO: make config write work
 | 
			
		||||
	// TODO: make config write work
 | 
			
		||||
	install_node(&rpki_node, &config_write);
 | 
			
		||||
	install_default(RPKI_NODE);
 | 
			
		||||
	overwrite_exit_commands();
 | 
			
		||||
@ -1212,4 +1191,4 @@ static void install_cli_commands(void)
 | 
			
		||||
 | 
			
		||||
FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
 | 
			
		||||
		 .description = "Enable RPKI support for FRR.",
 | 
			
		||||
	 .init = bgp_rpki_module_init)
 | 
			
		||||
		 .init = bgp_rpki_module_init)
 | 
			
		||||
 | 
			
		||||
@ -864,8 +864,6 @@ static u_char *bgp4PathAttrTable(struct variable *v, oid name[], size_t *length,
 | 
			
		||||
		return SNMP_INTEGER(-1);
 | 
			
		||||
		break;
 | 
			
		||||
	case BGP4PATHATTRBEST: /* 13 */
 | 
			
		||||
			       /* $FRR indent$ */
 | 
			
		||||
			       /* clang-format off */
 | 
			
		||||
#define BGP4_PathAttrBest_false 1
 | 
			
		||||
#define BGP4_PathAttrBest_true  2
 | 
			
		||||
		if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
 | 
			
		||||
 | 
			
		||||
@ -85,9 +85,8 @@ static void sync_init(struct update_subgroup *subgrp)
 | 
			
		||||
	BGP_ADV_FIFO_INIT(&subgrp->sync->update);
 | 
			
		||||
	BGP_ADV_FIFO_INIT(&subgrp->sync->withdraw);
 | 
			
		||||
	BGP_ADV_FIFO_INIT(&subgrp->sync->withdraw_low);
 | 
			
		||||
	subgrp->hash = hash_create(baa_hash_key,
 | 
			
		||||
				   baa_hash_cmp,
 | 
			
		||||
				   "BGP SubGroup Hash");
 | 
			
		||||
	subgrp->hash =
 | 
			
		||||
		hash_create(baa_hash_key, baa_hash_cmp, "BGP SubGroup Hash");
 | 
			
		||||
 | 
			
		||||
	/* We use a larger buffer for subgrp->work in the event that:
 | 
			
		||||
	 * - We RX a BGP_UPDATE where the attributes alone are just
 | 
			
		||||
@ -1545,8 +1544,7 @@ void update_bgp_group_init(struct bgp *bgp)
 | 
			
		||||
 | 
			
		||||
	AF_FOREACH (afid)
 | 
			
		||||
		bgp->update_groups[afid] =
 | 
			
		||||
			hash_create(updgrp_hash_key_make,
 | 
			
		||||
				    updgrp_hash_cmp,
 | 
			
		||||
			hash_create(updgrp_hash_key_make, updgrp_hash_cmp,
 | 
			
		||||
				    "BGP Update Group Hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1877,11 +1875,12 @@ void subgroup_trigger_write(struct update_subgroup *subgrp)
 | 
			
		||||
	 * the subgroup output queue into their own output queue. This action
 | 
			
		||||
	 * will trigger a write job on the I/O thread.
 | 
			
		||||
	 */
 | 
			
		||||
	SUBGRP_FOREACH_PEER(subgrp, paf)
 | 
			
		||||
	if (paf->peer->status == Established)
 | 
			
		||||
		thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets,
 | 
			
		||||
				      paf->peer, 0,
 | 
			
		||||
				      &paf->peer->t_generate_updgrp_packets);
 | 
			
		||||
	SUBGRP_FOREACH_PEER (subgrp, paf)
 | 
			
		||||
		if (paf->peer->status == Established)
 | 
			
		||||
			thread_add_timer_msec(
 | 
			
		||||
				bm->master, bgp_generate_updgrp_packets,
 | 
			
		||||
				paf->peer, 0,
 | 
			
		||||
				&paf->peer->t_generate_updgrp_packets);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int update_group_clear_update_dbg(struct update_group *updgrp, void *arg)
 | 
			
		||||
 | 
			
		||||
@ -287,7 +287,6 @@ struct update_subgroup {
 | 
			
		||||
 */
 | 
			
		||||
#define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
 | 
			
		||||
 | 
			
		||||
/* really a private structure */
 | 
			
		||||
@ -341,23 +340,23 @@ struct updwalk_context {
 | 
			
		||||
 * Walk all subgroups in an update group.
 | 
			
		||||
 */
 | 
			
		||||
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp)                                  \
 | 
			
		||||
	LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
 | 
			
		||||
	LIST_FOREACH (subgrp, &((updgrp)->subgrps), updgrp_train)
 | 
			
		||||
 | 
			
		||||
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp)                 \
 | 
			
		||||
	LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train,          \
 | 
			
		||||
			  tmp_subgrp)
 | 
			
		||||
	LIST_FOREACH_SAFE (subgrp, &((updgrp)->subgrps), updgrp_train,         \
 | 
			
		||||
			   tmp_subgrp)
 | 
			
		||||
 | 
			
		||||
#define SUBGRP_FOREACH_PEER(subgrp, paf)                                       \
 | 
			
		||||
	LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
 | 
			
		||||
	LIST_FOREACH (paf, &(subgrp->peers), subgrp_train)
 | 
			
		||||
 | 
			
		||||
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf)                        \
 | 
			
		||||
	LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
 | 
			
		||||
	LIST_FOREACH_SAFE (paf, &(subgrp->peers), subgrp_train, temp_paf)
 | 
			
		||||
 | 
			
		||||
#define SUBGRP_FOREACH_ADJ(subgrp, adj)                                        \
 | 
			
		||||
	TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
 | 
			
		||||
	TAILQ_FOREACH (adj, &(subgrp->adjq), subgrp_adj_train)
 | 
			
		||||
 | 
			
		||||
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp)                         \
 | 
			
		||||
	TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
 | 
			
		||||
	TAILQ_FOREACH_SAFE (adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
 | 
			
		||||
 | 
			
		||||
/* Prototypes.  */
 | 
			
		||||
/* bgp_updgrp.c */
 | 
			
		||||
 | 
			
		||||
@ -733,8 +733,9 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
 | 
			
		||||
 | 
			
		||||
		space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
 | 
			
		||||
				  - BGP_MAX_PACKET_SIZE_OVERFLOW;
 | 
			
		||||
		space_needed = BGP_NLRI_LENGTH + addpath_overhead +
 | 
			
		||||
			       bgp_packet_mpattr_prefix_size(afi, safi, &rn->p);
 | 
			
		||||
		space_needed =
 | 
			
		||||
			BGP_NLRI_LENGTH + addpath_overhead
 | 
			
		||||
			+ bgp_packet_mpattr_prefix_size(afi, safi, &rn->p);
 | 
			
		||||
 | 
			
		||||
		/* When remaining space can't include NLRI and it's length.  */
 | 
			
		||||
		if (space_remaining < space_needed)
 | 
			
		||||
@ -778,9 +779,9 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
 | 
			
		||||
			space_remaining =
 | 
			
		||||
				STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
 | 
			
		||||
				- BGP_MAX_PACKET_SIZE_OVERFLOW;
 | 
			
		||||
			space_needed = BGP_NLRI_LENGTH + addpath_overhead +
 | 
			
		||||
				bgp_packet_mpattr_prefix_size(afi, safi,
 | 
			
		||||
							      &rn->p);
 | 
			
		||||
			space_needed = BGP_NLRI_LENGTH + addpath_overhead
 | 
			
		||||
				       + bgp_packet_mpattr_prefix_size(
 | 
			
		||||
						 afi, safi, &rn->p);
 | 
			
		||||
 | 
			
		||||
			/* If the attributes alone do not leave any room for
 | 
			
		||||
			 * NLRI then
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										362
									
								
								bgpd/bgp_vty.c
									
									
									
									
									
								
							
							
						
						
									
										362
									
								
								bgpd/bgp_vty.c
									
									
									
									
									
								
							@ -832,8 +832,7 @@ DEFUN_NOSH (router_bgp,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (listcount(bm->bgp) > 1) {
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"%% Multiple BGP processes are configured\n");
 | 
			
		||||
			vty_out(vty, "%% Please specify ASN and VRF\n");
 | 
			
		||||
			return CMD_WARNING_CONFIG_FAILED;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -908,8 +907,7 @@ DEFUN (no_router_bgp,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (listcount(bm->bgp) > 1) {
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"%% Multiple BGP processes are configured\n");
 | 
			
		||||
			vty_out(vty, "%% Please specify ASN and VRF\n");
 | 
			
		||||
			return CMD_WARNING_CONFIG_FAILED;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -1540,8 +1538,7 @@ DEFUN (no_bgp_maxpaths,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ALIAS_HIDDEN(no_bgp_maxpaths, no_bgp_maxpaths_hidden_cmd,
 | 
			
		||||
	     "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
 | 
			
		||||
	     NO_STR
 | 
			
		||||
	     "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", NO_STR
 | 
			
		||||
	     "Forward packets over multiple paths\n"
 | 
			
		||||
	     "Number of paths\n")
 | 
			
		||||
 | 
			
		||||
@ -6413,11 +6410,16 @@ DEFUN (clear_bgp_ipv6_safi_prefix,
 | 
			
		||||
       "Clear bestpath and re-advertise\n"
 | 
			
		||||
       "IPv6 prefix\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_safi = 3;
 | 
			
		||||
	int idx_ipv6_prefixlen = 5;
 | 
			
		||||
	int idx_safi = 0;
 | 
			
		||||
	int idx_ipv6_prefix = 0;
 | 
			
		||||
	safi_t safi = SAFI_UNICAST;
 | 
			
		||||
	char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ?
 | 
			
		||||
		argv[idx_ipv6_prefix]->arg : NULL;
 | 
			
		||||
 | 
			
		||||
	argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
 | 
			
		||||
	return bgp_clear_prefix(
 | 
			
		||||
		vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
 | 
			
		||||
		bgp_vty_safi_from_str(argv[idx_safi]->text), NULL);
 | 
			
		||||
		vty, NULL, prefix, AFI_IP6,
 | 
			
		||||
		safi, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (clear_bgp_instance_ipv6_safi_prefix,
 | 
			
		||||
@ -6433,11 +6435,20 @@ DEFUN (clear_bgp_instance_ipv6_safi_prefix,
 | 
			
		||||
       "IPv6 prefix\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_word = 3;
 | 
			
		||||
	int idx_safi = 5;
 | 
			
		||||
	int idx_ipv6_prefixlen = 7;
 | 
			
		||||
	int idx_safi = 0;
 | 
			
		||||
	int idx_ipv6_prefix = 0;
 | 
			
		||||
	safi_t safi = SAFI_UNICAST;
 | 
			
		||||
	char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ?
 | 
			
		||||
		argv[idx_ipv6_prefix]->arg : NULL;
 | 
			
		||||
	/* [<view|vrf> VIEWVRFNAME] */
 | 
			
		||||
	char *vrfview = argv_find(argv, argc, "VIEWVRFNAME", &idx_word) ?
 | 
			
		||||
		argv[idx_word]->arg : NULL;
 | 
			
		||||
 | 
			
		||||
	argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
 | 
			
		||||
 | 
			
		||||
	return bgp_clear_prefix(
 | 
			
		||||
		vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg,
 | 
			
		||||
		AFI_IP6, bgp_vty_safi_from_str(argv[idx_safi]->text), NULL);
 | 
			
		||||
		vty, vrfview, prefix,
 | 
			
		||||
		AFI_IP6, safi, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_views,
 | 
			
		||||
@ -6571,9 +6582,8 @@ DEFUN (show_bgp_vrfs,
 | 
			
		||||
 | 
			
		||||
		json_object_int_add(json, "totalVrfs", count);
 | 
			
		||||
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (count)
 | 
			
		||||
@ -6722,20 +6732,17 @@ DEFUN (show_bgp_memory,
 | 
			
		||||
	/* Other attributes */
 | 
			
		||||
	if ((count = community_count()))
 | 
			
		||||
		vty_out(vty, "%ld BGP community entries, using %s of memory\n",
 | 
			
		||||
			count,
 | 
			
		||||
			mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
				     count * sizeof(struct community)));
 | 
			
		||||
			count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
					    count * sizeof(struct community)));
 | 
			
		||||
	if ((count = mtype_stats_alloc(MTYPE_ECOMMUNITY)))
 | 
			
		||||
		vty_out(vty, "%ld BGP community entries, using %s of memory\n",
 | 
			
		||||
			count,
 | 
			
		||||
			mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
				     count * sizeof(struct ecommunity)));
 | 
			
		||||
			count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
					    count * sizeof(struct ecommunity)));
 | 
			
		||||
	if ((count = mtype_stats_alloc(MTYPE_LCOMMUNITY)))
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"%ld BGP large-community entries, using %s of memory\n",
 | 
			
		||||
			count,
 | 
			
		||||
			mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
				     count * sizeof(struct lcommunity)));
 | 
			
		||||
			count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
					    count * sizeof(struct lcommunity)));
 | 
			
		||||
 | 
			
		||||
	if ((count = mtype_stats_alloc(MTYPE_CLUSTER)))
 | 
			
		||||
		vty_out(vty, "%ld Cluster lists, using %s of memory\n", count,
 | 
			
		||||
@ -6764,9 +6771,8 @@ DEFUN (show_bgp_memory,
 | 
			
		||||
				     count * sizeof(struct hash_backet)));
 | 
			
		||||
	if ((count = mtype_stats_alloc(MTYPE_BGP_REGEXP)))
 | 
			
		||||
		vty_out(vty, "%ld compiled regexes, using %s of memory\n",
 | 
			
		||||
			count,
 | 
			
		||||
			mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
				     count * sizeof(regex_t)));
 | 
			
		||||
			count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
					    count * sizeof(regex_t)));
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7018,9 +7024,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
 | 
			
		||||
						json, "peerGroupCount", ents);
 | 
			
		||||
					json_object_int_add(
 | 
			
		||||
						json, "peerGroupMemory",
 | 
			
		||||
						ents
 | 
			
		||||
							* sizeof(struct
 | 
			
		||||
								 peer_group));
 | 
			
		||||
						ents * sizeof(struct
 | 
			
		||||
							      peer_group));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (CHECK_FLAG(bgp->af_flags[afi][safi],
 | 
			
		||||
@ -7043,11 +7048,10 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"RIB entries %ld, using %s of memory\n",
 | 
			
		||||
					ents,
 | 
			
		||||
					mtype_memstr(
 | 
			
		||||
						memstrbuf, sizeof(memstrbuf),
 | 
			
		||||
						ents
 | 
			
		||||
							* sizeof(struct
 | 
			
		||||
								 bgp_node)));
 | 
			
		||||
					mtype_memstr(memstrbuf,
 | 
			
		||||
						     sizeof(memstrbuf),
 | 
			
		||||
						     ents * sizeof(struct
 | 
			
		||||
								   bgp_node)));
 | 
			
		||||
 | 
			
		||||
				/* Peer related usage */
 | 
			
		||||
				ents = listcount(bgp->peer);
 | 
			
		||||
@ -7064,9 +7068,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
 | 
			
		||||
						mtype_memstr(
 | 
			
		||||
							memstrbuf,
 | 
			
		||||
							sizeof(memstrbuf),
 | 
			
		||||
							ents
 | 
			
		||||
								* sizeof(struct
 | 
			
		||||
									 peer_group)));
 | 
			
		||||
							ents * sizeof(struct
 | 
			
		||||
								      peer_group)));
 | 
			
		||||
 | 
			
		||||
				if (CHECK_FLAG(bgp->af_flags[afi][safi],
 | 
			
		||||
					       BGP_CONFIG_DAMPENING))
 | 
			
		||||
@ -7199,9 +7202,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
 | 
			
		||||
 | 
			
		||||
		bgp_show_bestpath_json(bgp, json);
 | 
			
		||||
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (count)
 | 
			
		||||
@ -7836,9 +7838,8 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
 | 
			
		||||
 | 
			
		||||
		paf = peer_af_find(p, afi, safi);
 | 
			
		||||
		if (paf && PAF_SUBGRP(paf)) {
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"  Update group %" PRIu64 ", subgroup %" PRIu64
 | 
			
		||||
				"\n",
 | 
			
		||||
			vty_out(vty, "  Update group %" PRIu64
 | 
			
		||||
				     ", subgroup %" PRIu64 "\n",
 | 
			
		||||
				PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id);
 | 
			
		||||
			vty_out(vty, "  Packet Queue length %d\n",
 | 
			
		||||
				bpacket_queue_virtual_length(paf));
 | 
			
		||||
@ -9638,9 +9639,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
 | 
			
		||||
			} else
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"  Reduce the no. of prefix from %s, will restart in %ld seconds\n",
 | 
			
		||||
					p->host,
 | 
			
		||||
					thread_timer_remain_second(
 | 
			
		||||
						p->t_pmax_restart));
 | 
			
		||||
					p->host, thread_timer_remain_second(
 | 
			
		||||
							 p->t_pmax_restart));
 | 
			
		||||
		} else {
 | 
			
		||||
			if (use_json)
 | 
			
		||||
				json_object_boolean_true_add(
 | 
			
		||||
@ -9884,9 +9884,8 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (use_json) {
 | 
			
		||||
		vty_out(vty, "%s\n",
 | 
			
		||||
			json_object_to_json_string_ext(
 | 
			
		||||
				json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		vty_out(vty, "%s\n", json_object_to_json_string_ext(
 | 
			
		||||
					     json, JSON_C_TO_STRING_PRETTY));
 | 
			
		||||
		json_object_free(json);
 | 
			
		||||
	} else {
 | 
			
		||||
		vty_out(vty, "\n");
 | 
			
		||||
@ -10300,227 +10299,43 @@ static void show_bgp_updgrps_adj_info_aux(struct vty *vty, const char *name,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_ip_bgp_updgrps_adj,
 | 
			
		||||
       show_ip_bgp_updgrps_adj_cmd,
 | 
			
		||||
       "show [ip] bgp update-groups <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
DEFPY(show_ip_bgp_instance_updgrps_adj_s,
 | 
			
		||||
      show_ip_bgp_instance_updgrps_adj_s_cmd,
 | 
			
		||||
      "show [ip]$ip bgp [<view|vrf> VIEWVRFNAME$vrf] [<ipv4|ipv6>$afi <unicast|multicast|vpn>$safi] update-groups [SUBGROUP-ID]$sgid <advertise-queue|advertised-routes|packet-queue>$rtq",
 | 
			
		||||
      SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
 | 
			
		||||
	      BGP_SAFI_HELP_STR
 | 
			
		||||
      "Detailed info about dynamic update groups\n"
 | 
			
		||||
      "Specific subgroup to display info for\n"
 | 
			
		||||
      "Advertisement queue\n"
 | 
			
		||||
      "Announced routes\n"
 | 
			
		||||
      "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_type = 4;
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST,
 | 
			
		||||
				      argv[idx_type]->arg, 0);
 | 
			
		||||
	uint64_t subgrp_id = 0;
 | 
			
		||||
	afi_t afiz;
 | 
			
		||||
	safi_t safiz;
 | 
			
		||||
	if (sgid)
 | 
			
		||||
		subgrp_id = strtoull(sgid, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	if (!ip && !afi)
 | 
			
		||||
		afiz = AFI_IP6;
 | 
			
		||||
	if (!ip && afi)
 | 
			
		||||
		afiz = bgp_vty_afi_from_str(afi);
 | 
			
		||||
	if (ip && !afi)
 | 
			
		||||
		afiz = AFI_IP;
 | 
			
		||||
	if (ip && afi) {
 | 
			
		||||
		afiz = bgp_vty_afi_from_str(afi);
 | 
			
		||||
		if (afiz != AFI_IP)
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"%% Cannot specify both 'ip' and 'ipv6'\n");
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	safiz = safi ? bgp_vty_safi_from_str(safi) : SAFI_UNICAST;
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, vrf, afiz, safiz, rtq, subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_ip_bgp_instance_updgrps_adj,
 | 
			
		||||
       show_ip_bgp_instance_updgrps_adj_cmd,
 | 
			
		||||
       "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_INSTANCE_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_word = 4;
 | 
			
		||||
	int idx_type = 6;
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP,
 | 
			
		||||
				      SAFI_UNICAST, argv[idx_type]->arg, 0);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_updgrps_afi_adj,
 | 
			
		||||
       show_bgp_updgrps_afi_adj_cmd,
 | 
			
		||||
       "show [ip] bgp "BGP_AFI_SAFI_CMD_STR" update-groups <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_AFI_SAFI_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_afi = 2;
 | 
			
		||||
	int idx_safi = 3;
 | 
			
		||||
	int idx_type = 5;
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(
 | 
			
		||||
		vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text),
 | 
			
		||||
		bgp_vty_safi_from_str(argv[idx_safi]->text),
 | 
			
		||||
		argv[idx_type]->arg, 0);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_updgrps_adj,
 | 
			
		||||
       show_bgp_updgrps_adj_cmd,
 | 
			
		||||
       "show [ip] bgp update-groups <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_type = 3;
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST,
 | 
			
		||||
				      argv[idx_type]->arg, 0);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_instance_updgrps_adj,
 | 
			
		||||
       show_bgp_instance_updgrps_adj_cmd,
 | 
			
		||||
       "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_INSTANCE_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_word = 3;
 | 
			
		||||
	int idx_type = 5;
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP6,
 | 
			
		||||
				      SAFI_UNICAST, argv[idx_type]->arg, 0);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_ip_bgp_updgrps_adj_s,
 | 
			
		||||
       show_ip_bgp_updgrps_adj_s_cmd,
 | 
			
		||||
       "show [ip] bgp update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Specific subgroup to display info for\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_subgroup_id = 4;
 | 
			
		||||
	int idx_type = 5;
 | 
			
		||||
	uint64_t subgrp_id;
 | 
			
		||||
 | 
			
		||||
	subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST,
 | 
			
		||||
				      argv[idx_type]->arg, subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_ip_bgp_instance_updgrps_adj_s,
 | 
			
		||||
       show_ip_bgp_instance_updgrps_adj_s_cmd,
 | 
			
		||||
       "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_INSTANCE_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Specific subgroup to display info for\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_vrf = 4;
 | 
			
		||||
	int idx_subgroup_id = 6;
 | 
			
		||||
	int idx_type = 7;
 | 
			
		||||
	uint64_t subgrp_id;
 | 
			
		||||
 | 
			
		||||
	subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP,
 | 
			
		||||
				      SAFI_UNICAST, argv[idx_type]->arg,
 | 
			
		||||
				      subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_updgrps_afi_adj_s,
 | 
			
		||||
       show_bgp_updgrps_afi_adj_s_cmd,
 | 
			
		||||
       "show [ip] bgp "BGP_AFI_SAFI_CMD_STR" update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_AFI_SAFI_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Specific subgroup to display info for\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_afi = 2;
 | 
			
		||||
	int idx_safi = 3;
 | 
			
		||||
	int idx_subgroup_id = 5;
 | 
			
		||||
	int idx_type = 6;
 | 
			
		||||
	uint64_t subgrp_id;
 | 
			
		||||
 | 
			
		||||
	subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(
 | 
			
		||||
		vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text),
 | 
			
		||||
		bgp_vty_safi_from_str(argv[idx_safi]->text),
 | 
			
		||||
		argv[idx_type]->arg, subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_updgrps_adj_s,
 | 
			
		||||
       show_bgp_updgrps_adj_s_cmd,
 | 
			
		||||
       "show [ip] bgp update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Specific subgroup to display info for\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_subgroup_id = 3;
 | 
			
		||||
	int idx_type = 4;
 | 
			
		||||
	uint64_t subgrp_id;
 | 
			
		||||
 | 
			
		||||
	subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST,
 | 
			
		||||
				      argv[idx_type]->arg, subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN (show_bgp_instance_updgrps_adj_s,
 | 
			
		||||
       show_bgp_instance_updgrps_adj_s_cmd,
 | 
			
		||||
       "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups SUBGROUP-ID <advertise-queue|advertised-routes|packet-queue>",
 | 
			
		||||
       SHOW_STR
 | 
			
		||||
       IP_STR
 | 
			
		||||
       BGP_STR
 | 
			
		||||
       BGP_INSTANCE_HELP_STR
 | 
			
		||||
       "Detailed info about dynamic update groups\n"
 | 
			
		||||
       "Specific subgroup to display info for\n"
 | 
			
		||||
       "Advertisement queue\n"
 | 
			
		||||
       "Announced routes\n"
 | 
			
		||||
       "Packet queue\n")
 | 
			
		||||
{
 | 
			
		||||
	int idx_vrf = 3;
 | 
			
		||||
	int idx_subgroup_id = 5;
 | 
			
		||||
	int idx_type = 6;
 | 
			
		||||
	uint64_t subgrp_id;
 | 
			
		||||
 | 
			
		||||
	subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10);
 | 
			
		||||
 | 
			
		||||
	show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP6,
 | 
			
		||||
				      SAFI_UNICAST, argv[idx_type]->arg,
 | 
			
		||||
				      subgrp_id);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
 | 
			
		||||
{
 | 
			
		||||
	struct listnode *node, *nnode;
 | 
			
		||||
@ -12435,19 +12250,10 @@ void bgp_vty_init(void)
 | 
			
		||||
 | 
			
		||||
	/* "show [ip] bgp summary" commands. */
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_updgrps_adj_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_updgrps_adj_s_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_bgp_updgrps_stats_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_summary_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd);
 | 
			
		||||
	install_element(VIEW_NODE, &show_ip_bgp_updgrps_cmd);
 | 
			
		||||
 | 
			
		||||
	/* "show [ip] bgp neighbors" commands. */
 | 
			
		||||
 | 
			
		||||
@ -1746,8 +1746,7 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
 | 
			
		||||
	if (BGP_DEBUG(zebra, ZEBRA))
 | 
			
		||||
		zlog_debug("Rx L3-VNI %s VRF %s VNI %u RMAC %s filter %s",
 | 
			
		||||
			   (cmd == ZEBRA_L3VNI_ADD) ? "add" : "del",
 | 
			
		||||
			   vrf_id_to_name(vrf_id),
 | 
			
		||||
			   l3vni,
 | 
			
		||||
			   vrf_id_to_name(vrf_id), l3vni,
 | 
			
		||||
			   prefix_mac2str(&rmac, buf, sizeof(buf)),
 | 
			
		||||
			   filter ? "prefix-routes-only" : "none");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								bgpd/bgpd.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								bgpd/bgpd.c
									
									
									
									
									
								
							@ -108,7 +108,8 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp)
 | 
			
		||||
	struct listnode *bgpnode, *nbgpnode;
 | 
			
		||||
	struct bgp *bgp_temp;
 | 
			
		||||
 | 
			
		||||
	if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
 | 
			
		||||
	if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF &&
 | 
			
		||||
	    vrf_is_mapped_on_netns(bgp->vrf_id))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (create == true) {
 | 
			
		||||
		if (bgp_server_main_created)
 | 
			
		||||
@ -1078,10 +1079,8 @@ static void peer_free(struct peer *peer)
 | 
			
		||||
		XFREE(MTYPE_TMP, peer->notify.data);
 | 
			
		||||
	memset(&peer->notify, 0, sizeof(struct bgp_notify));
 | 
			
		||||
 | 
			
		||||
	if (peer->clear_node_queue) {
 | 
			
		||||
		work_queue_free(peer->clear_node_queue);
 | 
			
		||||
		peer->clear_node_queue = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (peer->clear_node_queue)
 | 
			
		||||
		work_queue_free_and_null(&peer->clear_node_queue);
 | 
			
		||||
 | 
			
		||||
	bgp_sync_delete(peer);
 | 
			
		||||
 | 
			
		||||
@ -3019,17 +3018,15 @@ struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
 | 
			
		||||
/* handle socket creation or deletion, if necessary
 | 
			
		||||
 * this is called for all new BGP instances
 | 
			
		||||
 */
 | 
			
		||||
int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf,
 | 
			
		||||
			  vrf_id_t old_vrf_id, bool create)
 | 
			
		||||
int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
 | 
			
		||||
		      bool create)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	/* Create BGP server socket, if listen mode not disabled */
 | 
			
		||||
	if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (bgp->name
 | 
			
		||||
	    && bgp->inst_type == BGP_INSTANCE_TYPE_VRF
 | 
			
		||||
	    && vrf) {
 | 
			
		||||
	if (bgp->name && bgp->inst_type == BGP_INSTANCE_TYPE_VRF && vrf) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * suppress vrf socket
 | 
			
		||||
		 */
 | 
			
		||||
@ -3425,8 +3422,8 @@ struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
 | 
			
		||||
			 * invoked without an instance
 | 
			
		||||
			 * when examining VRFs.
 | 
			
		||||
			 */
 | 
			
		||||
			if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF) &&
 | 
			
		||||
			    !vrf_is_mapped_on_netns(bgp->vrf_id))
 | 
			
		||||
			if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
 | 
			
		||||
			    && !vrf_is_mapped_on_netns(bgp->vrf_id))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			peer = hash_lookup(bgp->peerhash, &tmp_peer);
 | 
			
		||||
@ -4070,9 +4067,8 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Track if addpath TX is in use */
 | 
			
		||||
	if (flag
 | 
			
		||||
	    & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
 | 
			
		||||
	       | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
 | 
			
		||||
	if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
 | 
			
		||||
		    | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
 | 
			
		||||
		bgp = peer->bgp;
 | 
			
		||||
		addpath_tx_used = 0;
 | 
			
		||||
 | 
			
		||||
@ -6885,9 +6881,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!peer_af_flag_check(peer, afi, safi,
 | 
			
		||||
					PEER_FLAG_SEND_COMMUNITY)
 | 
			
		||||
		    && (!g_peer
 | 
			
		||||
			|| peer_af_flag_check(g_peer, afi, safi,
 | 
			
		||||
					      PEER_FLAG_SEND_COMMUNITY))
 | 
			
		||||
		    && (!g_peer || peer_af_flag_check(g_peer, afi, safi,
 | 
			
		||||
						      PEER_FLAG_SEND_COMMUNITY))
 | 
			
		||||
		    && !peer_af_flag_check(peer, afi, safi,
 | 
			
		||||
					   PEER_FLAG_SEND_EXT_COMMUNITY)
 | 
			
		||||
		    && (!g_peer
 | 
			
		||||
@ -6895,10 +6890,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
					      PEER_FLAG_SEND_EXT_COMMUNITY))
 | 
			
		||||
		    && !peer_af_flag_check(peer, afi, safi,
 | 
			
		||||
					   PEER_FLAG_SEND_LARGE_COMMUNITY)
 | 
			
		||||
		    && (!g_peer
 | 
			
		||||
			|| peer_af_flag_check(
 | 
			
		||||
				   g_peer, afi, safi,
 | 
			
		||||
				   PEER_FLAG_SEND_LARGE_COMMUNITY))) {
 | 
			
		||||
		    && (!g_peer || peer_af_flag_check(
 | 
			
		||||
					   g_peer, afi, safi,
 | 
			
		||||
					   PEER_FLAG_SEND_LARGE_COMMUNITY))) {
 | 
			
		||||
			vty_out(vty, "  no neighbor %s send-community all\n",
 | 
			
		||||
				addr);
 | 
			
		||||
		} else {
 | 
			
		||||
@ -6926,10 +6920,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
 | 
			
		||||
 | 
			
		||||
			if (!peer_af_flag_check(peer, afi, safi,
 | 
			
		||||
						PEER_FLAG_SEND_COMMUNITY)
 | 
			
		||||
			    && (!g_peer
 | 
			
		||||
				|| peer_af_flag_check(
 | 
			
		||||
					   g_peer, afi, safi,
 | 
			
		||||
					   PEER_FLAG_SEND_COMMUNITY))) {
 | 
			
		||||
			    && (!g_peer || peer_af_flag_check(
 | 
			
		||||
						   g_peer, afi, safi,
 | 
			
		||||
						   PEER_FLAG_SEND_COMMUNITY))) {
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"  no neighbor %s send-community\n",
 | 
			
		||||
					addr);
 | 
			
		||||
@ -7644,10 +7637,8 @@ void bgp_terminate(void)
 | 
			
		||||
				bgp_notify_send(peer, BGP_NOTIFY_CEASE,
 | 
			
		||||
						BGP_NOTIFY_CEASE_PEER_UNCONFIG);
 | 
			
		||||
 | 
			
		||||
	if (bm->process_main_queue) {
 | 
			
		||||
		work_queue_free(bm->process_main_queue);
 | 
			
		||||
		bm->process_main_queue = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (bm->process_main_queue)
 | 
			
		||||
		work_queue_free_and_null(&bm->process_main_queue);
 | 
			
		||||
 | 
			
		||||
	if (bm->t_rmap_update)
 | 
			
		||||
		BGP_TIMER_OFF(bm->t_rmap_update);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								bgpd/bgpd.h
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								bgpd/bgpd.h
									
									
									
									
									
								
							@ -133,8 +133,6 @@ struct bgp_master {
 | 
			
		||||
	/* timer to dampen route map changes */
 | 
			
		||||
	struct thread *t_rmap_update; /* Handle route map updates */
 | 
			
		||||
	u_int32_t rmap_update_timer;  /* Route map update timer */
 | 
			
		||||
				      /* $FRR indent$ */
 | 
			
		||||
				      /* clang-format off */
 | 
			
		||||
#define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
 | 
			
		||||
 | 
			
		||||
	/* Id space for automatic RD derivation for an EVI/VRF */
 | 
			
		||||
@ -249,8 +247,6 @@ struct bgp {
 | 
			
		||||
		*t_startup; /* start-up timer on only once at the beginning */
 | 
			
		||||
 | 
			
		||||
	u_int32_t v_maxmed_onstartup;     /* Duration of max-med on start-up */
 | 
			
		||||
					  /* $FRR indent$ */
 | 
			
		||||
					  /* clang-format off */
 | 
			
		||||
#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED  0 /* 0 means off, its the default */
 | 
			
		||||
	u_int32_t maxmed_onstartup_value; /* Max-med value when active on
 | 
			
		||||
					     start-up */
 | 
			
		||||
@ -259,17 +255,13 @@ struct bgp {
 | 
			
		||||
	u_char maxmed_onstartup_over; /* Flag to make it effective only once */
 | 
			
		||||
 | 
			
		||||
	u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */
 | 
			
		||||
			       /* $FRR indent$ */
 | 
			
		||||
			       /* clang-format off */
 | 
			
		||||
#define BGP_MAXMED_ADMIN_UNCONFIGURED  0 /* Off by default */
 | 
			
		||||
	u_int32_t maxmed_admin_value; /* Max-med value when administrative in on
 | 
			
		||||
				       */
 | 
			
		||||
				      /* $FRR indent$ */
 | 
			
		||||
				      /* clang-format off */
 | 
			
		||||
#define BGP_MAXMED_VALUE_DEFAULT  4294967294 /* Maximum by default */
 | 
			
		||||
 | 
			
		||||
	u_char maxmed_active;	 /* 1/0 if max-med is active or not */
 | 
			
		||||
	u_int32_t maxmed_value;       /* Max-med value when its active */
 | 
			
		||||
	u_char maxmed_active;   /* 1/0 if max-med is active or not */
 | 
			
		||||
	u_int32_t maxmed_value; /* Max-med value when its active */
 | 
			
		||||
 | 
			
		||||
	/* BGP update delay on startup */
 | 
			
		||||
	struct thread *t_update_delay;
 | 
			
		||||
@ -320,6 +312,13 @@ struct bgp {
 | 
			
		||||
	u_int16_t af_flags[AFI_MAX][SAFI_MAX];
 | 
			
		||||
#define BGP_CONFIG_DAMPENING              (1 << 0)
 | 
			
		||||
 | 
			
		||||
/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
 | 
			
		||||
#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST      (1 << 1)
 | 
			
		||||
#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST      (1 << 2)
 | 
			
		||||
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4	   (1 << 3)
 | 
			
		||||
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6	   (1 << 4)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* Route table for next-hop lookup cache. */
 | 
			
		||||
	struct bgp_table *nexthop_cache_table[AFI_MAX];
 | 
			
		||||
 | 
			
		||||
@ -431,12 +430,11 @@ struct bgp {
 | 
			
		||||
	/* vrf flags */
 | 
			
		||||
	uint32_t vrf_flags;
 | 
			
		||||
#define BGP_VRF_AUTO                        (1 << 0)
 | 
			
		||||
#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN      (1 << 1)
 | 
			
		||||
#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN      (1 << 2)
 | 
			
		||||
#define BGP_VRF_IMPORT_RT_CFGD              (1 << 3)
 | 
			
		||||
#define BGP_VRF_EXPORT_RT_CFGD              (1 << 4)
 | 
			
		||||
#define BGP_VRF_RD_CFGD                     (1 << 5)
 | 
			
		||||
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY    (1 << 6)
 | 
			
		||||
#define BGP_VRF_IMPORT_RT_CFGD              (1 << 1)
 | 
			
		||||
#define BGP_VRF_EXPORT_RT_CFGD              (1 << 2)
 | 
			
		||||
#define BGP_VRF_RD_CFGD                     (1 << 3)
 | 
			
		||||
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY    (1 << 4)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* unique ID for auto derivation of RD for this vrf */
 | 
			
		||||
	uint16_t vrf_rd_id;
 | 
			
		||||
@ -680,8 +678,6 @@ struct peer {
 | 
			
		||||
	unsigned short port; /* Destination port for peer */
 | 
			
		||||
	char *host;	  /* Printable address of the peer. */
 | 
			
		||||
	union sockunion su;  /* Sockunion address of the peer. */
 | 
			
		||||
			     /* $FRR indent$ */
 | 
			
		||||
			     /* clang-format off */
 | 
			
		||||
#define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC)
 | 
			
		||||
	time_t uptime;       /* Last Up/Down time */
 | 
			
		||||
	time_t readtime;     /* Last read time */
 | 
			
		||||
@ -898,8 +894,8 @@ struct peer {
 | 
			
		||||
				       memory_order_relaxed)
 | 
			
		||||
 | 
			
		||||
	/* Statistics field */
 | 
			
		||||
	_Atomic uint32_t open_in;         /* Open message input count */
 | 
			
		||||
	_Atomic uint32_t open_out;        /* Open message output count */
 | 
			
		||||
	_Atomic uint32_t open_in;	 /* Open message input count */
 | 
			
		||||
	_Atomic uint32_t open_out;	/* Open message output count */
 | 
			
		||||
	_Atomic uint32_t update_in;       /* Update message input count */
 | 
			
		||||
	_Atomic uint32_t update_out;      /* Update message ouput count */
 | 
			
		||||
	_Atomic time_t update_time;       /* Update message received time. */
 | 
			
		||||
 | 
			
		||||
@ -1636,9 +1636,8 @@ DEFUN (vnc_nve_group_export_no_prefixlist,
 | 
			
		||||
	idx += 2; /* skip afi and keyword */
 | 
			
		||||
 | 
			
		||||
	if (is_bgp) {
 | 
			
		||||
		if (idx == argc
 | 
			
		||||
		    || strmatch(argv[idx]->arg,
 | 
			
		||||
				rfg->plist_export_bgp_name[afi])) {
 | 
			
		||||
		if (idx == argc || strmatch(argv[idx]->arg,
 | 
			
		||||
					    rfg->plist_export_bgp_name[afi])) {
 | 
			
		||||
			if (rfg->plist_export_bgp_name[afi])
 | 
			
		||||
				free(rfg->plist_export_bgp_name[afi]);
 | 
			
		||||
			rfg->plist_export_bgp_name[afi] = NULL;
 | 
			
		||||
@ -1768,9 +1767,8 @@ DEFUN (vnc_nve_group_export_no_routemap,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_bgp) {
 | 
			
		||||
		if (idx == argc
 | 
			
		||||
		    || strmatch(argv[idx]->arg,
 | 
			
		||||
				rfg->routemap_export_bgp_name)) {
 | 
			
		||||
		if (idx == argc || strmatch(argv[idx]->arg,
 | 
			
		||||
					    rfg->routemap_export_bgp_name)) {
 | 
			
		||||
			if (rfg->routemap_export_bgp_name)
 | 
			
		||||
				free(rfg->routemap_export_bgp_name);
 | 
			
		||||
			rfg->routemap_export_bgp_name = NULL;
 | 
			
		||||
@ -1780,9 +1778,8 @@ DEFUN (vnc_nve_group_export_no_routemap,
 | 
			
		||||
			vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (idx == argc
 | 
			
		||||
		    || strmatch(argv[idx]->arg,
 | 
			
		||||
				rfg->routemap_export_zebra_name)) {
 | 
			
		||||
		if (idx == argc || strmatch(argv[idx]->arg,
 | 
			
		||||
					    rfg->routemap_export_zebra_name)) {
 | 
			
		||||
			if (rfg->routemap_export_zebra_name)
 | 
			
		||||
				free(rfg->routemap_export_zebra_name);
 | 
			
		||||
			rfg->routemap_export_zebra_name = NULL;
 | 
			
		||||
@ -2978,7 +2975,8 @@ DEFUN_NOSH (vnc_vrf_policy,
 | 
			
		||||
	VTY_DECLVAR_CONTEXT(bgp, bgp);
 | 
			
		||||
 | 
			
		||||
	if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
 | 
			
		||||
		vty_out(vty, "Can't configure vrf-policy within a BGP VRF instance\n");
 | 
			
		||||
		vty_out(vty,
 | 
			
		||||
			"Can't configure vrf-policy within a BGP VRF instance\n");
 | 
			
		||||
		return CMD_WARNING_CONFIG_FAILED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -383,9 +383,8 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
 | 
			
		||||
 | 
			
		||||
	vnc_zlog_debug_verbose(
 | 
			
		||||
		"%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
 | 
			
		||||
		__func__, peer, buf,
 | 
			
		||||
		prefix_rd2str(prd, buf2, sizeof(buf2)), afi, safi, bn,
 | 
			
		||||
		(bn ? bn->info : NULL));
 | 
			
		||||
		__func__, peer, buf, prefix_rd2str(prd, buf2, sizeof(buf2)),
 | 
			
		||||
		afi, safi, bn, (bn ? bn->info : NULL));
 | 
			
		||||
 | 
			
		||||
	for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) {
 | 
			
		||||
 | 
			
		||||
@ -749,9 +748,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
 | 
			
		||||
	if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) {
 | 
			
		||||
		uint32_t lt;
 | 
			
		||||
 | 
			
		||||
		encaptlv =
 | 
			
		||||
			XCALLOC(MTYPE_ENCAP_TLV,
 | 
			
		||||
				sizeof(struct bgp_attr_encap_subtlv) + 4);
 | 
			
		||||
		encaptlv = XCALLOC(MTYPE_ENCAP_TLV,
 | 
			
		||||
				   sizeof(struct bgp_attr_encap_subtlv) + 4);
 | 
			
		||||
		assert(encaptlv);
 | 
			
		||||
		encaptlv->type =
 | 
			
		||||
			BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */
 | 
			
		||||
@ -795,8 +793,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
 | 
			
		||||
				 */
 | 
			
		||||
				encaptlv = XCALLOC(
 | 
			
		||||
					MTYPE_ENCAP_TLV,
 | 
			
		||||
					sizeof(struct bgp_attr_encap_subtlv)
 | 
			
		||||
					+ 2 + hop->length);
 | 
			
		||||
					sizeof(struct bgp_attr_encap_subtlv) + 2
 | 
			
		||||
						+ hop->length);
 | 
			
		||||
				assert(encaptlv);
 | 
			
		||||
				encaptlv->type =
 | 
			
		||||
					BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP
 | 
			
		||||
 | 
			
		||||
@ -1083,9 +1083,8 @@ int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id)
 | 
			
		||||
				} else if (encode == ECOMMUNITY_ENCODE_AS) {
 | 
			
		||||
					as = (*p++ << 8);
 | 
			
		||||
					as |= (*p++);
 | 
			
		||||
					p +=
 | 
			
		||||
						2; /* skip next two, tag/vid
 | 
			
		||||
						      always in lowest bytes */
 | 
			
		||||
					p += 2; /* skip next two, tag/vid
 | 
			
		||||
						   always in lowest bytes */
 | 
			
		||||
				}
 | 
			
		||||
				if (as == bgp->as) {
 | 
			
		||||
					*tag_id = *p++ << 8;
 | 
			
		||||
@ -1221,8 +1220,7 @@ static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2)
 | 
			
		||||
 | 
			
		||||
	switch (pfx_un1.family) {
 | 
			
		||||
	case AF_INET:
 | 
			
		||||
		if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4,
 | 
			
		||||
				    &pfx_un2.u.prefix4))
 | 
			
		||||
		if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4, &pfx_un2.u.prefix4))
 | 
			
		||||
			return 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case AF_INET6:
 | 
			
		||||
@ -2235,9 +2233,9 @@ static struct bgp_info *rfapiItBiIndexSearch(
 | 
			
		||||
 | 
			
		||||
				vnc_zlog_debug_verbose(
 | 
			
		||||
					"%s: bi has prd=%s, peer=%p", __func__,
 | 
			
		||||
					prefix_rd2str(&bi_result->extra->vnc.import.rd,
 | 
			
		||||
						      buf,
 | 
			
		||||
						      sizeof(buf)),
 | 
			
		||||
					prefix_rd2str(&bi_result->extra->vnc
 | 
			
		||||
							       .import.rd,
 | 
			
		||||
						      buf, sizeof(buf)),
 | 
			
		||||
					bi_result->peer);
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
@ -4338,7 +4336,7 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h)
 | 
			
		||||
		h->import_mac = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	work_queue_free(h->deferred_close_q);
 | 
			
		||||
	work_queue_free_and_null(&h->deferred_close_q);
 | 
			
		||||
 | 
			
		||||
	if (h->rfp != NULL)
 | 
			
		||||
		rfp_stop(h->rfp);
 | 
			
		||||
 | 
			
		||||
@ -929,17 +929,14 @@ void rfapiMonitorItNodeChanged(
 | 
			
		||||
					char buf_attach_pfx[PREFIX_STRLEN];
 | 
			
		||||
					char buf_target_pfx[PREFIX_STRLEN];
 | 
			
		||||
 | 
			
		||||
					prefix2str(&m->node->p,
 | 
			
		||||
						   buf_attach_pfx,
 | 
			
		||||
					prefix2str(&m->node->p, buf_attach_pfx,
 | 
			
		||||
						   sizeof(buf_attach_pfx));
 | 
			
		||||
					prefix2str(&m->p,
 | 
			
		||||
						   buf_target_pfx,
 | 
			
		||||
					prefix2str(&m->p, buf_target_pfx,
 | 
			
		||||
						   sizeof(buf_target_pfx));
 | 
			
		||||
					vnc_zlog_debug_verbose(
 | 
			
		||||
						"%s: update rfd %p attached to pfx %s (targ=%s)",
 | 
			
		||||
						__func__, m->rfd,
 | 
			
		||||
						buf_attach_pfx,
 | 
			
		||||
						buf_target_pfx);
 | 
			
		||||
						buf_attach_pfx, buf_target_pfx);
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * update its RIB
 | 
			
		||||
 | 
			
		||||
@ -345,7 +345,8 @@ extern void rfapi_un_options_free(struct rfapi_un_option *goner);
 | 
			
		||||
 | 
			
		||||
extern void rfapi_vn_options_free(struct rfapi_vn_option *goner);
 | 
			
		||||
 | 
			
		||||
extern void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg);
 | 
			
		||||
extern void vnc_add_vrf_opener(struct bgp *bgp,
 | 
			
		||||
			       struct rfapi_nve_group_cfg *rfg);
 | 
			
		||||
extern void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg);
 | 
			
		||||
/*------------------------------------------
 | 
			
		||||
 * rfapi_extract_l2o
 | 
			
		||||
 | 
			
		||||
@ -511,7 +511,8 @@ void rfapiRibClear(struct rfapi_descriptor *rfd)
 | 
			
		||||
				if (pn->info) {
 | 
			
		||||
					if (pn->info != (void *)1) {
 | 
			
		||||
						list_delete_and_null(
 | 
			
		||||
							(struct list **)(&pn->info));
 | 
			
		||||
							(struct list *
 | 
			
		||||
								 *)(&pn->info));
 | 
			
		||||
					}
 | 
			
		||||
					pn->info = NULL;
 | 
			
		||||
					/* linklist or 1 deleted */
 | 
			
		||||
@ -570,10 +571,8 @@ void rfapiRibClear(struct rfapi_descriptor *rfd)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (rfd->updated_responses_queue) {
 | 
			
		||||
		work_queue_free(rfd->updated_responses_queue);
 | 
			
		||||
		rfd->updated_responses_queue = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (rfd->updated_responses_queue)
 | 
			
		||||
		work_queue_free_and_null(&rfd->updated_responses_queue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -1407,9 +1406,10 @@ callback:
 | 
			
		||||
						vnc_zlog_debug_verbose(
 | 
			
		||||
							"%s: move route to recently deleted list, rd=%s",
 | 
			
		||||
							__func__,
 | 
			
		||||
							prefix_rd2str(&ri->rk.rd,
 | 
			
		||||
								      buf_rd,
 | 
			
		||||
								      sizeof(buf_rd)));
 | 
			
		||||
							prefix_rd2str(
 | 
			
		||||
								&ri->rk.rd,
 | 
			
		||||
								buf_rd,
 | 
			
		||||
								sizeof(buf_rd)));
 | 
			
		||||
					}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1163,8 +1163,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
 | 
			
		||||
		 * print that on the next line
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		if (bi->extra
 | 
			
		||||
		    && bi->extra->vnc.import.aux_prefix.family) {
 | 
			
		||||
		if (bi->extra && bi->extra->vnc.import.aux_prefix.family) {
 | 
			
		||||
			const char *sp;
 | 
			
		||||
 | 
			
		||||
			sp = rfapi_ntop(
 | 
			
		||||
@ -4630,7 +4629,7 @@ notcfg:
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
void vnc_add_vrf_opener(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
 | 
			
		||||
{
 | 
			
		||||
	if (rfg->rfd == NULL) {	/* need new rfapi_handle */
 | 
			
		||||
	if (rfg->rfd == NULL) { /* need new rfapi_handle */
 | 
			
		||||
		/* based on rfapi_open */
 | 
			
		||||
		struct rfapi_descriptor *rfd;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -53,8 +53,7 @@
 | 
			
		||||
 | 
			
		||||
static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
				       struct rfapi_nve_group_cfg *rfg,
 | 
			
		||||
				       struct route_node *rn,
 | 
			
		||||
				       struct attr *attr,
 | 
			
		||||
				       struct route_node *rn, struct attr *attr,
 | 
			
		||||
				       afi_t afi,
 | 
			
		||||
				       struct rfapi_descriptor *irfd);
 | 
			
		||||
 | 
			
		||||
@ -879,8 +878,9 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
 | 
			
		||||
				     NULL,		 /* attr, ignored */
 | 
			
		||||
				     afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
				     BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
				     NULL,	/* RD not used for unicast */
 | 
			
		||||
				     NULL, 0, NULL); /* tag not used for unicast */
 | 
			
		||||
				     NULL, /* RD not used for unicast */
 | 
			
		||||
				     NULL, 0,
 | 
			
		||||
				     NULL); /* tag not used for unicast */
 | 
			
		||||
			/*
 | 
			
		||||
			 * yuck!
 | 
			
		||||
			 *  - but consistent with rest of function
 | 
			
		||||
@ -908,8 +908,9 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp,
 | 
			
		||||
				     NULL,		 /* attr, ignored */
 | 
			
		||||
				     afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
				     BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
				     NULL,	/* RD not used for unicast */
 | 
			
		||||
				     NULL, 0, NULL); /* tag not used for unicast */
 | 
			
		||||
				     NULL, /* RD not used for unicast */
 | 
			
		||||
				     NULL, 0,
 | 
			
		||||
				     NULL); /* tag not used for unicast */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1035,20 +1036,18 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
 | 
			
		||||
 | 
			
		||||
					iattr = bgp_attr_intern(&hattr);
 | 
			
		||||
					bgp_attr_flush(&hattr);
 | 
			
		||||
 | 
			
		||||
					bgp_update(irfd->peer,
 | 
			
		||||
						   &rn->p, /* prefix */
 | 
			
		||||
						   0,      /* addpath_id */
 | 
			
		||||
						   iattr,  /* bgp_update copies
 | 
			
		||||
							      it */
 | 
			
		||||
						   afi, SAFI_UNICAST,
 | 
			
		||||
						   ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
						   BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
						   NULL,     /* RD not used for
 | 
			
		||||
								unicast */
 | 
			
		||||
						   NULL,     /* tag not used for
 | 
			
		||||
								unicast */
 | 
			
		||||
						   0, 0, NULL); /* EVPN not used */
 | 
			
		||||
					bgp_update(
 | 
			
		||||
						irfd->peer, &rn->p, /* prefix */
 | 
			
		||||
						0,     /* addpath_id */
 | 
			
		||||
						iattr, /* bgp_update copies
 | 
			
		||||
							  it */
 | 
			
		||||
						afi, SAFI_UNICAST,
 | 
			
		||||
						ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
						BGP_ROUTE_REDISTRIBUTE, NULL,
 | 
			
		||||
						/* RD not used for unicast */
 | 
			
		||||
						NULL,
 | 
			
		||||
						/* tag not used for unicast */
 | 
			
		||||
						0, 0, NULL); /* EVPN not used */
 | 
			
		||||
 | 
			
		||||
					bgp_attr_unintern(&iattr);
 | 
			
		||||
				}
 | 
			
		||||
@ -1153,10 +1152,8 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
 | 
			
		||||
 | 
			
		||||
static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
				       struct rfapi_nve_group_cfg *rfg,
 | 
			
		||||
				       struct route_node *rn,
 | 
			
		||||
				       struct attr *attr,
 | 
			
		||||
				       afi_t afi,
 | 
			
		||||
				       struct rfapi_descriptor *irfd)
 | 
			
		||||
				       struct route_node *rn, struct attr *attr,
 | 
			
		||||
				       afi_t afi, struct rfapi_descriptor *irfd)
 | 
			
		||||
{
 | 
			
		||||
	struct prefix nhp;
 | 
			
		||||
	struct bgp_info info;
 | 
			
		||||
@ -1169,23 +1166,26 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
		assert(rfg->rfd == NULL);
 | 
			
		||||
 | 
			
		||||
		if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
 | 
			
		||||
			vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing RT import/export configuration.\n",
 | 
			
		||||
					       __func__, rfg->name);
 | 
			
		||||
			vnc_zlog_debug_verbose(
 | 
			
		||||
				"%s: VRF \"%s\" is missing RT import/export configuration.\n",
 | 
			
		||||
				__func__, rfg->name);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if (!rfg->rd.prefixlen) {
 | 
			
		||||
			vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing RD configuration.\n",
 | 
			
		||||
					       __func__, rfg->name);
 | 
			
		||||
			vnc_zlog_debug_verbose(
 | 
			
		||||
				"%s: VRF \"%s\" is missing RD configuration.\n",
 | 
			
		||||
				__func__, rfg->name);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if (rfg->label > MPLS_LABEL_MAX) {
 | 
			
		||||
			vnc_zlog_debug_verbose("%s: VRF \"%s\" is missing defaul label configuration.\n",
 | 
			
		||||
					       __func__, rfg->name);
 | 
			
		||||
			vnc_zlog_debug_verbose(
 | 
			
		||||
				"%s: VRF \"%s\" is missing defaul label configuration.\n",
 | 
			
		||||
				__func__, rfg->name);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		irfd = XCALLOC(MTYPE_RFAPI_DESC,
 | 
			
		||||
			      sizeof(struct rfapi_descriptor));
 | 
			
		||||
			       sizeof(struct rfapi_descriptor));
 | 
			
		||||
		irfd->bgp = bgp;
 | 
			
		||||
		rfg->rfd = irfd;
 | 
			
		||||
		/*
 | 
			
		||||
@ -1221,11 +1221,9 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
 | 
			
		||||
		vnc_zlog_debug_any("%s: attr follows",
 | 
			
		||||
				   __func__);
 | 
			
		||||
		vnc_zlog_debug_any("%s: attr follows", __func__);
 | 
			
		||||
		rfapiPrintAttrPtrs(NULL, attr);
 | 
			
		||||
		vnc_zlog_debug_any("%s: hattr follows",
 | 
			
		||||
				   __func__);
 | 
			
		||||
		vnc_zlog_debug_any("%s: hattr follows", __func__);
 | 
			
		||||
		rfapiPrintAttrPtrs(NULL, &hattr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1234,12 +1232,13 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
 | 
			
		||||
		info.peer = irfd->peer;
 | 
			
		||||
		info.attr = &hattr;
 | 
			
		||||
		ret = route_map_apply(rfg->routemap_export_bgp,
 | 
			
		||||
				      &rn->p, RMAP_BGP, &info);
 | 
			
		||||
		ret = route_map_apply(rfg->routemap_export_bgp, &rn->p,
 | 
			
		||||
				      RMAP_BGP, &info);
 | 
			
		||||
		if (ret == RMAP_DENYMATCH) {
 | 
			
		||||
			bgp_attr_flush(&hattr);
 | 
			
		||||
			vnc_zlog_debug_verbose("%s: route map says DENY, so not calling bgp_update",
 | 
			
		||||
					       __func__);
 | 
			
		||||
			vnc_zlog_debug_verbose(
 | 
			
		||||
				"%s: route map says DENY, so not calling bgp_update",
 | 
			
		||||
				__func__);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -1254,13 +1253,11 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
 | 
			
		||||
	bgp_update(irfd->peer, &rn->p, /* prefix */
 | 
			
		||||
		   0,		       /* addpath_id */
 | 
			
		||||
		   iattr, /* bgp_update copies it */
 | 
			
		||||
		   afi, SAFI_UNICAST,
 | 
			
		||||
		   ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
		   BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
		   NULL, /* RD not used for unicast */
 | 
			
		||||
		   NULL, /* tag not used for unicast */
 | 
			
		||||
		   0, 0, NULL); /* EVPN not used */
 | 
			
		||||
		   iattr,	      /* bgp_update copies it */
 | 
			
		||||
		   afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
		   BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
 | 
			
		||||
		   NULL,			 /* tag not used for unicast */
 | 
			
		||||
		   0, 0, NULL);			 /* EVPN not used */
 | 
			
		||||
 | 
			
		||||
	bgp_attr_unintern(&iattr);
 | 
			
		||||
 | 
			
		||||
@ -1340,7 +1337,8 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
 | 
			
		||||
			for (ln = listhead(rfg->nves); ln;
 | 
			
		||||
			     ln = listnextnode(ln)) {
 | 
			
		||||
				vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
 | 
			
		||||
						   afi, listgetdata(ln));
 | 
			
		||||
							   afi,
 | 
			
		||||
							   listgetdata(ln));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -1361,21 +1359,17 @@ void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
 | 
			
		||||
 | 
			
		||||
static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
 | 
			
		||||
				       struct rfapi_nve_group_cfg *rfg,
 | 
			
		||||
				       struct route_node *rn,
 | 
			
		||||
				       afi_t afi,
 | 
			
		||||
				       struct route_node *rn, afi_t afi,
 | 
			
		||||
				       struct rfapi_descriptor *irfd)
 | 
			
		||||
{
 | 
			
		||||
	if (irfd == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	bgp_withdraw(irfd->peer, &rn->p, /* prefix */
 | 
			
		||||
		     0,		    /* addpath_id */
 | 
			
		||||
		     NULL,		    /* attr, ignored */
 | 
			
		||||
		     afi, SAFI_UNICAST,
 | 
			
		||||
		     ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
		     BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
		     NULL, /* RD not used for unicast */
 | 
			
		||||
		     NULL, 0,
 | 
			
		||||
		     NULL); /* tag not used for unicast */
 | 
			
		||||
		     0,			 /* addpath_id */
 | 
			
		||||
		     NULL,		 /* attr, ignored */
 | 
			
		||||
		     afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
 | 
			
		||||
		     BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
 | 
			
		||||
		     NULL, 0, NULL); /* tag not used for unicast */
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1414,20 +1408,22 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
 | 
			
		||||
	for (rn = route_top(rt); rn; rn = route_next(rn))
 | 
			
		||||
		if (rn->info) {
 | 
			
		||||
			if (rfg->type == RFAPI_GROUP_CFG_VRF)
 | 
			
		||||
				vnc_direct_del_rn_group_rd(bgp, rfg, rn,
 | 
			
		||||
							   afi, rfg->rfd);
 | 
			
		||||
				vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
 | 
			
		||||
							   rfg->rfd);
 | 
			
		||||
			else {
 | 
			
		||||
				struct listnode *ln;
 | 
			
		||||
 | 
			
		||||
				/*
 | 
			
		||||
				 * For each NVE that is assigned to the export nve
 | 
			
		||||
				 * For each NVE that is assigned to the export
 | 
			
		||||
				 * nve
 | 
			
		||||
				 * group, generate
 | 
			
		||||
				 * a route with that NVE as its next hop
 | 
			
		||||
				 */
 | 
			
		||||
				for (ln = listhead(rfg->nves); ln;
 | 
			
		||||
				     ln = listnextnode(ln))
 | 
			
		||||
					vnc_direct_del_rn_group_rd(bgp, rfg, rn,
 | 
			
		||||
						afi, listgetdata(ln));
 | 
			
		||||
					vnc_direct_del_rn_group_rd(
 | 
			
		||||
						bgp, rfg, rn, afi,
 | 
			
		||||
						listgetdata(ln));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
@ -1531,8 +1527,8 @@ static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
 | 
			
		||||
		if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
 | 
			
		||||
			if (rfgn->rfg->nves)
 | 
			
		||||
				nve_group_to_nve_list(rfgn->rfg, nves, family);
 | 
			
		||||
			else if (rfgn->rfg->rfd &&
 | 
			
		||||
				 rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
 | 
			
		||||
			else if (rfgn->rfg->rfd
 | 
			
		||||
				 && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
 | 
			
		||||
				if (!*nves)
 | 
			
		||||
					*nves = list_new();
 | 
			
		||||
				listnode_add(*nves, rfgn->rfg->rfd);
 | 
			
		||||
@ -1718,7 +1714,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
 | 
			
		||||
		   iattr,	/* bgp_update copies this attr */
 | 
			
		||||
		   afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
 | 
			
		||||
		   BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
 | 
			
		||||
		   NULL,     /* tag not used for unicast, EVPN neither */
 | 
			
		||||
		   NULL,	/* tag not used for unicast, EVPN neither */
 | 
			
		||||
		   0, 0, NULL); /* EVPN not used */
 | 
			
		||||
	bgp_attr_unintern(&iattr);
 | 
			
		||||
}
 | 
			
		||||
@ -1734,7 +1730,8 @@ static int vncExportWithdrawTimer(struct thread *t)
 | 
			
		||||
		     NULL,			  /* attr, ignored */
 | 
			
		||||
		     family2afi(eti->node->p.family), SAFI_UNICAST, eti->type,
 | 
			
		||||
		     eti->subtype, NULL, /* RD not used for unicast */
 | 
			
		||||
		     NULL, 0, NULL); /* tag not used for unicast, EVPN neither */
 | 
			
		||||
		     NULL, 0,
 | 
			
		||||
		     NULL); /* tag not used for unicast, EVPN neither */
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Free the eti
 | 
			
		||||
@ -1857,9 +1854,8 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
 | 
			
		||||
 | 
			
		||||
				prefix2str(&rn->p, prefixstr,
 | 
			
		||||
					   sizeof(prefixstr));
 | 
			
		||||
				vnc_zlog_debug_verbose(
 | 
			
		||||
					"%s: checking prefix %s", __func__,
 | 
			
		||||
					prefixstr);
 | 
			
		||||
				vnc_zlog_debug_verbose("%s: checking prefix %s",
 | 
			
		||||
						       __func__, prefixstr);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
@ -1952,20 +1948,20 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
 | 
			
		||||
						"%s: calling bgp_update",
 | 
			
		||||
						__func__);
 | 
			
		||||
 | 
			
		||||
					bgp_update(ri->peer,
 | 
			
		||||
						   &rn->p, /* prefix */
 | 
			
		||||
						   0,      /* addpath_id */
 | 
			
		||||
						   iattr,  /* bgp_update copies
 | 
			
		||||
							      it */
 | 
			
		||||
						   AFI_IP, SAFI_UNICAST,
 | 
			
		||||
						   ZEBRA_ROUTE_VNC_DIRECT_RH,
 | 
			
		||||
						   BGP_ROUTE_REDISTRIBUTE,
 | 
			
		||||
						   NULL,     /* RD not used for
 | 
			
		||||
								unicast */
 | 
			
		||||
						   NULL,     /* tag not used for
 | 
			
		||||
								unicast, EVPN
 | 
			
		||||
								neither */
 | 
			
		||||
						   0, 0, NULL); /* EVPN not used */
 | 
			
		||||
					bgp_update(
 | 
			
		||||
						ri->peer, &rn->p, /* prefix */
 | 
			
		||||
						0,     /* addpath_id */
 | 
			
		||||
						iattr, /* bgp_update copies
 | 
			
		||||
							  it */
 | 
			
		||||
						AFI_IP, SAFI_UNICAST,
 | 
			
		||||
						ZEBRA_ROUTE_VNC_DIRECT_RH,
 | 
			
		||||
						BGP_ROUTE_REDISTRIBUTE, NULL,
 | 
			
		||||
						/* RD not used for unicast */
 | 
			
		||||
						NULL,
 | 
			
		||||
						/* tag not used for unicast,
 | 
			
		||||
						   or EVPN */
 | 
			
		||||
						0, 0, NULL); /* EVPN not used */
 | 
			
		||||
 | 
			
		||||
					bgp_attr_unintern(&iattr);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -2557,7 +2557,7 @@ void vnc_import_bgp_exterior_del_route_interior(
 | 
			
		||||
				if (bi->extra) {
 | 
			
		||||
					prd = &bi->extra->vnc.import.rd;
 | 
			
		||||
					label = decode_label(
 | 
			
		||||
							&bi->extra->label[0]);
 | 
			
		||||
						&bi->extra->label[0]);
 | 
			
		||||
				} else
 | 
			
		||||
					prd = NULL;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							@ -396,6 +396,8 @@ AC_ARG_ENABLE(rpki,
 | 
			
		||||
  AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
 | 
			
		||||
AC_ARG_ENABLE([clippy-only],
 | 
			
		||||
  AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
 | 
			
		||||
AC_ARG_ENABLE([numeric_version],
 | 
			
		||||
  AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
 | 
			
		||||
 | 
			
		||||
AS_IF([test "${enable_clippy_only}" != "yes"], [
 | 
			
		||||
AC_CHECK_HEADERS(json-c/json.h)
 | 
			
		||||
@ -647,6 +649,14 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout
 | 
			
		||||
 | 
			
		||||
AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
 | 
			
		||||
 | 
			
		||||
dnl ------------------------------------
 | 
			
		||||
dnl Alpine only accepts numeric versions
 | 
			
		||||
dnl ------------------------------------
 | 
			
		||||
if test "x${enable_numeric_version}" != "x" ; then
 | 
			
		||||
  VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`"
 | 
			
		||||
  PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
dnl -----------------------------------
 | 
			
		||||
dnl Add extra version string to package
 | 
			
		||||
dnl name, string and version fields.
 | 
			
		||||
@ -1872,6 +1882,7 @@ AC_CONFIG_FILES([Makefile
 | 
			
		||||
	  redhat/frr.spec
 | 
			
		||||
	  debianpkg/Makefile
 | 
			
		||||
	  debianpkg/changelog
 | 
			
		||||
	  alpine/APKBUILD
 | 
			
		||||
	  snapcraft/snapcraft.yaml
 | 
			
		||||
	  lib/version.h
 | 
			
		||||
	  tests/lib/cli/test_cli.refout
 | 
			
		||||
 | 
			
		||||
@ -170,6 +170,12 @@ customize the build to include or exclude specific features and dependencies.
 | 
			
		||||
 | 
			
		||||
   Build with FPM module support.
 | 
			
		||||
 | 
			
		||||
.. option:: --enable-numeric-version
 | 
			
		||||
 | 
			
		||||
   Alpine Linux does not allow non-numeric characters in the version string.
 | 
			
		||||
   With this option, we provide a way to strip out these characters for apk dev
 | 
			
		||||
   package builds.
 | 
			
		||||
 | 
			
		||||
You may specify any combination of the above options to the configure
 | 
			
		||||
script. By default, the executables are placed in :file:`/usr/local/sbin`
 | 
			
		||||
and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/`
 | 
			
		||||
 | 
			
		||||
@ -94,11 +94,7 @@
 | 
			
		||||
#define EIGRP_MULTICAST_ADDRESS            0xe000000A /*224.0.0.10*/
 | 
			
		||||
 | 
			
		||||
#define EIGRP_MAX_METRIC                   0xffffffffU    /*4294967295*/
 | 
			
		||||
enum metric_change {
 | 
			
		||||
	METRIC_DECREASE,
 | 
			
		||||
	METRIC_SAME,
 | 
			
		||||
	METRIC_INCREASE
 | 
			
		||||
};
 | 
			
		||||
enum metric_change { METRIC_DECREASE, METRIC_SAME, METRIC_INCREASE };
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_ROUTE               ZEBRA_ROUTE_MAX
 | 
			
		||||
#define DEFAULT_ROUTE_TYPE(T) ((T) == DEFAULT_ROUTE)
 | 
			
		||||
@ -182,7 +178,7 @@ enum eigrp_fsm_events {
 | 
			
		||||
	 * state not changed
 | 
			
		||||
	 * usually by receiving not last reply
 | 
			
		||||
	 */
 | 
			
		||||
	 EIGRP_FSM_KEEP_STATE,
 | 
			
		||||
	EIGRP_FSM_KEEP_STATE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -216,8 +216,7 @@ void show_ip_eigrp_interface_sub(struct vty *vty, struct eigrp *eigrp,
 | 
			
		||||
	vty_out(vty, "%u %c %-10u", 0, '/',
 | 
			
		||||
		eigrp_neighbor_packet_queue_sum(ei));
 | 
			
		||||
	vty_out(vty, "%-7u %-14u %-12u %-8u", 0, 0, 0, 0);
 | 
			
		||||
	vty_out(vty, "%-8u %-8u \n", ei->params.v_hello,
 | 
			
		||||
		ei->params.v_wait);
 | 
			
		||||
	vty_out(vty, "%-8u %-8u \n", ei->params.v_hello, ei->params.v_wait);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void show_ip_eigrp_interface_detail(struct vty *vty, struct eigrp *eigrp,
 | 
			
		||||
@ -253,7 +252,8 @@ void show_ip_eigrp_neighbor_sub(struct vty *vty, struct eigrp_neighbor *nbr,
 | 
			
		||||
	vty_out(vty, "%-3u %-17s %-21s", 0, eigrp_neigh_ip_string(nbr),
 | 
			
		||||
		eigrp_if_name_string(nbr->ei));
 | 
			
		||||
	if (nbr->t_holddown)
 | 
			
		||||
		vty_out(vty, "%-7lu", thread_timer_remain_second(nbr->t_holddown));
 | 
			
		||||
		vty_out(vty, "%-7lu",
 | 
			
		||||
			thread_timer_remain_second(nbr->t_holddown));
 | 
			
		||||
	else
 | 
			
		||||
		vty_out(vty, "-      ");
 | 
			
		||||
	vty_out(vty, "%-8u %-6u %-5u", 0, 0, EIGRP_PACKET_RETRANS_TIME);
 | 
			
		||||
@ -295,8 +295,7 @@ void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "%s, ",
 | 
			
		||||
		prefix2str(tn->destination, buffer, PREFIX_STRLEN));
 | 
			
		||||
	vty_out(vty, "%u successors, ",
 | 
			
		||||
		(successors) ? successors->count : 0);
 | 
			
		||||
	vty_out(vty, "%u successors, ", (successors) ? successors->count : 0);
 | 
			
		||||
	vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance,
 | 
			
		||||
		tn->serno);
 | 
			
		||||
 | 
			
		||||
@ -305,7 +304,7 @@ void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void show_ip_eigrp_nexthop_entry(struct vty *vty, struct eigrp *eigrp,
 | 
			
		||||
				  struct eigrp_nexthop_entry *te, int *first)
 | 
			
		||||
				 struct eigrp_nexthop_entry *te, int *first)
 | 
			
		||||
{
 | 
			
		||||
	if (te->reported_distance == EIGRP_MAX_METRIC)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
@ -157,7 +157,7 @@ extern void show_ip_eigrp_neighbor_sub(struct vty *, struct eigrp_neighbor *,
 | 
			
		||||
extern void show_ip_eigrp_prefix_entry(struct vty *,
 | 
			
		||||
				       struct eigrp_prefix_entry *);
 | 
			
		||||
extern void show_ip_eigrp_nexthop_entry(struct vty *, struct eigrp *,
 | 
			
		||||
					 struct eigrp_nexthop_entry *, int *);
 | 
			
		||||
					struct eigrp_nexthop_entry *, int *);
 | 
			
		||||
 | 
			
		||||
extern void eigrp_debug_init(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -257,8 +257,8 @@ static const char *change2str(enum metric_change change)
 | 
			
		||||
 * Return number of occurred event (arrow in diagram).
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static enum eigrp_fsm_events eigrp_get_fsm_event(
 | 
			
		||||
	struct eigrp_fsm_action_message *msg)
 | 
			
		||||
static enum eigrp_fsm_events
 | 
			
		||||
eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	// Loading base information from message
 | 
			
		||||
	// struct eigrp *eigrp = msg->eigrp;
 | 
			
		||||
@ -315,8 +315,7 @@ static enum eigrp_fsm_events eigrp_get_fsm_event(
 | 
			
		||||
				return EIGRP_FSM_KEEP_STATE;
 | 
			
		||||
 | 
			
		||||
			zlog_info("All reply received\n");
 | 
			
		||||
			if (head->reported_distance
 | 
			
		||||
			    < prefix->fdistance) {
 | 
			
		||||
			if (head->reported_distance < prefix->fdistance) {
 | 
			
		||||
				return EIGRP_FSM_EVENT_LR_FCS;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -417,13 +416,12 @@ int eigrp_fsm_event(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	enum eigrp_fsm_events event = eigrp_get_fsm_event(msg);
 | 
			
		||||
 | 
			
		||||
	zlog_info("EIGRP AS: %d State: %s Event: %s Network: %s Packet Type: %s Reply RIJ Count: %d change: %s",
 | 
			
		||||
		  msg->eigrp->AS, prefix_state2str(msg->prefix->state),
 | 
			
		||||
		  fsm_state2str(event),
 | 
			
		||||
		  eigrp_topology_ip_string(msg->prefix),
 | 
			
		||||
		  packet_type2str(msg->packet_type),
 | 
			
		||||
		  msg->prefix->rij->count,
 | 
			
		||||
		  change2str(msg->change));
 | 
			
		||||
	zlog_info(
 | 
			
		||||
		"EIGRP AS: %d State: %s Event: %s Network: %s Packet Type: %s Reply RIJ Count: %d change: %s",
 | 
			
		||||
		msg->eigrp->AS, prefix_state2str(msg->prefix->state),
 | 
			
		||||
		fsm_state2str(event), eigrp_topology_ip_string(msg->prefix),
 | 
			
		||||
		packet_type2str(msg->packet_type), msg->prefix->rij->count,
 | 
			
		||||
		change2str(msg->change));
 | 
			
		||||
	(*(NSM[msg->prefix->state][event].func))(msg);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@ -444,8 +442,7 @@ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
 | 
			
		||||
	ne = listnode_head(successors);
 | 
			
		||||
	prefix->state = EIGRP_FSM_STATE_ACTIVE_1;
 | 
			
		||||
	prefix->rdistance = prefix->distance = prefix->fdistance =
 | 
			
		||||
		ne->distance;
 | 
			
		||||
	prefix->rdistance = prefix->distance = prefix->fdistance = ne->distance;
 | 
			
		||||
	prefix->reported_metric = ne->total_metric;
 | 
			
		||||
 | 
			
		||||
	if (eigrp_nbr_count_get()) {
 | 
			
		||||
@ -472,8 +469,7 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
 | 
			
		||||
	ne = listnode_head(successors);
 | 
			
		||||
	prefix->state = EIGRP_FSM_STATE_ACTIVE_3;
 | 
			
		||||
	prefix->rdistance = prefix->distance = prefix->fdistance =
 | 
			
		||||
		ne->distance;
 | 
			
		||||
	prefix->rdistance = prefix->distance = prefix->fdistance = ne->distance;
 | 
			
		||||
	prefix->reported_metric = ne->total_metric;
 | 
			
		||||
	if (eigrp_nbr_count_get()) {
 | 
			
		||||
		prefix->req_action |= EIGRP_FSM_NEED_QUERY;
 | 
			
		||||
@ -498,8 +494,7 @@ int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
					   ne->total_metric)) {
 | 
			
		||||
			prefix->rdistance = prefix->fdistance =
 | 
			
		||||
				prefix->distance = ne->distance;
 | 
			
		||||
			prefix->reported_metric =
 | 
			
		||||
				ne->total_metric;
 | 
			
		||||
			prefix->reported_metric = ne->total_metric;
 | 
			
		||||
			if (msg->packet_type == EIGRP_OPC_QUERY)
 | 
			
		||||
				eigrp_send_reply(msg->adv_router, prefix);
 | 
			
		||||
			prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
 | 
			
		||||
@ -523,8 +518,7 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
	struct eigrp_prefix_entry *prefix = msg->prefix;
 | 
			
		||||
	struct eigrp_nexthop_entry *ne = listnode_head(prefix->entries);
 | 
			
		||||
 | 
			
		||||
	prefix->fdistance = prefix->distance = prefix->rdistance =
 | 
			
		||||
		ne->distance;
 | 
			
		||||
	prefix->fdistance = prefix->distance = prefix->rdistance = ne->distance;
 | 
			
		||||
	prefix->reported_metric = ne->total_metric;
 | 
			
		||||
 | 
			
		||||
	if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) {
 | 
			
		||||
@ -533,8 +527,7 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
		assert(successors); // It's like Napolean and Waterloo
 | 
			
		||||
 | 
			
		||||
		ne = listnode_head(successors);
 | 
			
		||||
		eigrp_send_reply(ne->adv_router,
 | 
			
		||||
				 prefix);
 | 
			
		||||
		eigrp_send_reply(ne->adv_router, prefix);
 | 
			
		||||
		list_delete_and_null(&successors);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -587,8 +580,7 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
		assert(successors); // Having a spoon and all you need is a
 | 
			
		||||
				    // knife
 | 
			
		||||
		ne = listnode_head(successors);
 | 
			
		||||
		eigrp_send_reply(ne->adv_router,
 | 
			
		||||
				 prefix);
 | 
			
		||||
		eigrp_send_reply(ne->adv_router, prefix);
 | 
			
		||||
 | 
			
		||||
		list_delete_and_null(&successors);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -96,8 +96,8 @@ int eigrp_hello_timer(struct thread *thread)
 | 
			
		||||
 | 
			
		||||
	/* Hello timer set. */
 | 
			
		||||
	ei->t_hello = NULL;
 | 
			
		||||
	thread_add_timer(master, eigrp_hello_timer, ei,
 | 
			
		||||
			 ei->params.v_hello, &ei->t_hello);
 | 
			
		||||
	thread_add_timer(master, eigrp_hello_timer, ei, ei->params.v_hello,
 | 
			
		||||
			 &ei->t_hello);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -443,7 +443,7 @@ static u_int16_t eigrp_sw_version_encode(struct stream *s)
 | 
			
		||||
	stream_putw(s, EIGRP_TLV_SW_VERSION);
 | 
			
		||||
	stream_putw(s, length);
 | 
			
		||||
 | 
			
		||||
	stream_putc(s, FRR_MAJOR);  //!< major os version
 | 
			
		||||
	stream_putc(s, FRR_MAJOR); //!< major os version
 | 
			
		||||
	stream_putc(s, FRR_MINOR); //!< minor os version
 | 
			
		||||
 | 
			
		||||
	/* and the core eigrp version */
 | 
			
		||||
@ -634,14 +634,14 @@ static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei,
 | 
			
		||||
 | 
			
		||||
	if (ep) {
 | 
			
		||||
		// encode common header feilds
 | 
			
		||||
		eigrp_packet_header_init(EIGRP_OPC_HELLO, ei->eigrp, ep->s, 0, 0, ack);
 | 
			
		||||
		eigrp_packet_header_init(EIGRP_OPC_HELLO, ei->eigrp, ep->s, 0,
 | 
			
		||||
					 0, ack);
 | 
			
		||||
 | 
			
		||||
		// encode Authentication TLV
 | 
			
		||||
		if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
		    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
			length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
 | 
			
		||||
		} else if ((ei->params.auth_type
 | 
			
		||||
			    == EIGRP_AUTH_TYPE_SHA256)
 | 
			
		||||
		} else if ((ei->params.auth_type == EIGRP_AUTH_TYPE_SHA256)
 | 
			
		||||
			   && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
			length += eigrp_add_authTLV_SHA256_to_stream(ep->s, ei);
 | 
			
		||||
		}
 | 
			
		||||
@ -680,8 +680,7 @@ static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei,
 | 
			
		||||
		    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
			eigrp_make_md5_digest(ei, ep->s,
 | 
			
		||||
					      EIGRP_AUTH_BASIC_HELLO_FLAG);
 | 
			
		||||
		} else if ((ei->params.auth_type
 | 
			
		||||
			    == EIGRP_AUTH_TYPE_SHA256)
 | 
			
		||||
		} else if ((ei->params.auth_type == EIGRP_AUTH_TYPE_SHA256)
 | 
			
		||||
			   && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
			eigrp_make_sha256_digest(ei, ep->s,
 | 
			
		||||
						 EIGRP_AUTH_BASIC_HELLO_FLAG);
 | 
			
		||||
 | 
			
		||||
@ -125,12 +125,11 @@ struct list *eigrp_iflist;
 | 
			
		||||
void eigrp_if_init()
 | 
			
		||||
{
 | 
			
		||||
	/* Initialize Zebra interface data structure. */
 | 
			
		||||
	//hook_register_prio(if_add, 0, eigrp_if_new);
 | 
			
		||||
	// hook_register_prio(if_add, 0, eigrp_if_new);
 | 
			
		||||
	hook_register_prio(if_del, 0, eigrp_if_delete_hook);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void eigrp_del_if_params(struct eigrp_if_params *eip)
 | 
			
		||||
{
 | 
			
		||||
	if (eip->auth_keychain)
 | 
			
		||||
@ -160,8 +159,7 @@ int eigrp_if_up(struct eigrp_interface *ei)
 | 
			
		||||
	thread_add_event(master, eigrp_hello_timer, ei, (1), NULL);
 | 
			
		||||
 | 
			
		||||
	/*Prepare metrics*/
 | 
			
		||||
	metric.bandwidth =
 | 
			
		||||
		eigrp_bandwidth_to_scaled(ei->params.bandwidth);
 | 
			
		||||
	metric.bandwidth = eigrp_bandwidth_to_scaled(ei->params.bandwidth);
 | 
			
		||||
	metric.delay = eigrp_delay_to_scaled(ei->params.delay);
 | 
			
		||||
	metric.load = ei->params.load;
 | 
			
		||||
	metric.reliability = ei->params.reliability;
 | 
			
		||||
@ -310,8 +308,7 @@ void eigrp_if_set_multicast(struct eigrp_interface *ei)
 | 
			
		||||
		 * group. */
 | 
			
		||||
		if (ei->member_allrouters) {
 | 
			
		||||
			/* Only actually drop if this is the last reference */
 | 
			
		||||
			eigrp_if_drop_allspfrouters(ei->eigrp,
 | 
			
		||||
						    ei->address,
 | 
			
		||||
			eigrp_if_drop_allspfrouters(ei->eigrp, ei->address,
 | 
			
		||||
						    ei->ifp->ifindex);
 | 
			
		||||
			/* Unset the flag regardless of whether the system call
 | 
			
		||||
			   to leave
 | 
			
		||||
@ -333,8 +330,7 @@ u_char eigrp_default_iftype(struct interface *ifp)
 | 
			
		||||
		return EIGRP_IFTYPE_BROADCAST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eigrp_if_free(struct eigrp_interface *ei,
 | 
			
		||||
		   int source)
 | 
			
		||||
void eigrp_if_free(struct eigrp_interface *ei, int source)
 | 
			
		||||
{
 | 
			
		||||
	struct prefix dest_addr;
 | 
			
		||||
	struct eigrp_prefix_entry *pe;
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,6 @@
 | 
			
		||||
#ifndef _ZEBRA_EIGRP_MACROS_H_
 | 
			
		||||
#define _ZEBRA_EIGRP_MACROS_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#define EIGRP_IF_STRING_MAXLEN  40
 | 
			
		||||
 | 
			
		||||
@ -358,7 +358,8 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
 | 
			
		||||
	eigrp_nbr_delete(nbr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry *ne, struct eigrp_interface *ei)
 | 
			
		||||
int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry *ne,
 | 
			
		||||
				  struct eigrp_interface *ei)
 | 
			
		||||
{
 | 
			
		||||
	if (ne->distance == EIGRP_MAX_METRIC)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@ -280,8 +280,7 @@ static void eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p,
 | 
			
		||||
		if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (p->family == co->address->family
 | 
			
		||||
		    && !ifp->info
 | 
			
		||||
		if (p->family == co->address->family && !ifp->info
 | 
			
		||||
		    && eigrp_network_match_iface(co, p)) {
 | 
			
		||||
 | 
			
		||||
			ei = eigrp_if_new(eigrp, ifp, co->address);
 | 
			
		||||
@ -408,17 +407,17 @@ u_int32_t eigrp_calculate_total_metrics(struct eigrp *eigrp,
 | 
			
		||||
	struct eigrp_interface *ei = entry->ei;
 | 
			
		||||
 | 
			
		||||
	entry->total_metric = entry->reported_metric;
 | 
			
		||||
	uint64_t temp_delay = (uint64_t)entry->total_metric.delay
 | 
			
		||||
			      + (uint64_t)eigrp_delay_to_scaled(ei->params.delay);
 | 
			
		||||
	uint64_t temp_delay =
 | 
			
		||||
		(uint64_t)entry->total_metric.delay
 | 
			
		||||
		+ (uint64_t)eigrp_delay_to_scaled(ei->params.delay);
 | 
			
		||||
	entry->total_metric.delay = temp_delay > EIGRP_MAX_METRIC
 | 
			
		||||
					    ? EIGRP_MAX_METRIC
 | 
			
		||||
					    : (u_int32_t)temp_delay;
 | 
			
		||||
 | 
			
		||||
	u_int32_t bw =
 | 
			
		||||
		eigrp_bandwidth_to_scaled(ei->params.bandwidth);
 | 
			
		||||
	u_int32_t bw = eigrp_bandwidth_to_scaled(ei->params.bandwidth);
 | 
			
		||||
	entry->total_metric.bandwidth = entry->total_metric.bandwidth > bw
 | 
			
		||||
					       ? bw
 | 
			
		||||
					       : entry->total_metric.bandwidth;
 | 
			
		||||
						? bw
 | 
			
		||||
						: entry->total_metric.bandwidth;
 | 
			
		||||
 | 
			
		||||
	return eigrp_calculate_metrics(eigrp, entry->total_metric);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -194,8 +194,9 @@ int eigrp_check_md5_digest(struct stream *s,
 | 
			
		||||
		key = key_lookup_for_send(keychain);
 | 
			
		||||
 | 
			
		||||
	if (!key) {
 | 
			
		||||
		zlog_warn("Interface %s: Expected key value not found in config",
 | 
			
		||||
			  nbr->ei->ifp->name);
 | 
			
		||||
		zlog_warn(
 | 
			
		||||
			"Interface %s: Expected key value not found in config",
 | 
			
		||||
			nbr->ei->ifp->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -270,8 +271,9 @@ int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
 | 
			
		||||
		key = key_lookup_for_send(keychain);
 | 
			
		||||
 | 
			
		||||
	if (!key) {
 | 
			
		||||
		zlog_warn("Interface %s: Expected key value not found in config",
 | 
			
		||||
			  ei->ifp->name);
 | 
			
		||||
		zlog_warn(
 | 
			
		||||
			"Interface %s: Expected key value not found in config",
 | 
			
		||||
			ei->ifp->name);
 | 
			
		||||
		eigrp_authTLV_SHA256_free(auth_TLV);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@ -325,8 +327,6 @@ int eigrp_write(struct thread *thread)
 | 
			
		||||
#ifdef WANT_EIGRP_WRITE_FRAGMENT
 | 
			
		||||
	static u_int16_t ipid = 0;
 | 
			
		||||
#endif /* WANT_EIGRP_WRITE_FRAGMENT */
 | 
			
		||||
       /* $FRR indent$ */
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
#define EIGRP_WRITE_IPHL_SHIFT 2
 | 
			
		||||
 | 
			
		||||
	eigrp->t_write = NULL;
 | 
			
		||||
@ -350,8 +350,7 @@ int eigrp_write(struct thread *thread)
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	if (ep->length < EIGRP_HEADER_LEN) {
 | 
			
		||||
		zlog_err("%s: Packet just has a header?",
 | 
			
		||||
			 __PRETTY_FUNCTION__);
 | 
			
		||||
		zlog_err("%s: Packet just has a header?", __PRETTY_FUNCTION__);
 | 
			
		||||
		eigrp_header_dump((struct eigrp_header *)ep->s->data);
 | 
			
		||||
		eigrp_packet_delete(ei);
 | 
			
		||||
		goto out;
 | 
			
		||||
@ -435,10 +434,10 @@ int eigrp_write(struct thread *thread)
 | 
			
		||||
 | 
			
		||||
	if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) {
 | 
			
		||||
		eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
 | 
			
		||||
		zlog_debug("Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
 | 
			
		||||
			   lookup_msg(eigrp_packet_type_str, eigrph->opcode, NULL),
 | 
			
		||||
			   seqno, ack,
 | 
			
		||||
			   inet_ntoa(ep->dst), IF_NAME(ei), ret);
 | 
			
		||||
		zlog_debug(
 | 
			
		||||
			"Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
 | 
			
		||||
			lookup_msg(eigrp_packet_type_str, eigrph->opcode, NULL),
 | 
			
		||||
			seqno, ack, inet_ntoa(ep->dst), IF_NAME(ei), ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
@ -615,10 +614,11 @@ int eigrp_read(struct thread *thread)
 | 
			
		||||
 | 
			
		||||
		strlcpy(src, inet_ntoa(iph->ip_src), sizeof(src));
 | 
			
		||||
		strlcpy(dst, inet_ntoa(iph->ip_dst), sizeof(dst));
 | 
			
		||||
		zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
 | 
			
		||||
			   lookup_msg(eigrp_packet_type_str, opcode, NULL),
 | 
			
		||||
			   ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
 | 
			
		||||
			   IF_NAME(ei), src, dst);
 | 
			
		||||
		zlog_debug(
 | 
			
		||||
			"Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
 | 
			
		||||
			lookup_msg(eigrp_packet_type_str, opcode, NULL),
 | 
			
		||||
			ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
 | 
			
		||||
			IF_NAME(ei), src, dst);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Read rest of the packet and call each sort of packet routine. */
 | 
			
		||||
@ -639,7 +639,8 @@ int eigrp_read(struct thread *thread)
 | 
			
		||||
			eigrp_packet_free(ep);
 | 
			
		||||
 | 
			
		||||
			if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
 | 
			
		||||
			    && (ntohl(eigrph->ack) == nbr->init_sequence_number)) {
 | 
			
		||||
			    && (ntohl(eigrph->ack)
 | 
			
		||||
				== nbr->init_sequence_number)) {
 | 
			
		||||
				eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
 | 
			
		||||
				zlog_info("Neighbor(%s) adjacency became full",
 | 
			
		||||
					  inet_ntoa(nbr->src));
 | 
			
		||||
@ -647,8 +648,7 @@ int eigrp_read(struct thread *thread)
 | 
			
		||||
				nbr->recv_sequence_number =
 | 
			
		||||
					ntohl(eigrph->sequence);
 | 
			
		||||
				eigrp_update_send_EOT(nbr);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			} else
 | 
			
		||||
				eigrp_send_packet_reliably(nbr);
 | 
			
		||||
		}
 | 
			
		||||
		ep = eigrp_fifo_next(nbr->multicast_queue);
 | 
			
		||||
@ -875,9 +875,9 @@ void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Make EIGRP header. */
 | 
			
		||||
void eigrp_packet_header_init(int type, struct eigrp *eigrp,
 | 
			
		||||
			      struct stream *s, u_int32_t flags,
 | 
			
		||||
			      u_int32_t sequence, u_int32_t ack)
 | 
			
		||||
void eigrp_packet_header_init(int type, struct eigrp *eigrp, struct stream *s,
 | 
			
		||||
			      u_int32_t flags, u_int32_t sequence,
 | 
			
		||||
			      u_int32_t ack)
 | 
			
		||||
{
 | 
			
		||||
	struct eigrp_header *eigrph;
 | 
			
		||||
 | 
			
		||||
@ -1234,8 +1234,7 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
 | 
			
		||||
 | 
			
		||||
	stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
 | 
			
		||||
	if (pe->destination->prefixlen > 8)
 | 
			
		||||
		stream_putc(s,
 | 
			
		||||
			    (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
 | 
			
		||||
		stream_putc(s, (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
 | 
			
		||||
	if (pe->destination->prefixlen > 16)
 | 
			
		||||
		stream_putc(s,
 | 
			
		||||
			    (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
 | 
			
		||||
 | 
			
		||||
@ -41,9 +41,8 @@ extern struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *,
 | 
			
		||||
						   struct eigrp_neighbor *);
 | 
			
		||||
extern void eigrp_packet_free(struct eigrp_packet *);
 | 
			
		||||
extern void eigrp_packet_delete(struct eigrp_interface *);
 | 
			
		||||
extern void eigrp_packet_header_init(int, struct eigrp *,
 | 
			
		||||
				     struct stream *, u_int32_t, u_int32_t,
 | 
			
		||||
				     u_int32_t);
 | 
			
		||||
extern void eigrp_packet_header_init(int, struct eigrp *, struct stream *,
 | 
			
		||||
				     u_int32_t, u_int32_t, u_int32_t);
 | 
			
		||||
extern void eigrp_packet_checksum(struct eigrp_interface *, struct stream *,
 | 
			
		||||
				  u_int16_t);
 | 
			
		||||
 | 
			
		||||
@ -84,8 +83,7 @@ extern int eigrp_hello_timer(struct thread *);
 | 
			
		||||
 * These externs are found in eigrp_update.c
 | 
			
		||||
 */
 | 
			
		||||
extern bool eigrp_update_prefix_apply(struct eigrp *eigrp,
 | 
			
		||||
				      struct eigrp_interface *ei,
 | 
			
		||||
				      int in,
 | 
			
		||||
				      struct eigrp_interface *ei, int in,
 | 
			
		||||
				      struct prefix *prefix);
 | 
			
		||||
extern void eigrp_update_send(struct eigrp_interface *);
 | 
			
		||||
extern void eigrp_update_receive(struct eigrp *, struct ip *,
 | 
			
		||||
 | 
			
		||||
@ -142,13 +142,13 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case EIGRP_TLV_IPv4_EXT:
 | 
			
		||||
			/* DVS: processing of external routes needs packet and fsm work.
 | 
			
		||||
			 *      for now, lets just not creash the box
 | 
			
		||||
			 */
 | 
			
		||||
		/* DVS: processing of external routes needs packet and fsm work.
 | 
			
		||||
		 *      for now, lets just not creash the box
 | 
			
		||||
		 */
 | 
			
		||||
		default:
 | 
			
		||||
			length = stream_getw(s);
 | 
			
		||||
			// -2 for type, -2 for len
 | 
			
		||||
			for (length-=4; length ; length--) {
 | 
			
		||||
			for (length -= 4; length; length--) {
 | 
			
		||||
				(void)stream_getc(s);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -177,16 +177,15 @@ void eigrp_send_query(struct eigrp_interface *ei)
 | 
			
		||||
			ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 | 
			
		||||
 | 
			
		||||
			/* Prepare EIGRP INIT UPDATE header */
 | 
			
		||||
			eigrp_packet_header_init(EIGRP_OPC_QUERY,
 | 
			
		||||
						 ei->eigrp, ep->s, 0,
 | 
			
		||||
			eigrp_packet_header_init(EIGRP_OPC_QUERY, ei->eigrp,
 | 
			
		||||
						 ep->s, 0,
 | 
			
		||||
						 ei->eigrp->sequence_number, 0);
 | 
			
		||||
 | 
			
		||||
			// encode Authentication TLV, if needed
 | 
			
		||||
			if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
			    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
				length +=
 | 
			
		||||
					eigrp_add_authTLV_MD5_to_stream(ep->s,
 | 
			
		||||
									ei);
 | 
			
		||||
				length += eigrp_add_authTLV_MD5_to_stream(ep->s,
 | 
			
		||||
									  ei);
 | 
			
		||||
			}
 | 
			
		||||
			new_packet = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -75,12 +75,10 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
 | 
			
		||||
		      sizeof(struct eigrp_prefix_entry));
 | 
			
		||||
	memcpy(pe2, pe, sizeof(struct eigrp_prefix_entry));
 | 
			
		||||
 | 
			
		||||
	if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
				      EIGRP_FILTER_OUT,
 | 
			
		||||
	if (eigrp_update_prefix_apply(eigrp, ei, EIGRP_FILTER_OUT,
 | 
			
		||||
				      pe2->destination)) {
 | 
			
		||||
		zlog_info("REPLY SEND: Setting Metric to max");
 | 
			
		||||
		pe2->reported_metric.delay = EIGRP_MAX_METRIC;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@ -163,17 +161,18 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
		dest_addr.u.prefix4 = tlv->destination;
 | 
			
		||||
		dest_addr.prefixlen = tlv->prefix_length;
 | 
			
		||||
		struct eigrp_prefix_entry *dest =
 | 
			
		||||
			eigrp_topology_table_lookup_ipv4(
 | 
			
		||||
				eigrp->topology_table, &dest_addr);
 | 
			
		||||
			eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
 | 
			
		||||
							 &dest_addr);
 | 
			
		||||
		/*
 | 
			
		||||
		 * Destination must exists
 | 
			
		||||
		 */
 | 
			
		||||
		if (!dest) {
 | 
			
		||||
			char buf[PREFIX_STRLEN];
 | 
			
		||||
 | 
			
		||||
			zlog_err("%s: Received prefix %s which we do not know about",
 | 
			
		||||
				 __PRETTY_FUNCTION__,
 | 
			
		||||
				 prefix2str(&dest_addr, buf, sizeof(buf)));
 | 
			
		||||
			zlog_err(
 | 
			
		||||
				"%s: Received prefix %s which we do not know about",
 | 
			
		||||
				__PRETTY_FUNCTION__,
 | 
			
		||||
				prefix2str(&dest_addr, buf, sizeof(buf)));
 | 
			
		||||
			eigrp_IPv4_InternalTLV_free(tlv);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@ -182,8 +181,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
		struct eigrp_nexthop_entry *entry =
 | 
			
		||||
			eigrp_prefix_entry_lookup(dest->entries, nbr);
 | 
			
		||||
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
					      EIGRP_FILTER_IN,
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei, EIGRP_FILTER_IN,
 | 
			
		||||
					      &dest_addr)) {
 | 
			
		||||
			tlv->metric.delay = EIGRP_MAX_METRIC;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,7 @@
 | 
			
		||||
#include "if_rmap.h"
 | 
			
		||||
 | 
			
		||||
extern bool eigrp_routemap_prefix_apply(struct eigrp *eigrp,
 | 
			
		||||
					struct eigrp_interface *ei,
 | 
			
		||||
					int in,
 | 
			
		||||
					struct eigrp_interface *ei, int in,
 | 
			
		||||
					struct prefix *prefix);
 | 
			
		||||
extern void eigrp_route_map_update(const char *);
 | 
			
		||||
extern void eigrp_route_map_init();
 | 
			
		||||
 | 
			
		||||
@ -104,9 +104,8 @@ struct eigrp {
 | 
			
		||||
 | 
			
		||||
	uint64_t serno; /* Global serial number counter for topology entry
 | 
			
		||||
			   changes*/
 | 
			
		||||
	uint64_t
 | 
			
		||||
		serno_last_update; /* Highest serial number of information send
 | 
			
		||||
				      by last update*/
 | 
			
		||||
	uint64_t serno_last_update; /* Highest serial number of information send
 | 
			
		||||
				       by last update*/
 | 
			
		||||
	struct list *topology_changes_internalIPV4;
 | 
			
		||||
	struct list *topology_changes_externalIPV4;
 | 
			
		||||
 | 
			
		||||
@ -140,14 +139,14 @@ struct eigrp_if_params {
 | 
			
		||||
	u_char passive_interface;
 | 
			
		||||
	u_int32_t v_hello;
 | 
			
		||||
	u_int16_t v_wait;
 | 
			
		||||
	u_char type;      /* type of interface */
 | 
			
		||||
	u_char type; /* type of interface */
 | 
			
		||||
	u_int32_t bandwidth;
 | 
			
		||||
	u_int32_t delay;
 | 
			
		||||
	u_char reliability;
 | 
			
		||||
	u_char load;
 | 
			
		||||
 | 
			
		||||
	char *auth_keychain; /* Associated keychain with interface*/
 | 
			
		||||
	int auth_type; /* EIGRP authentication type */
 | 
			
		||||
	int auth_type;       /* EIGRP authentication type */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum { MEMBER_ALLROUTERS = 0,
 | 
			
		||||
@ -160,7 +159,7 @@ struct eigrp_interface {
 | 
			
		||||
 | 
			
		||||
	/*multicast group refcnts */
 | 
			
		||||
	bool member_allrouters;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	/* This interface's parent eigrp instance. */
 | 
			
		||||
	struct eigrp *eigrp;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@
 | 
			
		||||
#include "eigrpd/eigrp_memory.h"
 | 
			
		||||
 | 
			
		||||
static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *,
 | 
			
		||||
				    struct eigrp_nexthop_entry *);
 | 
			
		||||
				   struct eigrp_nexthop_entry *);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns linkedlist used as topology table
 | 
			
		||||
@ -87,7 +87,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
 | 
			
		||||
 * Topology entry comparison
 | 
			
		||||
 */
 | 
			
		||||
static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *entry1,
 | 
			
		||||
				    struct eigrp_nexthop_entry *entry2)
 | 
			
		||||
				   struct eigrp_nexthop_entry *entry2)
 | 
			
		||||
{
 | 
			
		||||
	if (entry1->distance < entry2->distance)
 | 
			
		||||
		return -1;
 | 
			
		||||
@ -142,10 +142,10 @@ void eigrp_prefix_entry_add(struct route_table *topology,
 | 
			
		||||
		if (IS_DEBUG_EIGRP_EVENT) {
 | 
			
		||||
			char buf[PREFIX_STRLEN];
 | 
			
		||||
 | 
			
		||||
			zlog_debug("%s: %s Should we have found this entry in the topo table?",
 | 
			
		||||
				   __PRETTY_FUNCTION__,
 | 
			
		||||
				   prefix2str(pe->destination, buf,
 | 
			
		||||
					      sizeof(buf)));
 | 
			
		||||
			zlog_debug(
 | 
			
		||||
				"%s: %s Should we have found this entry in the topo table?",
 | 
			
		||||
				__PRETTY_FUNCTION__,
 | 
			
		||||
				prefix2str(pe->destination, buf, sizeof(buf)));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -157,7 +157,7 @@ void eigrp_prefix_entry_add(struct route_table *topology,
 | 
			
		||||
 * Adding topology entry to topology node
 | 
			
		||||
 */
 | 
			
		||||
void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *node,
 | 
			
		||||
			      struct eigrp_nexthop_entry *entry)
 | 
			
		||||
			     struct eigrp_nexthop_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	struct list *l = list_new();
 | 
			
		||||
 | 
			
		||||
@ -197,8 +197,8 @@ void eigrp_prefix_entry_delete(struct route_table *table,
 | 
			
		||||
	eigrp_zebra_route_delete(pe->destination);
 | 
			
		||||
 | 
			
		||||
	rn->info = NULL;
 | 
			
		||||
	route_unlock_node(rn);  //Lookup above
 | 
			
		||||
	route_unlock_node(rn);  //Initial creation
 | 
			
		||||
	route_unlock_node(rn); // Lookup above
 | 
			
		||||
	route_unlock_node(rn); // Initial creation
 | 
			
		||||
	XFREE(MTYPE_EIGRP_PREFIX_ENTRY, pe);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -206,7 +206,7 @@ void eigrp_prefix_entry_delete(struct route_table *table,
 | 
			
		||||
 * Deleting topology entry from topology node
 | 
			
		||||
 */
 | 
			
		||||
void eigrp_nexthop_entry_delete(struct eigrp_prefix_entry *node,
 | 
			
		||||
				 struct eigrp_nexthop_entry *entry)
 | 
			
		||||
				struct eigrp_nexthop_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	if (listnode_lookup(node->entries, entry) != NULL) {
 | 
			
		||||
		listnode_delete(node->entries, entry);
 | 
			
		||||
@ -355,7 +355,8 @@ struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp,
 | 
			
		||||
	return prefixes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
enum metric_change
 | 
			
		||||
eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct eigrp *eigrp = msg->eigrp;
 | 
			
		||||
	struct eigrp_prefix_entry *prefix = msg->prefix;
 | 
			
		||||
@ -365,7 +366,7 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag
 | 
			
		||||
 | 
			
		||||
	assert(entry);
 | 
			
		||||
 | 
			
		||||
	switch(msg->data_type) {
 | 
			
		||||
	switch (msg->data_type) {
 | 
			
		||||
	case EIGRP_CONNECTED:
 | 
			
		||||
		if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED)
 | 
			
		||||
			return change;
 | 
			
		||||
@ -382,8 +383,8 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag
 | 
			
		||||
			return change; // No change
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		new_reported_distance = eigrp_calculate_metrics(eigrp,
 | 
			
		||||
								msg->metrics);
 | 
			
		||||
		new_reported_distance =
 | 
			
		||||
			eigrp_calculate_metrics(eigrp, msg->metrics);
 | 
			
		||||
 | 
			
		||||
		if (entry->reported_distance < new_reported_distance) {
 | 
			
		||||
			change = METRIC_INCREASE;
 | 
			
		||||
@ -410,7 +411,7 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag
 | 
			
		||||
		zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 distance_done:
 | 
			
		||||
distance_done:
 | 
			
		||||
	/*
 | 
			
		||||
	 * Move to correct position in list according to new distance
 | 
			
		||||
	 */
 | 
			
		||||
@ -469,8 +470,7 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
 | 
			
		||||
	struct eigrp_nexthop_entry *entry;
 | 
			
		||||
 | 
			
		||||
	if (successors) {
 | 
			
		||||
		eigrp_zebra_route_add(prefix->destination,
 | 
			
		||||
				      successors);
 | 
			
		||||
		eigrp_zebra_route_add(prefix->destination, successors);
 | 
			
		||||
		for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
 | 
			
		||||
			entry->flags |= EIGRP_NEXTHOP_ENTRY_INTABLE_FLAG;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,16 +42,15 @@ extern void eigrp_topology_cleanup(struct route_table *table);
 | 
			
		||||
extern void eigrp_prefix_entry_add(struct route_table *table,
 | 
			
		||||
				   struct eigrp_prefix_entry *pe);
 | 
			
		||||
extern void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *,
 | 
			
		||||
				     struct eigrp_nexthop_entry *);
 | 
			
		||||
				    struct eigrp_nexthop_entry *);
 | 
			
		||||
extern void eigrp_prefix_entry_delete(struct route_table *table,
 | 
			
		||||
				      struct eigrp_prefix_entry *pe);
 | 
			
		||||
extern void eigrp_nexthop_entry_delete(struct eigrp_prefix_entry *,
 | 
			
		||||
					struct eigrp_nexthop_entry *);
 | 
			
		||||
				       struct eigrp_nexthop_entry *);
 | 
			
		||||
extern void eigrp_topology_delete_all(struct route_table *table);
 | 
			
		||||
extern unsigned int eigrp_topology_table_isempty(struct list *);
 | 
			
		||||
extern struct eigrp_prefix_entry *
 | 
			
		||||
eigrp_topology_table_lookup_ipv4(struct route_table *table,
 | 
			
		||||
				 struct prefix *p);
 | 
			
		||||
eigrp_topology_table_lookup_ipv4(struct route_table *table, struct prefix *p);
 | 
			
		||||
extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *);
 | 
			
		||||
extern struct list *
 | 
			
		||||
eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe,
 | 
			
		||||
@ -62,7 +61,8 @@ extern struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *,
 | 
			
		||||
						   struct eigrp_neighbor *);
 | 
			
		||||
extern void eigrp_topology_update_all_node_flags(struct eigrp *);
 | 
			
		||||
extern void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *);
 | 
			
		||||
extern enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_message *);
 | 
			
		||||
extern enum metric_change
 | 
			
		||||
eigrp_topology_update_distance(struct eigrp_fsm_action_message *);
 | 
			
		||||
extern void eigrp_update_routing_table(struct eigrp_prefix_entry *);
 | 
			
		||||
extern void eigrp_topology_neighbor_down(struct eigrp *,
 | 
			
		||||
					 struct eigrp_neighbor *);
 | 
			
		||||
 | 
			
		||||
@ -63,8 +63,7 @@
 | 
			
		||||
#include "eigrpd/eigrp_network.h"
 | 
			
		||||
#include "eigrpd/eigrp_memory.h"
 | 
			
		||||
 | 
			
		||||
bool eigrp_update_prefix_apply(struct eigrp *eigrp,
 | 
			
		||||
			       struct eigrp_interface *ei,
 | 
			
		||||
bool eigrp_update_prefix_apply(struct eigrp *eigrp, struct eigrp_interface *ei,
 | 
			
		||||
			       int in, struct prefix *prefix)
 | 
			
		||||
{
 | 
			
		||||
	struct access_list *alist;
 | 
			
		||||
@ -143,9 +142,9 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp,
 | 
			
		||||
	/* iterate over all prefixes which weren't advertised by neighbor */
 | 
			
		||||
	for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) {
 | 
			
		||||
		char buffer[PREFIX_STRLEN];
 | 
			
		||||
		zlog_debug("GR receive: Neighbor not advertised %s",
 | 
			
		||||
			   prefix2str(prefix->destination,
 | 
			
		||||
				      buffer, PREFIX_STRLEN));
 | 
			
		||||
		zlog_debug(
 | 
			
		||||
			"GR receive: Neighbor not advertised %s",
 | 
			
		||||
			prefix2str(prefix->destination, buffer, PREFIX_STRLEN));
 | 
			
		||||
 | 
			
		||||
		fsm_msg.metrics = prefix->reported_metric;
 | 
			
		||||
		/* set delay to MAX */
 | 
			
		||||
@ -335,9 +334,9 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
				/*Here comes topology information save*/
 | 
			
		||||
				pe = eigrp_prefix_entry_new();
 | 
			
		||||
				pe->serno = eigrp->serno;
 | 
			
		||||
				pe->destination = (struct prefix *)prefix_ipv4_new();
 | 
			
		||||
				prefix_copy(pe->destination,
 | 
			
		||||
					    &dest_addr);
 | 
			
		||||
				pe->destination =
 | 
			
		||||
					(struct prefix *)prefix_ipv4_new();
 | 
			
		||||
				prefix_copy(pe->destination, &dest_addr);
 | 
			
		||||
				pe->af = AF_INET;
 | 
			
		||||
				pe->state = EIGRP_FSM_STATE_PASSIVE;
 | 
			
		||||
				pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
 | 
			
		||||
@ -354,7 +353,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
				if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
							      EIGRP_FILTER_IN,
 | 
			
		||||
							      &dest_addr))
 | 
			
		||||
					ne->reported_metric.delay = EIGRP_MAX_METRIC;
 | 
			
		||||
					ne->reported_metric.delay =
 | 
			
		||||
						EIGRP_MAX_METRIC;
 | 
			
		||||
 | 
			
		||||
				ne->distance = eigrp_calculate_total_metrics(
 | 
			
		||||
					eigrp, ne);
 | 
			
		||||
@ -381,13 +381,13 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case EIGRP_TLV_IPv4_EXT:
 | 
			
		||||
			/* DVS: processing of external routes needs packet and fsm work.
 | 
			
		||||
			 *      for now, lets just not creash the box
 | 
			
		||||
			 */
 | 
			
		||||
		/* DVS: processing of external routes needs packet and fsm work.
 | 
			
		||||
		 *      for now, lets just not creash the box
 | 
			
		||||
		 */
 | 
			
		||||
		default:
 | 
			
		||||
			length = stream_getw(s);
 | 
			
		||||
			// -2 for type, -2 for len
 | 
			
		||||
			for (length-=4; length ; length--) {
 | 
			
		||||
			for (length -= 4; length; length--) {
 | 
			
		||||
				(void)stream_getc(s);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -428,10 +428,9 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
 | 
			
		||||
			   nbr->ei->eigrp->sequence_number,
 | 
			
		||||
			   nbr->recv_sequence_number);
 | 
			
		||||
 | 
			
		||||
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei->eigrp,
 | 
			
		||||
				 ep->s, EIGRP_INIT_FLAG,
 | 
			
		||||
				 nbr->ei->eigrp->sequence_number,
 | 
			
		||||
				 nbr->recv_sequence_number);
 | 
			
		||||
	eigrp_packet_header_init(
 | 
			
		||||
		EIGRP_OPC_UPDATE, nbr->ei->eigrp, ep->s, EIGRP_INIT_FLAG,
 | 
			
		||||
		nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number);
 | 
			
		||||
 | 
			
		||||
	// encode Authentication TLV, if needed
 | 
			
		||||
	if ((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
@ -464,12 +463,11 @@ void eigrp_update_send_init(struct eigrp_neighbor *nbr)
 | 
			
		||||
 | 
			
		||||
static void eigrp_update_place_on_nbr_queue(struct eigrp_neighbor *nbr,
 | 
			
		||||
					    struct eigrp_packet *ep,
 | 
			
		||||
					    u_int32_t seq_no,
 | 
			
		||||
					    int length)
 | 
			
		||||
					    u_int32_t seq_no, int length)
 | 
			
		||||
{
 | 
			
		||||
	if((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
 | 
			
		||||
	   (nbr->ei->params.auth_keychain != NULL)) {
 | 
			
		||||
		eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG);
 | 
			
		||||
	if ((nbr->ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
	    && (nbr->ei->params.auth_keychain != NULL)) {
 | 
			
		||||
		eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* EIGRP Checksum */
 | 
			
		||||
@ -541,14 +539,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
 | 
			
		||||
	ep = eigrp_packet_new(mtu, nbr);
 | 
			
		||||
 | 
			
		||||
	/* Prepare EIGRP EOT UPDATE header */
 | 
			
		||||
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
 | 
			
		||||
				 ep->s, EIGRP_EOT_FLAG,
 | 
			
		||||
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, ep->s, EIGRP_EOT_FLAG,
 | 
			
		||||
				 seq_no, nbr->recv_sequence_number);
 | 
			
		||||
 | 
			
		||||
	// encode Authentication TLV, if needed
 | 
			
		||||
	if((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
 | 
			
		||||
	   (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
		length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
 | 
			
		||||
	if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
	    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
		length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
 | 
			
		||||
@ -561,38 +558,40 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if ((length + EIGRP_TLV_MAX_IPV4_BYTE) > mtu) {
 | 
			
		||||
				eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
 | 
			
		||||
				eigrp_update_place_on_nbr_queue(nbr, ep, seq_no,
 | 
			
		||||
								length);
 | 
			
		||||
				seq_no++;
 | 
			
		||||
 | 
			
		||||
				length = EIGRP_HEADER_LEN;
 | 
			
		||||
				ep = eigrp_packet_new(mtu, nbr);
 | 
			
		||||
				eigrp_packet_header_init(EIGRP_OPC_UPDATE,
 | 
			
		||||
							 nbr->ei->eigrp,
 | 
			
		||||
							 ep->s, EIGRP_EOT_FLAG,
 | 
			
		||||
							 seq_no,
 | 
			
		||||
							 nbr->recv_sequence_number);
 | 
			
		||||
				eigrp_packet_header_init(
 | 
			
		||||
					EIGRP_OPC_UPDATE, nbr->ei->eigrp, ep->s,
 | 
			
		||||
					EIGRP_EOT_FLAG, seq_no,
 | 
			
		||||
					nbr->recv_sequence_number);
 | 
			
		||||
 | 
			
		||||
				if((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) &&
 | 
			
		||||
				   (ei->params.auth_keychain != NULL))
 | 
			
		||||
				{
 | 
			
		||||
					length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei);
 | 
			
		||||
				if ((ei->params.auth_type
 | 
			
		||||
				     == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
				    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
					length +=
 | 
			
		||||
						eigrp_add_authTLV_MD5_to_stream(
 | 
			
		||||
							ep->s, ei);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			/* Get destination address from prefix */
 | 
			
		||||
			dest_addr = pe->destination;
 | 
			
		||||
 | 
			
		||||
			/* Check if any list fits */
 | 
			
		||||
			if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
						      EIGRP_FILTER_OUT,
 | 
			
		||||
						      dest_addr))
 | 
			
		||||
			if (eigrp_update_prefix_apply(
 | 
			
		||||
				    eigrp, ei, EIGRP_FILTER_OUT, dest_addr))
 | 
			
		||||
				continue;
 | 
			
		||||
			else {
 | 
			
		||||
				length += eigrp_add_internalTLV_to_stream(ep->s, pe);
 | 
			
		||||
				length += eigrp_add_internalTLV_to_stream(ep->s,
 | 
			
		||||
									  pe);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length);
 | 
			
		||||
	eigrp_update_place_on_nbr_queue(nbr, ep, seq_no, length);
 | 
			
		||||
	eigrp->sequence_number = seq_no++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -614,8 +613,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
 | 
			
		||||
	ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 | 
			
		||||
 | 
			
		||||
	/* Prepare EIGRP INIT UPDATE header */
 | 
			
		||||
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
 | 
			
		||||
				 ep->s, 0, seq_no, 0);
 | 
			
		||||
	eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, ep->s, 0, seq_no, 0);
 | 
			
		||||
 | 
			
		||||
	// encode Authentication TLV, if needed
 | 
			
		||||
	if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
@ -635,11 +633,12 @@ void eigrp_update_send(struct eigrp_interface *ei)
 | 
			
		||||
		if (eigrp_nbr_split_horizon_check(ne, ei))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if ((length + EIGRP_TLV_MAX_IPV4_BYTE) >
 | 
			
		||||
		    (u_int16_t)ei->ifp->mtu) {
 | 
			
		||||
		if ((length + EIGRP_TLV_MAX_IPV4_BYTE)
 | 
			
		||||
		    > (u_int16_t)ei->ifp->mtu) {
 | 
			
		||||
			if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
			    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
				eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG);
 | 
			
		||||
				eigrp_make_md5_digest(ei, ep->s,
 | 
			
		||||
						      EIGRP_AUTH_UPDATE_FLAG);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			eigrp_packet_checksum(ei, ep->s, length);
 | 
			
		||||
@ -653,25 +652,24 @@ void eigrp_update_send(struct eigrp_interface *ei)
 | 
			
		||||
 | 
			
		||||
			length = EIGRP_HEADER_LEN;
 | 
			
		||||
			ep = eigrp_packet_new(ei->ifp->mtu, NULL);
 | 
			
		||||
			eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp,
 | 
			
		||||
						 ep->s, 0, seq_no, 0);
 | 
			
		||||
			eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, ep->s,
 | 
			
		||||
						 0, seq_no, 0);
 | 
			
		||||
			if ((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5)
 | 
			
		||||
			    && (ei->params.auth_keychain != NULL)) {
 | 
			
		||||
				length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei);
 | 
			
		||||
				length += eigrp_add_authTLV_MD5_to_stream(ep->s,
 | 
			
		||||
									  ei);
 | 
			
		||||
			}
 | 
			
		||||
			has_tlv = 0;
 | 
			
		||||
		}
 | 
			
		||||
		/* Get destination address from prefix */
 | 
			
		||||
		dest_addr = pe->destination;
 | 
			
		||||
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
					      EIGRP_FILTER_OUT,
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei, EIGRP_FILTER_OUT,
 | 
			
		||||
					      dest_addr)) {
 | 
			
		||||
			// pe->reported_metric.delay = EIGRP_MAX_METRIC;
 | 
			
		||||
			continue;
 | 
			
		||||
		} else {
 | 
			
		||||
			length += eigrp_add_internalTLV_to_stream(ep->s,
 | 
			
		||||
								  pe);
 | 
			
		||||
			length += eigrp_add_internalTLV_to_stream(ep->s, pe);
 | 
			
		||||
			has_tlv = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -729,7 +727,8 @@ void eigrp_update_send_all(struct eigrp *eigrp,
 | 
			
		||||
/**
 | 
			
		||||
 * @fn eigrp_update_send_GR_part
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]		nbr		contains neighbor who would receive Graceful
 | 
			
		||||
 * @param[in]		nbr		contains neighbor who would receive
 | 
			
		||||
 * Graceful
 | 
			
		||||
 * restart
 | 
			
		||||
 *
 | 
			
		||||
 * @return void
 | 
			
		||||
@ -814,8 +813,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
 | 
			
		||||
		 */
 | 
			
		||||
		dest_addr = pe->destination;
 | 
			
		||||
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
					      EIGRP_FILTER_OUT,
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei, EIGRP_FILTER_OUT,
 | 
			
		||||
					      dest_addr)) {
 | 
			
		||||
			/* do not send filtered route */
 | 
			
		||||
			zlog_info("Filtered prefix %s won't be sent out.",
 | 
			
		||||
@ -830,8 +828,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
 | 
			
		||||
		 * This makes no sense, Filter out then filter in???
 | 
			
		||||
		 * Look into this more - DBS
 | 
			
		||||
		 */
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei,
 | 
			
		||||
					      EIGRP_FILTER_IN,
 | 
			
		||||
		if (eigrp_update_prefix_apply(eigrp, ei, EIGRP_FILTER_IN,
 | 
			
		||||
					      dest_addr)) {
 | 
			
		||||
			/* do not send filtered route */
 | 
			
		||||
			zlog_info("Filtered prefix %s will be removed.",
 | 
			
		||||
@ -942,7 +939,8 @@ int eigrp_update_send_GR_thread(struct thread *thread)
 | 
			
		||||
/**
 | 
			
		||||
 * @fn eigrp_update_send_GR
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]		nbr			Neighbor who would receive Graceful
 | 
			
		||||
 * @param[in]		nbr			Neighbor who would receive
 | 
			
		||||
 * Graceful
 | 
			
		||||
 * restart
 | 
			
		||||
 * @param[in]		gr_type 	Who executed Graceful restart
 | 
			
		||||
 * @param[in]		vty 		Virtual terminal for log output
 | 
			
		||||
@ -980,8 +978,7 @@ void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type,
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				"Neighbor %s (%s) is resync: manually cleared\n",
 | 
			
		||||
				inet_ntoa(nbr->src),
 | 
			
		||||
				ifindex2ifname(ei->ifp->ifindex,
 | 
			
		||||
					       VRF_DEFAULT));
 | 
			
		||||
				ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1007,7 +1004,9 @@ void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type,
 | 
			
		||||
/**
 | 
			
		||||
 * @fn eigrp_update_send_interface_GR
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]		ei			Interface to neighbors of which the GR
 | 
			
		||||
 * @param[in]		ei			Interface to neighbors of which
 | 
			
		||||
 * the
 | 
			
		||||
 * GR
 | 
			
		||||
 * is sent
 | 
			
		||||
 * @param[in]		gr_type 	Who executed Graceful restart
 | 
			
		||||
 * @param[in]		vty 		Virtual terminal for log output
 | 
			
		||||
 | 
			
		||||
@ -109,8 +109,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
 | 
			
		||||
		if (ei->params.auth_keychain) {
 | 
			
		||||
			vty_out(vty,
 | 
			
		||||
				" ip authentication key-chain eigrp %d %s\n",
 | 
			
		||||
				eigrp->AS,
 | 
			
		||||
				ei->params.auth_keychain);
 | 
			
		||||
				eigrp->AS, ei->params.auth_keychain);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (ei->params.v_hello != EIGRP_HELLO_INTERVAL_DEFAULT) {
 | 
			
		||||
@ -147,8 +146,7 @@ static int eigrp_write_interface(struct vty *vty)
 | 
			
		||||
			vty_out(vty, " description %s\n", ifp->desc);
 | 
			
		||||
 | 
			
		||||
		if (ei->params.bandwidth != EIGRP_BANDWIDTH_DEFAULT)
 | 
			
		||||
			vty_out(vty, " bandwidth %u\n",
 | 
			
		||||
				ei->params.bandwidth);
 | 
			
		||||
			vty_out(vty, " bandwidth %u\n", ei->params.bandwidth);
 | 
			
		||||
		if (ei->params.delay != EIGRP_DELAY_DEFAULT)
 | 
			
		||||
			vty_out(vty, " delay %u\n", ei->params.delay);
 | 
			
		||||
		if (ei->params.v_hello != EIGRP_HELLO_INTERVAL_DEFAULT)
 | 
			
		||||
@ -495,7 +493,7 @@ DEFUN (show_ip_eigrp_topology,
 | 
			
		||||
				     & EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG)
 | 
			
		||||
				    == EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG))) {
 | 
			
		||||
				show_ip_eigrp_nexthop_entry(vty, eigrp, te,
 | 
			
		||||
							     &first);
 | 
			
		||||
							    &first);
 | 
			
		||||
				first = 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -777,8 +775,7 @@ DEFUN (no_eigrp_if_ip_hellointerval,
 | 
			
		||||
	ei->params.v_hello = EIGRP_HELLO_INTERVAL_DEFAULT;
 | 
			
		||||
 | 
			
		||||
	THREAD_TIMER_OFF(ei->t_hello);
 | 
			
		||||
	thread_add_timer(master, eigrp_hello_timer, ei, 1,
 | 
			
		||||
			 &ei->t_hello);
 | 
			
		||||
	thread_add_timer(master, eigrp_hello_timer, ei, 1, &ei->t_hello);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@ -1008,11 +1005,9 @@ DEFUN (eigrp_authentication_keychain,
 | 
			
		||||
	if (keychain != NULL) {
 | 
			
		||||
		if (ei->params.auth_keychain) {
 | 
			
		||||
			free(ei->params.auth_keychain);
 | 
			
		||||
			ei->params.auth_keychain =
 | 
			
		||||
				strdup(keychain->name);
 | 
			
		||||
			ei->params.auth_keychain = strdup(keychain->name);
 | 
			
		||||
		} else
 | 
			
		||||
			ei->params.auth_keychain =
 | 
			
		||||
				strdup(keychain->name);
 | 
			
		||||
			ei->params.auth_keychain = strdup(keychain->name);
 | 
			
		||||
	} else
 | 
			
		||||
		vty_out(vty, "Key chain with specified name not found\n");
 | 
			
		||||
 | 
			
		||||
@ -1339,8 +1334,7 @@ DEFUN (clear_ip_eigrp_neighbors_IP,
 | 
			
		||||
	struct in_addr nbr_addr;
 | 
			
		||||
 | 
			
		||||
	if (!inet_aton(argv[4]->arg, &nbr_addr)) {
 | 
			
		||||
		vty_out(vty, "Unable to parse %s",
 | 
			
		||||
			argv[4]->arg);
 | 
			
		||||
		vty_out(vty, "Unable to parse %s", argv[4]->arg);
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1446,8 +1440,7 @@ DEFUN (clear_ip_eigrp_neighbors_IP_soft,
 | 
			
		||||
	struct in_addr nbr_addr;
 | 
			
		||||
 | 
			
		||||
	if (!inet_aton(argv[4]->arg, &nbr_addr)) {
 | 
			
		||||
		vty_out(vty, "Unable to parse: %s",
 | 
			
		||||
			argv[4]->arg);
 | 
			
		||||
		vty_out(vty, "Unable to parse: %s", argv[4]->arg);
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -114,7 +114,7 @@ static void eigrp_zebra_connected(struct zclient *zclient)
 | 
			
		||||
 | 
			
		||||
void eigrp_zebra_init(void)
 | 
			
		||||
{
 | 
			
		||||
	struct zclient_options opt = { .receive_notify = false };
 | 
			
		||||
	struct zclient_options opt = {.receive_notify = false};
 | 
			
		||||
 | 
			
		||||
	zclient = zclient_new_notify(master, &opt);
 | 
			
		||||
 | 
			
		||||
@ -205,8 +205,7 @@ static int eigrp_interface_delete(int command, struct zclient *zclient,
 | 
			
		||||
			ifp->metric, ifp->mtu);
 | 
			
		||||
 | 
			
		||||
	if (ifp->info)
 | 
			
		||||
		eigrp_if_free(ifp->info,
 | 
			
		||||
			      INTERFACE_DOWN_BY_ZEBRA);
 | 
			
		||||
		eigrp_if_free(ifp->info, INTERFACE_DOWN_BY_ZEBRA);
 | 
			
		||||
 | 
			
		||||
	if_set_index(ifp, IFINDEX_INTERNAL);
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										74
									
								
								include/linux/fib_rules.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								include/linux/fib_rules.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
			
		||||
#ifndef __LINUX_FIB_RULES_H
 | 
			
		||||
#define __LINUX_FIB_RULES_H
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/rtnetlink.h>
 | 
			
		||||
 | 
			
		||||
/* rule is permanent, and cannot be deleted */
 | 
			
		||||
#define FIB_RULE_PERMANENT	0x00000001
 | 
			
		||||
#define FIB_RULE_INVERT		0x00000002
 | 
			
		||||
#define FIB_RULE_UNRESOLVED	0x00000004
 | 
			
		||||
#define FIB_RULE_IIF_DETACHED	0x00000008
 | 
			
		||||
#define FIB_RULE_DEV_DETACHED	FIB_RULE_IIF_DETACHED
 | 
			
		||||
#define FIB_RULE_OIF_DETACHED	0x00000010
 | 
			
		||||
 | 
			
		||||
/* try to find source address in routing lookups */
 | 
			
		||||
#define FIB_RULE_FIND_SADDR	0x00010000
 | 
			
		||||
 | 
			
		||||
struct fib_rule_hdr {
 | 
			
		||||
	__u8		family;
 | 
			
		||||
	__u8		dst_len;
 | 
			
		||||
	__u8		src_len;
 | 
			
		||||
	__u8		tos;
 | 
			
		||||
 | 
			
		||||
	__u8		table;
 | 
			
		||||
	__u8		res1;	/* reserved */
 | 
			
		||||
	__u8		res2;	/* reserved */
 | 
			
		||||
	__u8		action;
 | 
			
		||||
 | 
			
		||||
	__u32		flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	FRA_UNSPEC,
 | 
			
		||||
	FRA_DST,	/* destination address */
 | 
			
		||||
	FRA_SRC,	/* source address */
 | 
			
		||||
	FRA_IIFNAME,	/* interface name */
 | 
			
		||||
#define FRA_IFNAME	FRA_IIFNAME
 | 
			
		||||
	FRA_GOTO,	/* target to jump to (FR_ACT_GOTO) */
 | 
			
		||||
	FRA_UNUSED2,
 | 
			
		||||
	FRA_PRIORITY,	/* priority/preference */
 | 
			
		||||
	FRA_UNUSED3,
 | 
			
		||||
	FRA_UNUSED4,
 | 
			
		||||
	FRA_UNUSED5,
 | 
			
		||||
	FRA_FWMARK,	/* mark */
 | 
			
		||||
	FRA_FLOW,	/* flow/class id */
 | 
			
		||||
	FRA_UNUSED6,
 | 
			
		||||
	FRA_SUPPRESS_IFGROUP,
 | 
			
		||||
	FRA_SUPPRESS_PREFIXLEN,
 | 
			
		||||
	FRA_TABLE,	/* Extended table id */
 | 
			
		||||
	FRA_FWMASK,	/* mask for netfilter mark */
 | 
			
		||||
	FRA_OIFNAME,
 | 
			
		||||
	FRA_PAD,
 | 
			
		||||
	FRA_L3MDEV,	/* iif or oif is l3mdev goto its table */
 | 
			
		||||
	__FRA_MAX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FRA_MAX (__FRA_MAX - 1)
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	FR_ACT_UNSPEC,
 | 
			
		||||
	FR_ACT_TO_TBL,		/* Pass to fixed table */
 | 
			
		||||
	FR_ACT_GOTO,		/* Jump to another rule */
 | 
			
		||||
	FR_ACT_NOP,		/* No operation */
 | 
			
		||||
	FR_ACT_RES3,
 | 
			
		||||
	FR_ACT_RES4,
 | 
			
		||||
	FR_ACT_BLACKHOLE,	/* Drop without notification */
 | 
			
		||||
	FR_ACT_UNREACHABLE,	/* Drop with ENETUNREACH */
 | 
			
		||||
	FR_ACT_PROHIBIT,	/* Drop with EACCES */
 | 
			
		||||
	__FR_ACT_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FR_ACT_MAX (__FR_ACT_MAX - 1)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -7,4 +7,5 @@ noinst_HEADERS += \
 | 
			
		||||
	include/linux/rtnetlink.h \
 | 
			
		||||
	include/linux/socket.h \
 | 
			
		||||
	include/linux/net_namespace.h \
 | 
			
		||||
	include/linux/fib_rules.h \
 | 
			
		||||
	# end
 | 
			
		||||
 | 
			
		||||
@ -437,10 +437,10 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
 | 
			
		||||
			for (unsigned int i = 0; i < adj->area_address_count;
 | 
			
		||||
			     i++) {
 | 
			
		||||
				vty_out(vty, "      %s\n",
 | 
			
		||||
					  isonet_print(adj->area_addresses[i]
 | 
			
		||||
							       .area_addr,
 | 
			
		||||
						       adj->area_addresses[i]
 | 
			
		||||
							       .addr_len));
 | 
			
		||||
					isonet_print(adj->area_addresses[i]
 | 
			
		||||
							     .area_addr,
 | 
			
		||||
						     adj->area_addresses[i]
 | 
			
		||||
							     .addr_len));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (adj->ipv4_address_count) {
 | 
			
		||||
@ -448,7 +448,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
 | 
			
		||||
			for (unsigned int i = 0; i < adj->ipv4_address_count;
 | 
			
		||||
			     i++)
 | 
			
		||||
				vty_out(vty, "      %s\n",
 | 
			
		||||
					  inet_ntoa(adj->ipv4_addresses[i]));
 | 
			
		||||
					inet_ntoa(adj->ipv4_addresses[i]));
 | 
			
		||||
		}
 | 
			
		||||
		if (adj->ipv6_address_count) {
 | 
			
		||||
			vty_out(vty, "    IPv6 Address(es):\n");
 | 
			
		||||
 | 
			
		||||
@ -248,8 +248,7 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
 | 
			
		||||
		     bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
 | 
			
		||||
	stream_set_getp(circuit->rcv_stream, 0);
 | 
			
		||||
 | 
			
		||||
	memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN,
 | 
			
		||||
	       ETH_ALEN);
 | 
			
		||||
	memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
 | 
			
		||||
 | 
			
		||||
	if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
 | 
			
		||||
		zlog_warn("Flushing failed: %s", safe_strerror(errno));
 | 
			
		||||
 | 
			
		||||
@ -382,10 +382,12 @@ static uint8_t isis_circuit_id_gen(struct interface *ifp)
 | 
			
		||||
	/* Circuit ids MUST be unique for any broadcast circuits. Otherwise,
 | 
			
		||||
	 * Pseudo-Node LSPs cannot be generated correctly.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Currently, allocate one circuit ID for any circuit, limiting the total
 | 
			
		||||
	 * Currently, allocate one circuit ID for any circuit, limiting the
 | 
			
		||||
	 * total
 | 
			
		||||
	 * numer of circuits IS-IS can run on to 255.
 | 
			
		||||
	 *
 | 
			
		||||
	 * We should revisit this when implementing 3-way adjacencies for p2p, since
 | 
			
		||||
	 * We should revisit this when implementing 3-way adjacencies for p2p,
 | 
			
		||||
	 * since
 | 
			
		||||
	 * we then have extended interface IDs available.
 | 
			
		||||
	 */
 | 
			
		||||
	uint8_t id = ifp->ifindex;
 | 
			
		||||
@ -398,7 +400,8 @@ static uint8_t isis_circuit_id_gen(struct interface *ifp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (i == 256) {
 | 
			
		||||
		zlog_warn("Could not allocate a circuit id for '%s'", ifp->name);
 | 
			
		||||
		zlog_warn("Could not allocate a circuit id for '%s'",
 | 
			
		||||
			  ifp->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1349,7 +1352,8 @@ void isis_circuit_schedule_lsp_send(struct isis_circuit *circuit)
 | 
			
		||||
{
 | 
			
		||||
	if (circuit->t_send_lsp)
 | 
			
		||||
		return;
 | 
			
		||||
	circuit->t_send_lsp = thread_add_event(master, send_lsp, circuit, 0, NULL);
 | 
			
		||||
	circuit->t_send_lsp =
 | 
			
		||||
		thread_add_event(master, send_lsp, circuit, 0, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void isis_circuit_queue_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp)
 | 
			
		||||
 | 
			
		||||
@ -82,8 +82,9 @@ struct isis_circuit {
 | 
			
		||||
	struct thread *t_send_csnp[2];
 | 
			
		||||
	struct thread *t_send_psnp[2];
 | 
			
		||||
	struct thread *t_send_lsp;
 | 
			
		||||
	struct list *lsp_queue;	/* LSPs to be txed (both levels) */
 | 
			
		||||
	struct isis_lsp_hash *lsp_hash; /* Hashtable synchronized with lsp_queue */
 | 
			
		||||
	struct list *lsp_queue; /* LSPs to be txed (both levels) */
 | 
			
		||||
	struct isis_lsp_hash
 | 
			
		||||
		*lsp_hash; /* Hashtable synchronized with lsp_queue */
 | 
			
		||||
	time_t lsp_queue_last_push[2]; /* timestamp used to enforce transmit
 | 
			
		||||
					* interval;
 | 
			
		||||
					* for scalability, use one timestamp per
 | 
			
		||||
@ -96,8 +97,6 @@ struct isis_circuit {
 | 
			
		||||
	int (*tx)(struct isis_circuit *circuit, int level);
 | 
			
		||||
	struct stream *snd_stream; /* Stream for sending */
 | 
			
		||||
	int idx;		   /* idx in S[RM|SN] flags */
 | 
			
		||||
				   /* $FRR indent$ */
 | 
			
		||||
				   /* clang-format off */
 | 
			
		||||
#define CIRCUIT_T_UNKNOWN    0
 | 
			
		||||
#define CIRCUIT_T_BROADCAST  1
 | 
			
		||||
#define CIRCUIT_T_P2P        2
 | 
			
		||||
@ -185,7 +184,7 @@ void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router,
 | 
			
		||||
			 bool ipv6_router);
 | 
			
		||||
ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive);
 | 
			
		||||
void isis_circuit_is_type_set(struct isis_circuit *circuit, int is_type);
 | 
			
		||||
ferr_r isis_circuit_circ_type_set (struct isis_circuit *circuit, int circ_type);
 | 
			
		||||
ferr_r isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type);
 | 
			
		||||
 | 
			
		||||
ferr_r isis_circuit_metric_set(struct isis_circuit *circuit, int level,
 | 
			
		||||
			       int metric);
 | 
			
		||||
 | 
			
		||||
@ -41,20 +41,18 @@ long int flags_get_index(struct flags *flags);
 | 
			
		||||
void flags_free_index(struct flags *flags, long int index);
 | 
			
		||||
int flags_any_set(u_int32_t *flags);
 | 
			
		||||
 | 
			
		||||
#define _ISIS_SET_FLAG(F, C)                          \
 | 
			
		||||
	{                                             \
 | 
			
		||||
		F[(C) >> 5] |= (1 << ((C) & 0x1F));   \
 | 
			
		||||
#define _ISIS_SET_FLAG(F, C)                                                   \
 | 
			
		||||
	{                                                                      \
 | 
			
		||||
		F[(C) >> 5] |= (1 << ((C)&0x1F));                              \
 | 
			
		||||
	}
 | 
			
		||||
#define ISIS_SET_FLAG(F, C) _ISIS_SET_FLAG(F, C->idx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define _ISIS_CLEAR_FLAG(F, C)                        \
 | 
			
		||||
	{                                             \
 | 
			
		||||
		F[(C) >> 5] &= ~(1 << ((C) & 0x1F));  \
 | 
			
		||||
#define _ISIS_CLEAR_FLAG(F, C)                                                 \
 | 
			
		||||
	{                                                                      \
 | 
			
		||||
		F[(C) >> 5] &= ~(1 << ((C)&0x1F));                             \
 | 
			
		||||
	}
 | 
			
		||||
#define ISIS_CLEAR_FLAG(F, C) _ISIS_CLEAR_FLAG(F, C->idx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define _ISIS_CHECK_FLAG(F, C)  (F[(C)>>5] & (1<<((C) & 0x1F)))
 | 
			
		||||
#define ISIS_CHECK_FLAG(F, C) _ISIS_CHECK_FLAG(F, C->idx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1106,7 +1106,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
 | 
			
		||||
	struct list *fragments = isis_fragment_tlvs(tlvs, tlv_space);
 | 
			
		||||
	if (!fragments) {
 | 
			
		||||
		zlog_warn("BUG: could not fragment own LSP:");
 | 
			
		||||
		log_multiline(LOG_WARNING, "    ", "%s", isis_format_tlvs(tlvs));
 | 
			
		||||
		log_multiline(LOG_WARNING, "    ", "%s",
 | 
			
		||||
			      isis_format_tlvs(tlvs));
 | 
			
		||||
		isis_free_tlvs(tlvs);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@ -1119,8 +1120,9 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
 | 
			
		||||
			if (LSP_FRAGMENT(frag->hdr.lsp_id) == 255) {
 | 
			
		||||
				if (!fragment_overflow) {
 | 
			
		||||
					fragment_overflow = true;
 | 
			
		||||
					zlog_warn("ISIS (%s): Too much information for 256 fragments",
 | 
			
		||||
						  area->area_tag);
 | 
			
		||||
					zlog_warn(
 | 
			
		||||
						"ISIS (%s): Too much information for 256 fragments",
 | 
			
		||||
						area->area_tag);
 | 
			
		||||
				}
 | 
			
		||||
				isis_free_tlvs(tlvs);
 | 
			
		||||
				continue;
 | 
			
		||||
@ -1794,7 +1796,7 @@ int lsp_tick(struct thread *thread)
 | 
			
		||||
	dnode_t *dnode, *dnode_next;
 | 
			
		||||
	int level;
 | 
			
		||||
	u_int16_t rem_lifetime;
 | 
			
		||||
        time_t now = monotime(NULL);
 | 
			
		||||
	time_t now = monotime(NULL);
 | 
			
		||||
 | 
			
		||||
	lsp_list = list_new();
 | 
			
		||||
 | 
			
		||||
@ -1873,12 +1875,15 @@ int lsp_tick(struct thread *thread)
 | 
			
		||||
					if (!circuit->lsp_queue)
 | 
			
		||||
						continue;
 | 
			
		||||
 | 
			
		||||
					if (now - circuit->lsp_queue_last_push[level]
 | 
			
		||||
					if (now
 | 
			
		||||
						    - circuit->lsp_queue_last_push
 | 
			
		||||
							      [level]
 | 
			
		||||
					    < MIN_LSP_RETRANS_INTERVAL) {
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					circuit->lsp_queue_last_push[level] = now;
 | 
			
		||||
					circuit->lsp_queue_last_push[level] =
 | 
			
		||||
						now;
 | 
			
		||||
 | 
			
		||||
					for (ALL_LIST_ELEMENTS_RO(
 | 
			
		||||
						     lsp_list, lspnode, lsp)) {
 | 
			
		||||
@ -1887,7 +1892,8 @@ int lsp_tick(struct thread *thread)
 | 
			
		||||
						    && ISIS_CHECK_FLAG(
 | 
			
		||||
							       lsp->SRMflags,
 | 
			
		||||
							       circuit)) {
 | 
			
		||||
							isis_circuit_queue_lsp(circuit, lsp);
 | 
			
		||||
							isis_circuit_queue_lsp(
 | 
			
		||||
								circuit, lsp);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ void isis_lsp_hash_free(struct isis_lsp_hash *ih)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct isis_lsp *isis_lsp_hash_lookup(struct isis_lsp_hash *ih,
 | 
			
		||||
			    struct isis_lsp *lsp)
 | 
			
		||||
				      struct isis_lsp *lsp)
 | 
			
		||||
{
 | 
			
		||||
	return hash_lookup(ih->h, lsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -887,11 +887,10 @@ dontcheckadj:
 | 
			
		||||
					lsp_set_all_srmflags(lsp);
 | 
			
		||||
					/* v */
 | 
			
		||||
					ISIS_FLAGS_CLEAR_ALL(
 | 
			
		||||
						lsp
 | 
			
		||||
							->SSNflags); /* FIXME:
 | 
			
		||||
									OTHER
 | 
			
		||||
									than c
 | 
			
		||||
									*/
 | 
			
		||||
						lsp->SSNflags); /* FIXME:
 | 
			
		||||
								   OTHER
 | 
			
		||||
								   than c
 | 
			
		||||
								   */
 | 
			
		||||
 | 
			
		||||
					/* For the case of lsp confusion, flood
 | 
			
		||||
					 * the purge back to its
 | 
			
		||||
@ -1185,7 +1184,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
 | 
			
		||||
		     entry = entry->next) {
 | 
			
		||||
			zlog_debug(
 | 
			
		||||
				"ISIS-Snp (%s):         %cSNP entry %s, seq 0x%08" PRIx32
 | 
			
		||||
				", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s",
 | 
			
		||||
				", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
 | 
			
		||||
				"s",
 | 
			
		||||
				circuit->area->area_tag, typechar,
 | 
			
		||||
				rawlspid_print(entry->id), entry->seqno,
 | 
			
		||||
				entry->checksum, entry->rem_lifetime);
 | 
			
		||||
@ -1244,10 +1244,12 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
 | 
			
		||||
					       ISIS_SYS_ID_LEN + 1);
 | 
			
		||||
					LSP_FRAGMENT(lspid) = 0;
 | 
			
		||||
					lsp0 = lsp_search(
 | 
			
		||||
						  lspid,
 | 
			
		||||
						  circuit->area->lspdb[level - 1]);
 | 
			
		||||
						lspid,
 | 
			
		||||
						circuit->area
 | 
			
		||||
							->lspdb[level - 1]);
 | 
			
		||||
					if (!lsp0) {
 | 
			
		||||
						zlog_debug("Got lsp frag in snp, while zero not in database");
 | 
			
		||||
						zlog_debug(
 | 
			
		||||
							"Got lsp frag in snp, while zero not in database");
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@ -45,17 +45,16 @@
 | 
			
		||||
#include "privs.h"
 | 
			
		||||
 | 
			
		||||
/* tcpdump -i eth0 'isis' -dd */
 | 
			
		||||
static struct sock_filter isisfilter[] =
 | 
			
		||||
	{
 | 
			
		||||
		/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped
 | 
			
		||||
		 * off!
 | 
			
		||||
		 * (OTOH it's a bit more lower-layer agnostic and might work
 | 
			
		||||
		 * over GRE?) */
 | 
			
		||||
		/*	{ 0x28, 0, 0, 0x0000000c - 14 }, */
 | 
			
		||||
		/*	{ 0x25, 5, 0, 0x000005dc }, */
 | 
			
		||||
		{0x28, 0, 0, 0x0000000e - 14}, {0x15, 0, 3, 0x0000fefe},
 | 
			
		||||
		{0x30, 0, 0, 0x00000011 - 14}, {0x15, 0, 1, 0x00000083},
 | 
			
		||||
		{0x6, 0, 0, 0x00040000},       {0x6, 0, 0, 0x00000000},
 | 
			
		||||
static struct sock_filter isisfilter[] = {
 | 
			
		||||
	/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped
 | 
			
		||||
	 * off!
 | 
			
		||||
	 * (OTOH it's a bit more lower-layer agnostic and might work
 | 
			
		||||
	 * over GRE?) */
 | 
			
		||||
	/*	{ 0x28, 0, 0, 0x0000000c - 14 }, */
 | 
			
		||||
	/*	{ 0x25, 5, 0, 0x000005dc }, */
 | 
			
		||||
	{0x28, 0, 0, 0x0000000e - 14}, {0x15, 0, 3, 0x0000fefe},
 | 
			
		||||
	{0x30, 0, 0, 0x00000011 - 14}, {0x15, 0, 1, 0x00000083},
 | 
			
		||||
	{0x6, 0, 0, 0x00040000},       {0x6, 0, 0, 0x00000000},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct sock_fprog bpf = {
 | 
			
		||||
 | 
			
		||||
@ -85,10 +85,10 @@ struct isis_vertex {
 | 
			
		||||
		struct prefix prefix;
 | 
			
		||||
	} N;
 | 
			
		||||
 | 
			
		||||
	u_int32_t d_N;	       /* d(N) Distance from this IS      */
 | 
			
		||||
	u_int16_t depth;       /* The depth in the imaginary tree */
 | 
			
		||||
	struct list *Adj_N;    /* {Adj(N)} next hop or neighbor list */
 | 
			
		||||
	struct list *parents;  /* list of parents for ECMP */
 | 
			
		||||
	u_int32_t d_N;	/* d(N) Distance from this IS      */
 | 
			
		||||
	u_int16_t depth;      /* The depth in the imaginary tree */
 | 
			
		||||
	struct list *Adj_N;   /* {Adj(N)} next hop or neighbor list */
 | 
			
		||||
	struct list *parents; /* list of parents for ECMP */
 | 
			
		||||
	uint64_t insert_counter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,8 @@ static struct skiplist *isis_vertex_queue_skiplist(void)
 | 
			
		||||
	return skiplist_new(0, isis_vertex_queue_tent_cmp, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void isis_vertex_queue_init(struct isis_vertex_queue *queue, const char *name, bool ordered)
 | 
			
		||||
static void isis_vertex_queue_init(struct isis_vertex_queue *queue,
 | 
			
		||||
				   const char *name, bool ordered)
 | 
			
		||||
{
 | 
			
		||||
	if (ordered) {
 | 
			
		||||
		queue->insert_counter = 1;
 | 
			
		||||
@ -171,8 +172,7 @@ static void isis_vertex_queue_init(struct isis_vertex_queue *queue, const char *
 | 
			
		||||
		queue->l.list = list_new();
 | 
			
		||||
	}
 | 
			
		||||
	queue->hash = hash_create(isis_vertex_queue_hash_key,
 | 
			
		||||
				  isis_vertex_queue_hash_cmp,
 | 
			
		||||
				  name);
 | 
			
		||||
				  isis_vertex_queue_hash_cmp, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void isis_vertex_del(struct isis_vertex *vertex);
 | 
			
		||||
@ -183,7 +183,8 @@ static void isis_vertex_queue_clear(struct isis_vertex_queue *queue)
 | 
			
		||||
 | 
			
		||||
	if (queue->insert_counter) {
 | 
			
		||||
		struct isis_vertex *vertex;
 | 
			
		||||
		while (0 == skiplist_first(queue->l.slist, NULL, (void**)&vertex)) {
 | 
			
		||||
		while (0 == skiplist_first(queue->l.slist, NULL,
 | 
			
		||||
					   (void **)&vertex)) {
 | 
			
		||||
			isis_vertex_del(vertex);
 | 
			
		||||
			skiplist_delete_first(queue->l.slist);
 | 
			
		||||
		}
 | 
			
		||||
@ -241,13 +242,14 @@ static void isis_vertex_queue_insert(struct isis_vertex_queue *queue,
 | 
			
		||||
	assert(inserted == vertex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct isis_vertex *isis_vertex_queue_pop(struct isis_vertex_queue *queue)
 | 
			
		||||
static struct isis_vertex *
 | 
			
		||||
isis_vertex_queue_pop(struct isis_vertex_queue *queue)
 | 
			
		||||
{
 | 
			
		||||
	assert(queue->insert_counter);
 | 
			
		||||
 | 
			
		||||
	struct isis_vertex *rv;
 | 
			
		||||
 | 
			
		||||
	if (skiplist_first(queue->l.slist, NULL, (void**)&rv))
 | 
			
		||||
	if (skiplist_first(queue->l.slist, NULL, (void **)&rv))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	skiplist_delete_first(queue->l.slist);
 | 
			
		||||
@ -265,8 +267,8 @@ static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
 | 
			
		||||
	hash_release(queue->hash, vertex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \
 | 
			
		||||
		ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
 | 
			
		||||
#define ALL_QUEUE_ELEMENTS_RO(queue, node, data)                               \
 | 
			
		||||
	ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* End of vertex queue definitions */
 | 
			
		||||
@ -274,11 +276,12 @@ static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
 | 
			
		||||
struct isis_spftree {
 | 
			
		||||
	struct isis_vertex_queue paths; /* the SPT */
 | 
			
		||||
	struct isis_vertex_queue tents; /* TENT */
 | 
			
		||||
	struct isis_area *area;    /* back pointer to area */
 | 
			
		||||
	unsigned int runcount;     /* number of runs since uptime */
 | 
			
		||||
	time_t last_run_timestamp; /* last run timestamp as wall time for display */
 | 
			
		||||
	time_t last_run_monotime;  /* last run as monotime for scheduling */
 | 
			
		||||
	time_t last_run_duration;  /* last run duration in msec */
 | 
			
		||||
	struct isis_area *area;		/* back pointer to area */
 | 
			
		||||
	unsigned int runcount;		/* number of runs since uptime */
 | 
			
		||||
	time_t last_run_timestamp;      /* last run timestamp as wall time for
 | 
			
		||||
					   display */
 | 
			
		||||
	time_t last_run_monotime; /* last run as monotime for scheduling */
 | 
			
		||||
	time_t last_run_duration; /* last run duration in msec */
 | 
			
		||||
 | 
			
		||||
	uint16_t mtid;
 | 
			
		||||
	int family;
 | 
			
		||||
@ -405,7 +408,8 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
 | 
			
		||||
	return "UNKNOWN";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void isis_vertex_id_init(struct isis_vertex *vertex, void *id, enum vertextype vtype)
 | 
			
		||||
static void isis_vertex_id_init(struct isis_vertex *vertex, void *id,
 | 
			
		||||
				enum vertextype vtype)
 | 
			
		||||
{
 | 
			
		||||
	vertex->type = vtype;
 | 
			
		||||
 | 
			
		||||
@ -621,8 +625,8 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
 | 
			
		||||
	return vertex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue, void *id,
 | 
			
		||||
					    enum vertextype vtype)
 | 
			
		||||
static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue,
 | 
			
		||||
					    void *id, enum vertextype vtype)
 | 
			
		||||
{
 | 
			
		||||
	struct isis_vertex querier;
 | 
			
		||||
 | 
			
		||||
@ -827,10 +831,10 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
 | 
			
		||||
		return ISIS_OK;
 | 
			
		||||
 | 
			
		||||
	/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
 | 
			
		||||
	bool no_overload = (pseudo_lsp
 | 
			
		||||
			    || (spftree->mtid == ISIS_MT_IPV4_UNICAST
 | 
			
		||||
	bool no_overload =
 | 
			
		||||
		(pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST
 | 
			
		||||
				&& !ISIS_MASK_LSP_OL_BIT(lsp->hdr.lsp_bits))
 | 
			
		||||
			    || (mt_router_info && !mt_router_info->overload));
 | 
			
		||||
		 || (mt_router_info && !mt_router_info->overload));
 | 
			
		||||
 | 
			
		||||
lspfragloop:
 | 
			
		||||
	if (lsp->hdr.seqno == 0) {
 | 
			
		||||
@ -1372,10 +1376,10 @@ static int isis_run_spf_cb(struct thread *thread)
 | 
			
		||||
 | 
			
		||||
	if (area->ip_circuits)
 | 
			
		||||
		retval = isis_run_spf(area, level, AF_INET, isis->sysid,
 | 
			
		||||
			&thread->real);
 | 
			
		||||
				      &thread->real);
 | 
			
		||||
	if (area->ipv6_circuits)
 | 
			
		||||
		retval = isis_run_spf(area, level, AF_INET6, isis->sysid,
 | 
			
		||||
			&thread->real);
 | 
			
		||||
				      &thread->real);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
@ -1426,7 +1430,8 @@ int isis_spf_schedule(struct isis_area *area, int level)
 | 
			
		||||
	/* wait configured min_spf_interval before doing the SPF */
 | 
			
		||||
	long timer;
 | 
			
		||||
	if (diff >= area->min_spf_interval[level - 1]) {
 | 
			
		||||
		/* Last run is more than min interval ago, schedule immediate run */
 | 
			
		||||
		/* Last run is more than min interval ago, schedule immediate
 | 
			
		||||
		 * run */
 | 
			
		||||
		timer = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		timer = area->min_spf_interval[level - 1] - diff;
 | 
			
		||||
@ -1469,9 +1474,9 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue,
 | 
			
		||||
		vty_out(vty, "%-20s %-12s %-6u ",
 | 
			
		||||
			vid2string(vertex, buff, sizeof(buff)),
 | 
			
		||||
			vtype2string(vertex->type), vertex->d_N);
 | 
			
		||||
		for (unsigned int i = 0;
 | 
			
		||||
		     i < MAX(listcount(vertex->Adj_N),
 | 
			
		||||
			     listcount(vertex->parents)); i++) {
 | 
			
		||||
		for (unsigned int i = 0; i < MAX(listcount(vertex->Adj_N),
 | 
			
		||||
						 listcount(vertex->parents));
 | 
			
		||||
		     i++) {
 | 
			
		||||
			if (anode) {
 | 
			
		||||
				adj = listgetdata(anode);
 | 
			
		||||
				anode = anode->next;
 | 
			
		||||
@ -1502,8 +1507,7 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue,
 | 
			
		||||
					vty_out(vty, "%-20s %-9s ", "", "");
 | 
			
		||||
 | 
			
		||||
				vty_out(vty, "%s(%d)",
 | 
			
		||||
					vid2string(pvertex, buff,
 | 
			
		||||
						   sizeof(buff)),
 | 
			
		||||
					vid2string(pvertex, buff, sizeof(buff)),
 | 
			
		||||
					pvertex->type);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -1545,7 +1549,9 @@ DEFUN (show_isis_topology,
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (area->ip_circuits > 0 && area->spftree[level - 1]
 | 
			
		||||
			    && isis_vertex_queue_count(&area->spftree[level - 1]->paths) > 0) {
 | 
			
		||||
			    && isis_vertex_queue_count(
 | 
			
		||||
				       &area->spftree[level - 1]->paths)
 | 
			
		||||
				       > 0) {
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"IS-IS paths to level-%d routers that speak IP\n",
 | 
			
		||||
					level);
 | 
			
		||||
@ -1555,7 +1561,9 @@ DEFUN (show_isis_topology,
 | 
			
		||||
				vty_out(vty, "\n");
 | 
			
		||||
			}
 | 
			
		||||
			if (area->ipv6_circuits > 0 && area->spftree6[level - 1]
 | 
			
		||||
			    && isis_vertex_queue_count(&area->spftree6[level - 1]->paths) > 0) {
 | 
			
		||||
			    && isis_vertex_queue_count(
 | 
			
		||||
				       &area->spftree6[level - 1]->paths)
 | 
			
		||||
				       > 0) {
 | 
			
		||||
				vty_out(vty,
 | 
			
		||||
					"IS-IS paths to level-%d routers that speak IPv6\n",
 | 
			
		||||
					level);
 | 
			
		||||
@ -1586,6 +1594,5 @@ void isis_spf_print(struct isis_spftree *spftree, struct vty *vty)
 | 
			
		||||
	vty_out(vty, "      last run duration : %u usec\n",
 | 
			
		||||
		(u_int32_t)spftree->last_run_duration);
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "      run count         : %u\n",
 | 
			
		||||
		spftree->runcount);
 | 
			
		||||
	vty_out(vty, "      run count         : %u\n", spftree->runcount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -725,7 +725,8 @@ static u_char print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
 | 
			
		||||
 | 
			
		||||
	fval = ntohf(tlv->value);
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", fval);
 | 
			
		||||
	sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
 | 
			
		||||
		  fval);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
}
 | 
			
		||||
@ -741,8 +742,9 @@ static u_char print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
 | 
			
		||||
	for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
 | 
			
		||||
		fval1 = ntohf(tlv->value[i]);
 | 
			
		||||
		fval2 = ntohf(tlv->value[i + 1]);
 | 
			
		||||
		sbuf_push(buf, indent + 2, "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
 | 
			
		||||
			  i, fval1, i + 1, fval2);
 | 
			
		||||
		sbuf_push(buf, indent + 2,
 | 
			
		||||
			  "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i,
 | 
			
		||||
			  fval1, i + 1, fval2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
 | 
			
		||||
@ -786,7 +788,8 @@ static u_char print_subtlv_av_delay(struct sbuf *buf, int indent,
 | 
			
		||||
	delay = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK;
 | 
			
		||||
	A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
 | 
			
		||||
	sbuf_push(buf, indent,
 | 
			
		||||
		  "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
 | 
			
		||||
		  A ? "Anomalous" : "Normal", delay);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
@ -802,7 +805,8 @@ static u_char print_subtlv_mm_delay(struct sbuf *buf, int indent,
 | 
			
		||||
	A = (u_int32_t)ntohl(tlv->low) & TE_EXT_ANORMAL;
 | 
			
		||||
	high = (u_int32_t)ntohl(tlv->high) & TE_EXT_MASK;
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
 | 
			
		||||
	sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32
 | 
			
		||||
			       " (micro-sec)\n",
 | 
			
		||||
		  A ? "Anomalous" : "Normal", low, high);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
@ -815,7 +819,8 @@ static u_char print_subtlv_delay_var(struct sbuf *buf, int indent,
 | 
			
		||||
 | 
			
		||||
	jitter = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK;
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n", jitter);
 | 
			
		||||
	sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n",
 | 
			
		||||
		  jitter);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
}
 | 
			
		||||
@ -844,8 +849,8 @@ static u_char print_subtlv_res_bw(struct sbuf *buf, int indent,
 | 
			
		||||
 | 
			
		||||
	fval = ntohf(tlv->value);
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
 | 
			
		||||
		  fval);
 | 
			
		||||
	sbuf_push(buf, indent,
 | 
			
		||||
		  "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
}
 | 
			
		||||
@ -857,8 +862,8 @@ static u_char print_subtlv_ava_bw(struct sbuf *buf, int indent,
 | 
			
		||||
 | 
			
		||||
	fval = ntohf(tlv->value);
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
 | 
			
		||||
		  fval);
 | 
			
		||||
	sbuf_push(buf, indent,
 | 
			
		||||
		  "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
}
 | 
			
		||||
@ -870,8 +875,8 @@ static u_char print_subtlv_use_bw(struct sbuf *buf, int indent,
 | 
			
		||||
 | 
			
		||||
	fval = ntohf(tlv->value);
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
 | 
			
		||||
		  fval);
 | 
			
		||||
	sbuf_push(buf, indent,
 | 
			
		||||
		  "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval);
 | 
			
		||||
 | 
			
		||||
	return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
 | 
			
		||||
}
 | 
			
		||||
@ -892,8 +897,7 @@ static u_char print_unknown_tlv(struct sbuf *buf, int indent,
 | 
			
		||||
			sbuf_push(buf, 0, " %#.2x", v[i]);
 | 
			
		||||
			if (rtn == 8) {
 | 
			
		||||
				sbuf_push(buf, 0, "\n");
 | 
			
		||||
				sbuf_push(buf, indent + 8,
 | 
			
		||||
					  "[%.2x]", i + 1);
 | 
			
		||||
				sbuf_push(buf, indent + 8, "[%.2x]", i + 1);
 | 
			
		||||
				rtn = 1;
 | 
			
		||||
			} else
 | 
			
		||||
				rtn++;
 | 
			
		||||
@ -909,8 +913,8 @@ static u_char print_unknown_tlv(struct sbuf *buf, int indent,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Main Show function */
 | 
			
		||||
void mpls_te_print_detail(struct sbuf *buf, int indent,
 | 
			
		||||
			  uint8_t *subtlvs, uint8_t subtlv_len)
 | 
			
		||||
void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs,
 | 
			
		||||
			  uint8_t subtlv_len)
 | 
			
		||||
{
 | 
			
		||||
	struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
 | 
			
		||||
	uint16_t sum = 0;
 | 
			
		||||
@ -918,72 +922,78 @@ void mpls_te_print_detail(struct sbuf *buf, int indent,
 | 
			
		||||
	for (; sum < subtlv_len; tlvh = SUBTLV_HDR_NEXT(tlvh)) {
 | 
			
		||||
		switch (tlvh->type) {
 | 
			
		||||
		case TE_SUBTLV_ADMIN_GRP:
 | 
			
		||||
			sum += print_subtlv_admin_grp(buf, indent,
 | 
			
		||||
			sum += print_subtlv_admin_grp(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_admin_grp *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_LLRI:
 | 
			
		||||
			sum += print_subtlv_llri(buf, indent,
 | 
			
		||||
				(struct te_subtlv_llri *)tlvh);
 | 
			
		||||
						 (struct te_subtlv_llri *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_LOCAL_IPADDR:
 | 
			
		||||
			sum += print_subtlv_local_ipaddr(buf, indent,
 | 
			
		||||
			sum += print_subtlv_local_ipaddr(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_local_ipaddr *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_RMT_IPADDR:
 | 
			
		||||
			sum += print_subtlv_rmt_ipaddr(buf, indent,
 | 
			
		||||
			sum += print_subtlv_rmt_ipaddr(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_rmt_ipaddr *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_MAX_BW:
 | 
			
		||||
			sum += print_subtlv_max_bw(buf, indent,
 | 
			
		||||
				(struct te_subtlv_max_bw *)tlvh);
 | 
			
		||||
			sum += print_subtlv_max_bw(
 | 
			
		||||
				buf, indent, (struct te_subtlv_max_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_MAX_RSV_BW:
 | 
			
		||||
			sum += print_subtlv_max_rsv_bw(buf, indent,
 | 
			
		||||
			sum += print_subtlv_max_rsv_bw(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_max_rsv_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_UNRSV_BW:
 | 
			
		||||
			sum += print_subtlv_unrsv_bw(buf, indent,
 | 
			
		||||
				(struct te_subtlv_unrsv_bw *)tlvh);
 | 
			
		||||
			sum += print_subtlv_unrsv_bw(
 | 
			
		||||
				buf, indent, (struct te_subtlv_unrsv_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_TE_METRIC:
 | 
			
		||||
			sum += print_subtlv_te_metric(buf, indent,
 | 
			
		||||
			sum += print_subtlv_te_metric(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_te_metric *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_RAS:
 | 
			
		||||
			sum += print_subtlv_ras(buf, indent,
 | 
			
		||||
				(struct te_subtlv_ras *)tlvh);
 | 
			
		||||
						(struct te_subtlv_ras *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_RIP:
 | 
			
		||||
			sum += print_subtlv_rip(buf, indent,
 | 
			
		||||
				(struct te_subtlv_rip *)tlvh);
 | 
			
		||||
						(struct te_subtlv_rip *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_AV_DELAY:
 | 
			
		||||
			sum += print_subtlv_av_delay(buf, indent,
 | 
			
		||||
				(struct te_subtlv_av_delay *)tlvh);
 | 
			
		||||
			sum += print_subtlv_av_delay(
 | 
			
		||||
				buf, indent, (struct te_subtlv_av_delay *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_MM_DELAY:
 | 
			
		||||
			sum += print_subtlv_mm_delay(buf, indent,
 | 
			
		||||
				(struct te_subtlv_mm_delay *)tlvh);
 | 
			
		||||
			sum += print_subtlv_mm_delay(
 | 
			
		||||
				buf, indent, (struct te_subtlv_mm_delay *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_DELAY_VAR:
 | 
			
		||||
			sum += print_subtlv_delay_var(buf, indent,
 | 
			
		||||
			sum += print_subtlv_delay_var(
 | 
			
		||||
				buf, indent,
 | 
			
		||||
				(struct te_subtlv_delay_var *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_PKT_LOSS:
 | 
			
		||||
			sum += print_subtlv_pkt_loss(buf, indent,
 | 
			
		||||
				(struct te_subtlv_pkt_loss *)tlvh);
 | 
			
		||||
			sum += print_subtlv_pkt_loss(
 | 
			
		||||
				buf, indent, (struct te_subtlv_pkt_loss *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_RES_BW:
 | 
			
		||||
			sum += print_subtlv_res_bw(buf, indent,
 | 
			
		||||
				(struct te_subtlv_res_bw *)tlvh);
 | 
			
		||||
			sum += print_subtlv_res_bw(
 | 
			
		||||
				buf, indent, (struct te_subtlv_res_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_AVA_BW:
 | 
			
		||||
			sum += print_subtlv_ava_bw(buf, indent,
 | 
			
		||||
				(struct te_subtlv_ava_bw *)tlvh);
 | 
			
		||||
			sum += print_subtlv_ava_bw(
 | 
			
		||||
				buf, indent, (struct te_subtlv_ava_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		case TE_SUBTLV_USE_BW:
 | 
			
		||||
			sum += print_subtlv_use_bw(buf, indent,
 | 
			
		||||
				(struct te_subtlv_use_bw *)tlvh);
 | 
			
		||||
			sum += print_subtlv_use_bw(
 | 
			
		||||
				buf, indent, (struct te_subtlv_use_bw *)tlvh);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			sum += print_unknown_tlv(buf, indent, tlvh);
 | 
			
		||||
 | 
			
		||||
@ -309,7 +309,8 @@ struct mpls_te_circuit {
 | 
			
		||||
void isis_mpls_te_init(void);
 | 
			
		||||
struct mpls_te_circuit *mpls_te_circuit_new(void);
 | 
			
		||||
struct sbuf;
 | 
			
		||||
void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs, uint8_t subtlv_len);
 | 
			
		||||
void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs,
 | 
			
		||||
			  uint8_t subtlv_len);
 | 
			
		||||
void set_circuitparams_local_ipaddr(struct mpls_te_circuit *, struct in_addr);
 | 
			
		||||
void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *, struct in_addr);
 | 
			
		||||
uint8_t subtlvs_len(struct mpls_te_circuit *);
 | 
			
		||||
 | 
			
		||||
@ -161,9 +161,11 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context,
 | 
			
		||||
	sbuf_push(log, indent, "Unpacking IPv6 Source Prefix Sub-TLV...\n");
 | 
			
		||||
 | 
			
		||||
	if (tlv_len < 1) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Not enough data left. (expected 1 or more bytes, got %" PRIu8 ")\n",
 | 
			
		||||
			  tlv_len);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Not enough data left. (expected 1 or more bytes, got %" PRIu8
 | 
			
		||||
			")\n",
 | 
			
		||||
			tlv_len);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -496,8 +498,9 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
{
 | 
			
		||||
	struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "LSP Entry: %s, seq 0x%08" PRIx32
 | 
			
		||||
		  ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 "s\n",
 | 
			
		||||
	sbuf_push(buf, indent,
 | 
			
		||||
		  "LSP Entry: %s, seq 0x%08" PRIx32 ", cksum 0x%04" PRIx16
 | 
			
		||||
		  ", lifetime %" PRIu16 "s\n",
 | 
			
		||||
		  isis_format_id(e->id, 8), e->seqno, e->checksum,
 | 
			
		||||
		  e->rem_lifetime);
 | 
			
		||||
}
 | 
			
		||||
@ -579,7 +582,8 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
	sbuf_push(buf, 0, "\n");
 | 
			
		||||
 | 
			
		||||
	if (r->subtlv_len && r->subtlvs)
 | 
			
		||||
		mpls_te_print_detail(buf, indent + 2, r->subtlvs, r->subtlv_len);
 | 
			
		||||
		mpls_te_print_detail(buf, indent + 2, r->subtlvs,
 | 
			
		||||
				     r->subtlv_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_item_extended_reach(struct isis_item *i)
 | 
			
		||||
@ -621,10 +625,11 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
 | 
			
		||||
		  (mtid == ISIS_MT_IPV4_UNICAST) ? "extended" : "mt");
 | 
			
		||||
 | 
			
		||||
	if (len < 11) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Not enough data left. (expected 11 or more bytes, got %"
 | 
			
		||||
			  PRIu8 ")\n",
 | 
			
		||||
			  len);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Not enough data left. (expected 11 or more bytes, got %" PRIu8
 | 
			
		||||
			")\n",
 | 
			
		||||
			len);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -690,7 +695,8 @@ static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
	char prefixbuf[PREFIX2STR_BUFFER];
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "IP Reachability: %s (Metric: %" PRIu8 ")\n",
 | 
			
		||||
		  prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric);
 | 
			
		||||
		  prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
 | 
			
		||||
		  r->metric);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_item_oldstyle_ip_reach(struct isis_item *i)
 | 
			
		||||
@ -971,8 +977,7 @@ static void format_item_mt_router_info(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
	struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
 | 
			
		||||
		  isis_mtid2str(info->mtid),
 | 
			
		||||
		  info->overload ? " Overload" : "",
 | 
			
		||||
		  isis_mtid2str(info->mtid), info->overload ? " Overload" : "",
 | 
			
		||||
		  info->attached ? " Attached" : "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1121,8 +1126,8 @@ static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
 | 
			
		||||
	sbuf_push(buf, indent, "%s IP Reachability: %s (Metric: %u)%s",
 | 
			
		||||
		  (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
 | 
			
		||||
		  prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric,
 | 
			
		||||
		  r->down ? " Down" : "");
 | 
			
		||||
		  prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
 | 
			
		||||
		  r->metric, r->down ? " Down" : "");
 | 
			
		||||
	if (mtid != ISIS_MT_IPV4_UNICAST)
 | 
			
		||||
		sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
 | 
			
		||||
	sbuf_push(buf, 0, "\n");
 | 
			
		||||
@ -1175,9 +1180,11 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
 | 
			
		||||
 | 
			
		||||
	consume = 5;
 | 
			
		||||
	if (len < consume) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Not enough data left. (expected 5 or more bytes, got %" PRIu8 ")\n",
 | 
			
		||||
			  len);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Not enough data left. (expected 5 or more bytes, got %" PRIu8
 | 
			
		||||
			")\n",
 | 
			
		||||
			len);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1196,9 +1203,10 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
 | 
			
		||||
 | 
			
		||||
	consume += PSIZE(rv->prefix.prefixlen);
 | 
			
		||||
	if (len < consume) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Expected %u bytes of prefix, but only %u bytes available.\n",
 | 
			
		||||
			  PSIZE(rv->prefix.prefixlen), len - 5);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Expected %u bytes of prefix, but only %u bytes available.\n",
 | 
			
		||||
			PSIZE(rv->prefix.prefixlen), len - 5);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	stream_get(&rv->prefix.prefix.s_addr, s, PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
@ -1213,23 +1221,26 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
 | 
			
		||||
	if (control & ISIS_EXTENDED_IP_REACH_SUBTLV) {
 | 
			
		||||
		consume += 1;
 | 
			
		||||
		if (len < consume) {
 | 
			
		||||
			sbuf_push(log, indent,
 | 
			
		||||
				  "Expected 1 byte of subtlv len, but no more data present.\n");
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent,
 | 
			
		||||
				"Expected 1 byte of subtlv len, but no more data present.\n");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		subtlv_len = stream_getc(s);
 | 
			
		||||
 | 
			
		||||
		if (!subtlv_len) {
 | 
			
		||||
			sbuf_push(log, indent + 2,
 | 
			
		||||
				  "  WARNING: subtlv bit is set, but there are no subtlvs.\n");
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent + 2,
 | 
			
		||||
				"  WARNING: subtlv bit is set, but there are no subtlvs.\n");
 | 
			
		||||
		}
 | 
			
		||||
		consume += subtlv_len;
 | 
			
		||||
		if (len < consume) {
 | 
			
		||||
			sbuf_push(log, indent,
 | 
			
		||||
				  "Expected %" PRIu8
 | 
			
		||||
				  " bytes of subtlvs, but only %u bytes available.\n",
 | 
			
		||||
				  subtlv_len,
 | 
			
		||||
				  len - 6 - PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent,
 | 
			
		||||
				"Expected %" PRIu8
 | 
			
		||||
				" bytes of subtlvs, but only %u bytes available.\n",
 | 
			
		||||
				subtlv_len,
 | 
			
		||||
				len - 6 - PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		sbuf_push(log, indent, "Skipping %" PRIu8 " bytes of subvls",
 | 
			
		||||
@ -1350,8 +1361,7 @@ static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
 | 
			
		||||
	sbuf_push(buf, indent, "%sIPv6 Reachability: %s (Metric: %u)%s%s",
 | 
			
		||||
		  (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "MT ",
 | 
			
		||||
		  prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
 | 
			
		||||
		  r->metric,
 | 
			
		||||
		  r->down ? " Down" : "",
 | 
			
		||||
		  r->metric, r->down ? " Down" : "",
 | 
			
		||||
		  r->external ? " External" : "");
 | 
			
		||||
	if (mtid != ISIS_MT_IPV4_UNICAST)
 | 
			
		||||
		sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
 | 
			
		||||
@ -1416,10 +1426,11 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
 | 
			
		||||
		  (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "mt ");
 | 
			
		||||
	consume = 6;
 | 
			
		||||
	if (len < consume) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Not enough data left. (expected 6 or more bytes, got %"
 | 
			
		||||
			  PRIu8 ")\n",
 | 
			
		||||
			  len);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Not enough data left. (expected 6 or more bytes, got %" PRIu8
 | 
			
		||||
			")\n",
 | 
			
		||||
			len);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -1440,9 +1451,10 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
 | 
			
		||||
 | 
			
		||||
	consume += PSIZE(rv->prefix.prefixlen);
 | 
			
		||||
	if (len < consume) {
 | 
			
		||||
		sbuf_push(log, indent,
 | 
			
		||||
			  "Expected %u bytes of prefix, but only %u bytes available.\n",
 | 
			
		||||
			  PSIZE(rv->prefix.prefixlen), len - 6);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent,
 | 
			
		||||
			"Expected %u bytes of prefix, but only %u bytes available.\n",
 | 
			
		||||
			PSIZE(rv->prefix.prefixlen), len - 6);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
	stream_get(&rv->prefix.prefix.s6_addr, s, PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
@ -1456,23 +1468,26 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
 | 
			
		||||
	if (control & ISIS_IPV6_REACH_SUBTLV) {
 | 
			
		||||
		consume += 1;
 | 
			
		||||
		if (len < consume) {
 | 
			
		||||
			sbuf_push(log, indent,
 | 
			
		||||
				  "Expected 1 byte of subtlv len, but no more data persent.\n");
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent,
 | 
			
		||||
				"Expected 1 byte of subtlv len, but no more data persent.\n");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		subtlv_len = stream_getc(s);
 | 
			
		||||
 | 
			
		||||
		if (!subtlv_len) {
 | 
			
		||||
			sbuf_push(log, indent + 2,
 | 
			
		||||
				  "  WARNING: subtlv bit set, but there are no subtlvs.\n");
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent + 2,
 | 
			
		||||
				"  WARNING: subtlv bit set, but there are no subtlvs.\n");
 | 
			
		||||
		}
 | 
			
		||||
		consume += subtlv_len;
 | 
			
		||||
		if (len < consume) {
 | 
			
		||||
			sbuf_push(log, indent,
 | 
			
		||||
				  "Expected %" PRIu8
 | 
			
		||||
				  " bytes of subtlvs, but only %u bytes available.\n",
 | 
			
		||||
				  subtlv_len,
 | 
			
		||||
				  len - 6 - PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
			sbuf_push(
 | 
			
		||||
				log, indent,
 | 
			
		||||
				"Expected %" PRIu8
 | 
			
		||||
				" bytes of subtlvs, but only %u bytes available.\n",
 | 
			
		||||
				subtlv_len,
 | 
			
		||||
				len - 6 - PSIZE(rv->prefix.prefixlen));
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -1695,16 +1710,19 @@ static int pack_item(enum isis_tlv_context context, enum isis_tlv_type type,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_item_to_fragment(struct isis_item *i, struct pack_order_entry *pe,
 | 
			
		||||
static void add_item_to_fragment(struct isis_item *i,
 | 
			
		||||
				 struct pack_order_entry *pe,
 | 
			
		||||
				 struct isis_tlvs *fragment_tlvs, uint16_t mtid)
 | 
			
		||||
{
 | 
			
		||||
	struct isis_item_list *l;
 | 
			
		||||
 | 
			
		||||
	if (pe->how_to_pack == ISIS_ITEMS) {
 | 
			
		||||
		l = (struct isis_item_list *)(((char *)fragment_tlvs) + pe->what_to_pack);
 | 
			
		||||
		l = (struct isis_item_list *)(((char *)fragment_tlvs)
 | 
			
		||||
					      + pe->what_to_pack);
 | 
			
		||||
	} else {
 | 
			
		||||
		struct isis_mt_item_list *m;
 | 
			
		||||
		m = (struct isis_mt_item_list *)(((char *)fragment_tlvs) + pe->what_to_pack);
 | 
			
		||||
		m = (struct isis_mt_item_list *)(((char *)fragment_tlvs)
 | 
			
		||||
						 + pe->what_to_pack);
 | 
			
		||||
		l = isis_get_mt_items(m, mtid);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -2284,8 +2302,9 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
 | 
			
		||||
	/* When fragmenting, don't add auth as it's already accounted for in the
 | 
			
		||||
	 * size we are given. */
 | 
			
		||||
	if (!fragment_tlvs) {
 | 
			
		||||
		rv = pack_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth,
 | 
			
		||||
				stream, NULL, NULL, NULL, NULL);
 | 
			
		||||
		rv = pack_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH,
 | 
			
		||||
				&tlvs->isis_auth, stream, NULL, NULL, NULL,
 | 
			
		||||
				NULL);
 | 
			
		||||
		if (rv)
 | 
			
		||||
			return rv;
 | 
			
		||||
	}
 | 
			
		||||
@ -2440,9 +2459,11 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
 | 
			
		||||
		  tlv_type, tlv_len);
 | 
			
		||||
 | 
			
		||||
	if (avail_len < ((size_t)tlv_len) + 2) {
 | 
			
		||||
		sbuf_push(log, indent + 2,
 | 
			
		||||
			  "Available data %zu too short for claimed TLV len %" PRIu8 ".\n",
 | 
			
		||||
			  avail_len - 2, tlv_len);
 | 
			
		||||
		sbuf_push(
 | 
			
		||||
			log, indent + 2,
 | 
			
		||||
			"Available data %zu too short for claimed TLV len %" PRIu8
 | 
			
		||||
			".\n",
 | 
			
		||||
			avail_len - 2, tlv_len);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -2520,7 +2541,7 @@ int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
 | 
			
		||||
	static const struct tlv_ops tlv_##_name_##_ops = {                     \
 | 
			
		||||
		.name = _desc_,                                                \
 | 
			
		||||
		.unpack = unpack_tlv_with_items,                               \
 | 
			
		||||
									       \
 | 
			
		||||
                                                                               \
 | 
			
		||||
		.pack_item = pack_item_##_name_,                               \
 | 
			
		||||
		.free_item = free_item_##_name_,                               \
 | 
			
		||||
		.unpack_item = unpack_item_##_name_,                           \
 | 
			
		||||
@ -2550,34 +2571,49 @@ ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
 | 
			
		||||
 | 
			
		||||
SUBTLV_OPS(ipv6_source_prefix, "Sub-TLV 22 IPv6 Source Prefix");
 | 
			
		||||
 | 
			
		||||
static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
 | 
			
		||||
	[ISIS_CONTEXT_LSP] = {
 | 
			
		||||
		[ISIS_TLV_AREA_ADDRESSES] = &tlv_area_address_ops,
 | 
			
		||||
		[ISIS_TLV_OLDSTYLE_REACH] = &tlv_oldstyle_reach_ops,
 | 
			
		||||
		[ISIS_TLV_LAN_NEIGHBORS] = &tlv_lan_neighbor_ops,
 | 
			
		||||
		[ISIS_TLV_LSP_ENTRY] = &tlv_lsp_entry_ops,
 | 
			
		||||
		[ISIS_TLV_AUTH] = &tlv_auth_ops,
 | 
			
		||||
		[ISIS_TLV_EXTENDED_REACH] = &tlv_extended_reach_ops,
 | 
			
		||||
		[ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
 | 
			
		||||
		[ISIS_TLV_OLDSTYLE_IP_REACH] = &tlv_oldstyle_ip_reach_ops,
 | 
			
		||||
		[ISIS_TLV_PROTOCOLS_SUPPORTED] = &tlv_protocols_supported_ops,
 | 
			
		||||
		[ISIS_TLV_OLDSTYLE_IP_REACH_EXT] = &tlv_oldstyle_ip_reach_ops,
 | 
			
		||||
		[ISIS_TLV_IPV4_ADDRESS] = &tlv_ipv4_address_ops,
 | 
			
		||||
		[ISIS_TLV_TE_ROUTER_ID] = &tlv_te_router_id_ops,
 | 
			
		||||
		[ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
 | 
			
		||||
		[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
 | 
			
		||||
		[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
 | 
			
		||||
		[ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
 | 
			
		||||
		[ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
 | 
			
		||||
		[ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
 | 
			
		||||
		[ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
 | 
			
		||||
	},
 | 
			
		||||
	[ISIS_CONTEXT_SUBTLV_NE_REACH] = {},
 | 
			
		||||
	[ISIS_CONTEXT_SUBTLV_IP_REACH] = {},
 | 
			
		||||
	[ISIS_CONTEXT_SUBTLV_IPV6_REACH] = {
 | 
			
		||||
		[ISIS_SUBTLV_IPV6_SOURCE_PREFIX] = &subtlv_ipv6_source_prefix_ops,
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] =
 | 
			
		||||
	{[ISIS_CONTEXT_LSP] =
 | 
			
		||||
		 {
 | 
			
		||||
				 [ISIS_TLV_AREA_ADDRESSES] =
 | 
			
		||||
					 &tlv_area_address_ops,
 | 
			
		||||
				 [ISIS_TLV_OLDSTYLE_REACH] =
 | 
			
		||||
					 &tlv_oldstyle_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_LAN_NEIGHBORS] =
 | 
			
		||||
					 &tlv_lan_neighbor_ops,
 | 
			
		||||
				 [ISIS_TLV_LSP_ENTRY] = &tlv_lsp_entry_ops,
 | 
			
		||||
				 [ISIS_TLV_AUTH] = &tlv_auth_ops,
 | 
			
		||||
				 [ISIS_TLV_EXTENDED_REACH] =
 | 
			
		||||
					 &tlv_extended_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_OLDSTYLE_IP_REACH] =
 | 
			
		||||
					 &tlv_oldstyle_ip_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_PROTOCOLS_SUPPORTED] =
 | 
			
		||||
					 &tlv_protocols_supported_ops,
 | 
			
		||||
				 [ISIS_TLV_OLDSTYLE_IP_REACH_EXT] =
 | 
			
		||||
					 &tlv_oldstyle_ip_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_IPV4_ADDRESS] =
 | 
			
		||||
					 &tlv_ipv4_address_ops,
 | 
			
		||||
				 [ISIS_TLV_TE_ROUTER_ID] =
 | 
			
		||||
					 &tlv_te_router_id_ops,
 | 
			
		||||
				 [ISIS_TLV_EXTENDED_IP_REACH] =
 | 
			
		||||
					 &tlv_extended_ip_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_MT_IP_REACH] =
 | 
			
		||||
					 &tlv_extended_ip_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_DYNAMIC_HOSTNAME] =
 | 
			
		||||
					 &tlv_dynamic_hostname_ops,
 | 
			
		||||
				 [ISIS_TLV_MT_ROUTER_INFO] =
 | 
			
		||||
					 &tlv_mt_router_info_ops,
 | 
			
		||||
				 [ISIS_TLV_IPV6_ADDRESS] =
 | 
			
		||||
					 &tlv_ipv6_address_ops,
 | 
			
		||||
				 [ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
 | 
			
		||||
				 [ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
 | 
			
		||||
		 },
 | 
			
		||||
	 [ISIS_CONTEXT_SUBTLV_NE_REACH] = {},
 | 
			
		||||
	 [ISIS_CONTEXT_SUBTLV_IP_REACH] = {},
 | 
			
		||||
	 [ISIS_CONTEXT_SUBTLV_IPV6_REACH] = {
 | 
			
		||||
			 [ISIS_SUBTLV_IPV6_SOURCE_PREFIX] =
 | 
			
		||||
				 &subtlv_ipv6_source_prefix_ops,
 | 
			
		||||
	 }};
 | 
			
		||||
 | 
			
		||||
/* Accessor functions */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -764,7 +764,7 @@ DEFUN_NOSH (show_debugging,
 | 
			
		||||
	    "State of each debugging option\n"
 | 
			
		||||
	    ISIS_STR)
 | 
			
		||||
{
 | 
			
		||||
	vty_out (vty, "IS-IS debugging status:\n");
 | 
			
		||||
	vty_out(vty, "IS-IS debugging status:\n");
 | 
			
		||||
 | 
			
		||||
	if (isis->debugs)
 | 
			
		||||
		print_debug(vty, isis->debugs, 1);
 | 
			
		||||
 | 
			
		||||
@ -52,8 +52,9 @@ struct isis {
 | 
			
		||||
	struct area_addr *man_area_addrs; /* manualAreaAddresses */
 | 
			
		||||
	u_int32_t debugs;		  /* bitmap for debug */
 | 
			
		||||
	time_t uptime;			  /* when did we start */
 | 
			
		||||
	struct thread *t_dync_clean;      /* dynamic hostname cache cleanup thread */
 | 
			
		||||
	uint32_t circuit_ids_used[8];     /* 256 bits to track circuit ids 0 through 255 */
 | 
			
		||||
	struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */
 | 
			
		||||
	uint32_t circuit_ids_used
 | 
			
		||||
		[8]; /* 256 bits to track circuit ids 0 through 255 */
 | 
			
		||||
 | 
			
		||||
	struct route_table *ext_info[REDIST_PROTOCOL_COUNT];
 | 
			
		||||
 | 
			
		||||
@ -70,8 +71,6 @@ struct isis_area {
 | 
			
		||||
	struct route_table *route_table[ISIS_LEVELS];  /* IPv4 routes */
 | 
			
		||||
	struct isis_spftree *spftree6[ISIS_LEVELS];    /* The v6 SPTs */
 | 
			
		||||
	struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */
 | 
			
		||||
						       /* $FRR indent$ */
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
#define DEFAULT_LSP_MTU 1497
 | 
			
		||||
	unsigned int lsp_mtu;      /* Size of LSPs to generate */
 | 
			
		||||
	struct list *circuit_list; /* IS-IS circuits */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								ldpd/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								ldpd/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -15,4 +15,3 @@ TAGS
 | 
			
		||||
.arch-ids
 | 
			
		||||
*~
 | 
			
		||||
*.loT
 | 
			
		||||
ldp_vty_cmds_clippy.c
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								lib/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								lib/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -24,4 +24,3 @@ refix
 | 
			
		||||
grammar_sandbox
 | 
			
		||||
clippy
 | 
			
		||||
defun_lex.c
 | 
			
		||||
plist_clippy.c
 | 
			
		||||
 | 
			
		||||
@ -62,9 +62,10 @@ const char *node_names[] = {
 | 
			
		||||
	"aaa",			    // AAA_NODE,
 | 
			
		||||
	"keychain",		    // KEYCHAIN_NODE,
 | 
			
		||||
	"keychain key",		    // KEYCHAIN_KEY_NODE,
 | 
			
		||||
	"logical-router",	    // LOGICALROUTER_NODE,
 | 
			
		||||
	"logical-router",	   // LOGICALROUTER_NODE,
 | 
			
		||||
	"vrf",			    // VRF_NODE,
 | 
			
		||||
	"interface",		    // INTERFACE_NODE,
 | 
			
		||||
	"nexthop-group",            // NH_GROUP_NODE,
 | 
			
		||||
	"zebra",		    // ZEBRA_NODE,
 | 
			
		||||
	"table",		    // TABLE_NODE,
 | 
			
		||||
	"rip",			    // RIP_NODE,
 | 
			
		||||
@ -74,14 +75,14 @@ const char *node_names[] = {
 | 
			
		||||
	"bgp",			    // BGP_NODE,
 | 
			
		||||
	"bgp vpnv4",		    // BGP_VPNV4_NODE,
 | 
			
		||||
	"bgp vpnv6",		    // BGP_VPNV6_NODE,
 | 
			
		||||
	"bgp ipv4 unicast",         // BGP_IPV4_NODE,
 | 
			
		||||
	"bgp ipv4 unicast",	 // BGP_IPV4_NODE,
 | 
			
		||||
	"bgp ipv4 multicast",       // BGP_IPV4M_NODE,
 | 
			
		||||
	"bgp ipv4 labeled unicast", // BGP_IPV4L_NODE,
 | 
			
		||||
	"bgp ipv6",		    // BGP_IPV6_NODE,
 | 
			
		||||
	"bgp ipv6 multicast",       // BGP_IPV6M_NODE,
 | 
			
		||||
	"bgp ipv6 labeled unicast", // BGP_IPV6L_NODE,
 | 
			
		||||
	"bgp vrf policy",	    // BGP_VRF_POLICY_NODE,
 | 
			
		||||
	"bgp vnc defaults",         // BGP_VNC_DEFAULTS_NODE,
 | 
			
		||||
	"bgp vrf policy",	   // BGP_VRF_POLICY_NODE,
 | 
			
		||||
	"bgp vnc defaults",	 // BGP_VNC_DEFAULTS_NODE,
 | 
			
		||||
	"bgp vnc nve",		    // BGP_VNC_NVE_GROUP_NODE,
 | 
			
		||||
	"bgp vnc l2",		    // BGP_VNC_L2_GROUP_NODE,
 | 
			
		||||
	"rfp defaults",		    // RFP_DEFAULTS_NODE,
 | 
			
		||||
@ -99,13 +100,13 @@ const char *node_names[] = {
 | 
			
		||||
	"masc",			    // MASC_NODE,
 | 
			
		||||
	"irdp",			    // IRDP_NODE,
 | 
			
		||||
	"static ip",		    // IP_NODE,
 | 
			
		||||
	"ipv4 access list",         // ACCESS_NODE,
 | 
			
		||||
	"ipv4 prefix list",         // PREFIX_NODE,
 | 
			
		||||
	"ipv6 access list",         // ACCESS_IPV6_NODE,
 | 
			
		||||
	"MAC access list",          // ACCESS_MAC_NODE,
 | 
			
		||||
	"ipv6 prefix list",         // PREFIX_IPV6_NODE,
 | 
			
		||||
	"ipv4 access list",	 // ACCESS_NODE,
 | 
			
		||||
	"ipv4 prefix list",	 // PREFIX_NODE,
 | 
			
		||||
	"ipv6 access list",	 // ACCESS_IPV6_NODE,
 | 
			
		||||
	"MAC access list",	  // ACCESS_MAC_NODE,
 | 
			
		||||
	"ipv6 prefix list",	 // PREFIX_IPV6_NODE,
 | 
			
		||||
	"as list",		    // AS_LIST_NODE,
 | 
			
		||||
	"community list",	    // COMMUNITY_LIST_NODE,
 | 
			
		||||
	"community list",	   // COMMUNITY_LIST_NODE,
 | 
			
		||||
	"routemap",		    // RMAP_NODE,
 | 
			
		||||
	"smux",			    // SMUX_NODE,
 | 
			
		||||
	"dump",			    // DUMP_NODE,
 | 
			
		||||
@ -301,8 +302,7 @@ void install_node(struct cmd_node *node, int (*func)(struct vty *))
 | 
			
		||||
		cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
 | 
			
		||||
	graph_new_node(node->cmdgraph, token,
 | 
			
		||||
		       (void (*)(void *)) & cmd_token_del);
 | 
			
		||||
	node->cmd_hash = hash_create_size(16, cmd_hash_key,
 | 
			
		||||
					  cmd_hash_cmp,
 | 
			
		||||
	node->cmd_hash = hash_create_size(16, cmd_hash_key, cmd_hash_cmp,
 | 
			
		||||
					  "Command Hash");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -500,6 +500,9 @@ static int config_write_host(struct vty *vty)
 | 
			
		||||
	if (cmd_hostname_get())
 | 
			
		||||
		vty_out(vty, "hostname %s\n", cmd_hostname_get());
 | 
			
		||||
 | 
			
		||||
	if (cmd_domainname_get())
 | 
			
		||||
		vty_out(vty, "domainname %s\n", cmd_domainname_get());
 | 
			
		||||
 | 
			
		||||
	if (host.encrypt) {
 | 
			
		||||
		if (host.password_encrypt)
 | 
			
		||||
			vty_out(vty, "password 8 %s\n", host.password_encrypt);
 | 
			
		||||
@ -1167,8 +1170,7 @@ int command_config_read_one_line(struct vty *vty,
 | 
			
		||||
	if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
 | 
			
		||||
	    && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
 | 
			
		||||
	    && ret != CMD_SUCCESS && ret != CMD_WARNING
 | 
			
		||||
	    && ret != CMD_NOT_MY_INSTANCE
 | 
			
		||||
	    && ret != CMD_WARNING_CONFIG_FAILED
 | 
			
		||||
	    && ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
 | 
			
		||||
	    && vty->node != CONFIG_NODE) {
 | 
			
		||||
 | 
			
		||||
		saved_node = vty->node;
 | 
			
		||||
@ -1293,6 +1295,7 @@ void cmd_exit(struct vty *vty)
 | 
			
		||||
	case PW_NODE:
 | 
			
		||||
	case LOGICALROUTER_NODE:
 | 
			
		||||
	case VRF_NODE:
 | 
			
		||||
	case NH_GROUP_NODE:
 | 
			
		||||
	case ZEBRA_NODE:
 | 
			
		||||
	case BGP_NODE:
 | 
			
		||||
	case RIP_NODE:
 | 
			
		||||
@ -1378,6 +1381,7 @@ DEFUN (config_end,
 | 
			
		||||
	case PW_NODE:
 | 
			
		||||
	case LOGICALROUTER_NODE:
 | 
			
		||||
	case VRF_NODE:
 | 
			
		||||
	case NH_GROUP_NODE:
 | 
			
		||||
	case ZEBRA_NODE:
 | 
			
		||||
	case RIP_NODE:
 | 
			
		||||
	case RIPNG_NODE:
 | 
			
		||||
 | 
			
		||||
@ -85,9 +85,10 @@ enum node_type {
 | 
			
		||||
	AAA_NODE,		/* AAA node. */
 | 
			
		||||
	KEYCHAIN_NODE,		/* Key-chain node. */
 | 
			
		||||
	KEYCHAIN_KEY_NODE,      /* Key-chain key node. */
 | 
			
		||||
	LOGICALROUTER_NODE,	/* Logical-Router node. */
 | 
			
		||||
	LOGICALROUTER_NODE,     /* Logical-Router node. */
 | 
			
		||||
	VRF_NODE,		/* VRF mode node. */
 | 
			
		||||
	INTERFACE_NODE,		/* Interface mode node. */
 | 
			
		||||
	NH_GROUP_NODE,          /* Nexthop-Group mode node. */
 | 
			
		||||
	ZEBRA_NODE,		/* zebra connection node. */
 | 
			
		||||
	TABLE_NODE,		/* rtm_table selection node. */
 | 
			
		||||
	RIP_NODE,		/* RIP protocol mode node. */
 | 
			
		||||
@ -139,8 +140,9 @@ enum node_type {
 | 
			
		||||
	VTY_NODE,		/* Vty node. */
 | 
			
		||||
	LINK_PARAMS_NODE,       /* Link-parameters node */
 | 
			
		||||
	BGP_EVPN_VNI_NODE,      /* BGP EVPN VNI */
 | 
			
		||||
	RPKI_NODE,		/* RPKI node for configuration of RPKI cache server connections.*/
 | 
			
		||||
	NODE_TYPE_MAX,		/* maximum */
 | 
			
		||||
	RPKI_NODE,     /* RPKI node for configuration of RPKI cache server
 | 
			
		||||
			  connections.*/
 | 
			
		||||
	NODE_TYPE_MAX, /* maximum */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern vector cmdvec;
 | 
			
		||||
 | 
			
		||||
@ -21,25 +21,25 @@
 | 
			
		||||
 *   void prototype(void) __attribute__((_CONSTRUCTOR(100)));
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
 | 
			
		||||
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
 | 
			
		||||
#  define _RET_NONNULL    , returns_nonnull
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
# define _CONSTRUCTOR(x)  constructor(x)
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
 | 
			
		||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
 | 
			
		||||
#  define _RET_NONNULL    , returns_nonnull
 | 
			
		||||
# endif
 | 
			
		||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
 | 
			
		||||
#endif
 | 
			
		||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
 | 
			
		||||
#  define _CONSTRUCTOR(x) constructor(x)
 | 
			
		||||
#  define _DESTRUCTOR(x)  destructor(x)
 | 
			
		||||
#  define _ALLOC_SIZE(x)  alloc_size(x)
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __sun
 | 
			
		||||
/* Solaris doesn't do constructor priorities due to linker restrictions */
 | 
			
		||||
# undef _CONSTRUCTOR
 | 
			
		||||
# undef _DESTRUCTOR
 | 
			
		||||
#undef _CONSTRUCTOR
 | 
			
		||||
#undef _DESTRUCTOR
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* fallback versions */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								lib/debug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								lib/debug.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Debugging utilities.
 | 
			
		||||
 * Copyright (C) 2018  Cumulus Networks, Inc.
 | 
			
		||||
 * Quentin Young
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 of the License, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 "debug.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
 | 
			
		||||
static const struct debug_callbacks *callbacks;
 | 
			
		||||
 | 
			
		||||
/* All code in this section should be reentrant and MT-safe */
 | 
			
		||||
 | 
			
		||||
DEFUN_NOSH(debug_all, debug_all_cmd, "[no] debug all",
 | 
			
		||||
	   NO_STR DEBUG_STR "Toggle all debugging output\n")
 | 
			
		||||
{
 | 
			
		||||
	bool set = strmatch(argv[0]->text, "no");
 | 
			
		||||
	uint32_t mode = DEBUG_NODE2MODE(vty->node);
 | 
			
		||||
 | 
			
		||||
	if (callbacks->debug_set_all)
 | 
			
		||||
		callbacks->debug_set_all(mode, set);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
void debug_init(const struct debug_callbacks *cb)
 | 
			
		||||
{
 | 
			
		||||
	callbacks = cb;
 | 
			
		||||
	install_element(ENABLE_NODE, &debug_all_cmd);
 | 
			
		||||
	install_element(CONFIG_NODE, &debug_all_cmd);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										234
									
								
								lib/debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								lib/debug.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,234 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Debugging utilities.
 | 
			
		||||
 * Copyright (C) 2018  Cumulus Networks, Inc.
 | 
			
		||||
 * Quentin Young
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 of the License, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _FRRDEBUG_H
 | 
			
		||||
#define _FRRDEBUG_H
 | 
			
		||||
 | 
			
		||||
#include <zebra.h>
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "frratomic.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Debugging modes.
 | 
			
		||||
 *
 | 
			
		||||
 * FRR's convention is that a debug statement issued under the vty CONFIG_NODE
 | 
			
		||||
 * persists to the config file, whereas the same debug statement issued from
 | 
			
		||||
 * the ENABLE_NODE only persists for the current session. These are mapped to
 | 
			
		||||
 * DEBUG_MODE_CONF and DEBUG_MODE_TERM respectively.
 | 
			
		||||
 *
 | 
			
		||||
 * They are not mutually exclusive and are placed in the MSB of the flags
 | 
			
		||||
 * field in a debugging record.
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_MODE_TERM 0x01000000
 | 
			
		||||
#define DEBUG_MODE_CONF 0x02000000
 | 
			
		||||
#define DEBUG_MODE_ALL (DEBUG_MODE_TERM | DEBUG_MODE_CONF)
 | 
			
		||||
#define DEBUG_MODE_NONE 0x00000000
 | 
			
		||||
#define DEBUG_OPT_ALL 0x00FFFFFF
 | 
			
		||||
#define DEBUG_OPT_NONE 0x00000000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Debugging record.
 | 
			
		||||
 *
 | 
			
		||||
 * All operations on this record exposed in this header are MT-safe.
 | 
			
		||||
 *
 | 
			
		||||
 * flags
 | 
			
		||||
 *    A bitfield with the following format (bytes high to low)
 | 
			
		||||
 *    - [0] Debugging mode field (MSB)  | Mode
 | 
			
		||||
 *    - [1] Arbitrary flag field        | Option
 | 
			
		||||
 *    - [2] Arbitrary flag field        | Option
 | 
			
		||||
 *    - [3] Arbitrary flag field (LSB)  | Option
 | 
			
		||||
 *
 | 
			
		||||
 *              ALL THESE BYTES ARE YOURS - EXCEPT MODE.
 | 
			
		||||
 *                      ATTEMPT NO BIT OPS THERE.
 | 
			
		||||
 *
 | 
			
		||||
 *    The MSB of this field determines the debug mode, Use the DEBUG_MODE*
 | 
			
		||||
 *    macros to manipulate this byte.
 | 
			
		||||
 *
 | 
			
		||||
 *    The low 3 bytes of this field may be used to store arbitrary information.
 | 
			
		||||
 *    Usually they are used to store flags that tune how detailed the logging
 | 
			
		||||
 *    for a particular debug record is. Use the DEBUG_OPT* macros to manipulate
 | 
			
		||||
 *    those bytes.
 | 
			
		||||
 *
 | 
			
		||||
 *    All operations performed on this field should be done using the macros
 | 
			
		||||
 *    later in this header file. They are guaranteed to be atomic operations
 | 
			
		||||
 *    with respect to this field. Using anything except the macros to
 | 
			
		||||
 *    manipulate the flags field in a multithreaded environment results in
 | 
			
		||||
 *    undefined behavior.
 | 
			
		||||
 *
 | 
			
		||||
 * desc
 | 
			
		||||
 *    Human-readable description of this debugging record.
 | 
			
		||||
 */
 | 
			
		||||
struct debug {
 | 
			
		||||
	_Atomic uint32_t flags;
 | 
			
		||||
	const char *desc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Callback set for debugging code.
 | 
			
		||||
 *
 | 
			
		||||
 * debug_set_all
 | 
			
		||||
 *    Function pointer to call when the user requests that all debugs have a
 | 
			
		||||
 *    mode set.
 | 
			
		||||
 */
 | 
			
		||||
struct debug_callbacks {
 | 
			
		||||
	/*
 | 
			
		||||
	 * flags
 | 
			
		||||
	 *    flags to set on debug flag fields
 | 
			
		||||
	 *
 | 
			
		||||
	 * set
 | 
			
		||||
	 *    true: set flags
 | 
			
		||||
	 *    false: unset flags
 | 
			
		||||
	 */
 | 
			
		||||
	void (*debug_set_all)(uint32_t flags, bool set);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Check if a mode is set for a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_MODE_CHECK(name, mode)                                           \
 | 
			
		||||
	CHECK_FLAG_ATOMIC(&(name)->flags, (mode)&DEBUG_MODE_ALL)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Check if an option bit is set for a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_OPT_CHECK(name, opt)                                             \
 | 
			
		||||
	CHECK_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Check if bits are set for a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_FLAGS_CHECK(name, fl) CHECK_FLAG_ATOMIC(&(name)->flags, (fl))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set modes on a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_MODE_SET(name, mode, onoff)                                      \
 | 
			
		||||
	do {                                                                   \
 | 
			
		||||
		if (onoff)                                                     \
 | 
			
		||||
			SET_FLAG_ATOMIC(&(name)->flags,                        \
 | 
			
		||||
					(mode)&DEBUG_MODE_ALL);                \
 | 
			
		||||
		else                                                           \
 | 
			
		||||
			UNSET_FLAG_ATOMIC(&(name)->flags,                      \
 | 
			
		||||
					  (mode)&DEBUG_MODE_ALL);              \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/* Convenience macros for specific set operations. */
 | 
			
		||||
#define DEBUG_MODE_ON(name, mode) DEBUG_MODE_SET(name, mode, true)
 | 
			
		||||
#define DEBUG_MODE_OFF(name, mode) DEBUG_MODE_SET(name, mode, false)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set options on a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_OPT_SET(name, opt, onoff)                                        \
 | 
			
		||||
	do {                                                                   \
 | 
			
		||||
		if (onoff)                                                     \
 | 
			
		||||
			SET_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL);  \
 | 
			
		||||
		else                                                           \
 | 
			
		||||
			UNSET_FLAG_ATOMIC(&(name)->flags,                      \
 | 
			
		||||
					  (opt)&DEBUG_OPT_ALL);                \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/* Convenience macros for specific set operations. */
 | 
			
		||||
#define DEBUG_OPT_ON(name, opt) DEBUG_OPT_SET(name, opt, true)
 | 
			
		||||
#define DEBUG_OPT_OFF(name, opt) DEBUG_OPT_SET(name, opt, true)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set bits on a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_FLAGS_SET(name, fl, onoff)                                       \
 | 
			
		||||
	do {                                                                   \
 | 
			
		||||
		if (onoff)                                                     \
 | 
			
		||||
			SET_FLAG_ATOMIC(&(name)->flags, (fl));                 \
 | 
			
		||||
		else                                                           \
 | 
			
		||||
			UNSET_FLAG_ATOMIC(&(name)->flags, (fl));               \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/* Convenience macros for specific set operations. */
 | 
			
		||||
#define DEBUG_FLAGS_ON(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), true)
 | 
			
		||||
#define DEBUG_FLAGS_OFF(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), false)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unset all modes and options on a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_CLEAR(name) RESET_FLAG_ATOMIC(&(name)->flags)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set all modes and options on a debug.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_ON(name)                                                         \
 | 
			
		||||
	SET_FLAG_ATOMIC(&(name)->flags, DEBUG_MODE_ALL | DEBUG_OPT_ALL)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Map a vty node to the correct debugging mode flags. FRR behaves such that a
 | 
			
		||||
 * debug statement issued under the config node persists to the config file,
 | 
			
		||||
 * whereas the same debug statement issued from the enable node only persists
 | 
			
		||||
 * for the current session.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG_NODE2MODE(vtynode)                                               \
 | 
			
		||||
	(((vtynode) == CONFIG_NODE) ? DEBUG_MODE_ALL : DEBUG_MODE_TERM)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Debug at the given level to the default logging destination.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
#define DEBUG(level, name, fmt, ...)                                           \
 | 
			
		||||
	do {                                                                   \
 | 
			
		||||
		if (DEBUG_MODE_CHECK(name, DEBUG_MODE_ALL))                    \
 | 
			
		||||
			zlog_##level(fmt, ##__VA_ARGS__);                      \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/* Convenience macros for the various levels. */
 | 
			
		||||
#define DEBUGE(name, fmt, ...) DEBUG(err, name, fmt, ##__VA_ARGS__)
 | 
			
		||||
#define DEBUGW(name, fmt, ...) DEBUG(warn, name, fmt, ##__VA_ARGS__)
 | 
			
		||||
#define DEBUGI(name, fmt, ...) DEBUG(info, name, fmt, ##__VA_ARGS__)
 | 
			
		||||
#define DEBUGN(name, fmt, ...) DEBUG(notice, name, fmt, ##__VA_ARGS__)
 | 
			
		||||
#define DEBUGD(name, fmt, ...) DEBUG(debug, name, fmt, ##__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optional initializer for debugging. Highly recommended.
 | 
			
		||||
 *
 | 
			
		||||
 * This function installs common debugging commands and allows the caller to
 | 
			
		||||
 * specify callbacks to take when these commands are issued, allowing the
 | 
			
		||||
 * caller to respond to events such as a request to turn off all debugs.
 | 
			
		||||
 *
 | 
			
		||||
 * MT-Safe
 | 
			
		||||
 */
 | 
			
		||||
void debug_init(const struct debug_callbacks *cb);
 | 
			
		||||
 | 
			
		||||
#endif /* _FRRDEBUG_H */
 | 
			
		||||
							
								
								
									
										23
									
								
								lib/ferr.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								lib/ferr.c
									
									
									
									
									
								
							@ -63,8 +63,8 @@ ferr_r ferr_clear(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ferr_r ferr_set_va(const char *file, int line, const char *func,
 | 
			
		||||
		enum ferr_kind kind, const char *pathname, int errno_val,
 | 
			
		||||
		const char *text, va_list va)
 | 
			
		||||
			  enum ferr_kind kind, const char *pathname,
 | 
			
		||||
			  int errno_val, const char *text, va_list va)
 | 
			
		||||
{
 | 
			
		||||
	struct ferr *error = pthread_getspecific(errkey);
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,8 @@ static ferr_r ferr_set_va(const char *file, int line, const char *func,
 | 
			
		||||
			/* we're screwed */
 | 
			
		||||
			zlog_err("out of memory while allocating error info");
 | 
			
		||||
			raise(SIGSEGV);
 | 
			
		||||
			abort(); /* raise() can return, but raise(SIGSEGV) shall not */
 | 
			
		||||
			abort(); /* raise() can return, but raise(SIGSEGV) shall
 | 
			
		||||
				    not */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pthread_setspecific(errkey, error);
 | 
			
		||||
@ -86,12 +87,12 @@ static ferr_r ferr_set_va(const char *file, int line, const char *func,
 | 
			
		||||
	error->kind = kind;
 | 
			
		||||
 | 
			
		||||
	error->unique_id = jhash(text, strlen(text),
 | 
			
		||||
			jhash(file, strlen(file), 0xd4ed0298));
 | 
			
		||||
				 jhash(file, strlen(file), 0xd4ed0298));
 | 
			
		||||
 | 
			
		||||
	error->errno_val = errno_val;
 | 
			
		||||
	if (pathname)
 | 
			
		||||
		snprintf(error->pathname, sizeof(error->pathname),
 | 
			
		||||
				"%s", pathname);
 | 
			
		||||
		snprintf(error->pathname, sizeof(error->pathname), "%s",
 | 
			
		||||
			 pathname);
 | 
			
		||||
	else
 | 
			
		||||
		error->pathname[0] = '\0';
 | 
			
		||||
 | 
			
		||||
@ -100,7 +101,7 @@ static ferr_r ferr_set_va(const char *file, int line, const char *func,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ferr_r ferr_set_internal(const char *file, int line, const char *func,
 | 
			
		||||
		enum ferr_kind kind, const char *text, ...)
 | 
			
		||||
			 enum ferr_kind kind, const char *text, ...)
 | 
			
		||||
{
 | 
			
		||||
	ferr_r rv;
 | 
			
		||||
	va_list va;
 | 
			
		||||
@ -111,8 +112,8 @@ ferr_r ferr_set_internal(const char *file, int line, const char *func,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
 | 
			
		||||
		enum ferr_kind kind, const char *pathname, int errno_val,
 | 
			
		||||
		const char *text, ...)
 | 
			
		||||
			     enum ferr_kind kind, const char *pathname,
 | 
			
		||||
			     int errno_val, const char *text, ...)
 | 
			
		||||
{
 | 
			
		||||
	ferr_r rv;
 | 
			
		||||
	va_list va;
 | 
			
		||||
@ -139,10 +140,8 @@ void vty_print_error(struct vty *vty, ferr_r err, const char *msg, ...)
 | 
			
		||||
	else {
 | 
			
		||||
		replacepos[0] = '\0';
 | 
			
		||||
		replacepos += sizeof(REPLACE) - 1;
 | 
			
		||||
		vty_out(vty, "%s%s%s\n",
 | 
			
		||||
			tmpmsg,
 | 
			
		||||
		vty_out(vty, "%s%s%s\n", tmpmsg,
 | 
			
		||||
			last_error ? last_error->message : "(no error?)",
 | 
			
		||||
			replacepos);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								lib/ferr.h
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								lib/ferr.h
									
									
									
									
									
								
							@ -107,13 +107,12 @@ ferr_r ferr_clear(void);
 | 
			
		||||
 | 
			
		||||
/* do NOT call these functions directly.  only for macro use! */
 | 
			
		||||
ferr_r ferr_set_internal(const char *file, int line, const char *func,
 | 
			
		||||
		enum ferr_kind kind, const char *text, ...);
 | 
			
		||||
			 enum ferr_kind kind, const char *text, ...);
 | 
			
		||||
ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
 | 
			
		||||
		enum ferr_kind kind, const char *pathname, int errno_val,
 | 
			
		||||
		const char *text, ...);
 | 
			
		||||
			     enum ferr_kind kind, const char *pathname,
 | 
			
		||||
			     int errno_val, const char *text, ...);
 | 
			
		||||
 | 
			
		||||
#define ferr_ok() \
 | 
			
		||||
	0
 | 
			
		||||
#define ferr_ok() 0
 | 
			
		||||
 | 
			
		||||
/* Report an error.
 | 
			
		||||
 *
 | 
			
		||||
@ -122,58 +121,60 @@ ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
 | 
			
		||||
 *
 | 
			
		||||
 * Don't put a \n at the end of the error message.
 | 
			
		||||
 */
 | 
			
		||||
#define ferr_code_bug(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CODE_BUG, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_invalid(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_INVALID, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_reality(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_REALITY, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_resource(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_RESOURCE, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_system(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_SYSTEM, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_library(...) \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_LIBRARY, \
 | 
			
		||||
			__VA_ARGS__)
 | 
			
		||||
#define ferr_code_bug(...)                                                     \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CODE_BUG,         \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_invalid(...)                                                  \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_INVALID,   \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_reality(...)                                                  \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_REALITY,   \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
#define ferr_cfg_resource(...)                                                 \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_RESOURCE,         \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
#define ferr_system(...)                                                       \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_SYSTEM,           \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
#define ferr_library(...)                                                      \
 | 
			
		||||
	ferr_set_internal(__FILE__, __LINE__, __func__, FERR_LIBRARY,          \
 | 
			
		||||
			  __VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/* extended information variants */
 | 
			
		||||
#define ferr_system_errno(...) \
 | 
			
		||||
	ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, \
 | 
			
		||||
			NULL, errno, __VA_ARGS__)
 | 
			
		||||
#define ferr_system_path_errno(path, ...) \
 | 
			
		||||
	ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, \
 | 
			
		||||
			path, errno, __VA_ARGS__)
 | 
			
		||||
#define ferr_system_errno(...)                                                 \
 | 
			
		||||
	ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, NULL, \
 | 
			
		||||
			      errno, __VA_ARGS__)
 | 
			
		||||
#define ferr_system_path_errno(path, ...)                                      \
 | 
			
		||||
	ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, path, \
 | 
			
		||||
			      errno, __VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#include "vty.h"
 | 
			
		||||
/* print error message to vty;  $ERR is replaced by the error's message */
 | 
			
		||||
void vty_print_error(struct vty *vty, ferr_r err, const char *msg, ...);
 | 
			
		||||
 | 
			
		||||
#define CMD_FERR_DO(func, action, ...) \
 | 
			
		||||
	do { ferr_r cmd_retval = func; \
 | 
			
		||||
		if (cmd_retval) { \
 | 
			
		||||
			vty_print_error(vty, cmd_retval, __VA_ARGS__); \
 | 
			
		||||
			action; \
 | 
			
		||||
		} \
 | 
			
		||||
#define CMD_FERR_DO(func, action, ...)                                         \
 | 
			
		||||
	do {                                                                   \
 | 
			
		||||
		ferr_r cmd_retval = func;                                      \
 | 
			
		||||
		if (cmd_retval) {                                              \
 | 
			
		||||
			vty_print_error(vty, cmd_retval, __VA_ARGS__);         \
 | 
			
		||||
			action;                                                \
 | 
			
		||||
		}                                                              \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#define CMD_FERR_RETURN(func, ...) \
 | 
			
		||||
#define CMD_FERR_RETURN(func, ...)                                             \
 | 
			
		||||
	CMD_FERR_DO(func, return CMD_WARNING_CONFIG_FAILED, __VA_ARGS__)
 | 
			
		||||
#define CMD_FERR_GOTO(func, label, ...) \
 | 
			
		||||
#define CMD_FERR_GOTO(func, label, ...)                                        \
 | 
			
		||||
	CMD_FERR_DO(func, goto label, __VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
/* example:
 | 
			
		||||
 | 
			
		||||
/* example: uses bogus #define to keep indent.py happy */
 | 
			
		||||
#ifdef THIS_IS_AN_EXAMPLE
 | 
			
		||||
ferr_r foo_bar_set(struct object *obj, int bar)
 | 
			
		||||
{
 | 
			
		||||
	if (bar < 1 || bar >= 100)
 | 
			
		||||
		return ferr_config_invalid("bar setting (%d) must be 0<x<100", bar);
 | 
			
		||||
		return ferr_config_invalid("bar setting (%d) must be 0<x<100",
 | 
			
		||||
					   bar);
 | 
			
		||||
	obj->bar = bar;
 | 
			
		||||
	if (ioctl (obj->fd, bar))
 | 
			
		||||
	if (ioctl(obj->fd, bar))
 | 
			
		||||
		return ferr_system_errno("couldn't set bar to %d", bar);
 | 
			
		||||
 | 
			
		||||
	return ferr_ok();
 | 
			
		||||
@ -182,10 +183,10 @@ ferr_r foo_bar_set(struct object *obj, int bar)
 | 
			
		||||
DEFUN("bla")
 | 
			
		||||
{
 | 
			
		||||
	CMD_FERR_RETURN(foo_bar_set(obj, atoi(argv[1])),
 | 
			
		||||
		"command failed: $ERR\n");
 | 
			
		||||
			"command failed: $ERR\n");
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
#endif /* THIS_IS_AN_EXAMPLE */
 | 
			
		||||
 | 
			
		||||
#endif /* _FERR_H */
 | 
			
		||||
 | 
			
		||||
@ -302,8 +302,7 @@ struct qm_trace {
 | 
			
		||||
	(STAILQ_EMPTY((head))                                                  \
 | 
			
		||||
		 ? NULL                                                        \
 | 
			
		||||
		 : ((struct type *)(void *)((char *)((head)->stqh_last)        \
 | 
			
		||||
					    - offsetof(struct type,            \
 | 
			
		||||
							 field))))
 | 
			
		||||
					    - offsetof(struct type, field))))
 | 
			
		||||
 | 
			
		||||
#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,8 @@
 | 
			
		||||
#define atomic_exchange_explicit __atomic_exchange_n
 | 
			
		||||
#define atomic_fetch_add_explicit __atomic_fetch_add
 | 
			
		||||
#define atomic_fetch_sub_explicit __atomic_fetch_sub
 | 
			
		||||
#define atomic_fetch_and_explicit __atomic_fetch_and
 | 
			
		||||
#define atomic_fetch_or_explicit __atomic_fetch_or
 | 
			
		||||
 | 
			
		||||
#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1,      \
 | 
			
		||||
					      mem2)                            \
 | 
			
		||||
@ -135,6 +137,20 @@
 | 
			
		||||
		*_expect = rval;                                               \
 | 
			
		||||
		ret;                                                           \
 | 
			
		||||
	})
 | 
			
		||||
#define atomic_fetch_and_explicit(ptr, val, mem)                               \
 | 
			
		||||
	({                                                                     \
 | 
			
		||||
		__sync_synchronize();                                          \
 | 
			
		||||
		typeof(*ptr) rval = __sync_fetch_and_and(ptr, val);            \
 | 
			
		||||
		__sync_synchronize();                                          \
 | 
			
		||||
		rval;                                                          \
 | 
			
		||||
	})
 | 
			
		||||
#define atomic_fetch_or_explicit(ptr, val, mem)                                \
 | 
			
		||||
	({                                                                     \
 | 
			
		||||
		__sync_synchronize();                                          \
 | 
			
		||||
		typeof(*ptr) rval = __sync_fetch_and_or(ptr, val);             \
 | 
			
		||||
		__sync_synchronize();                                          \
 | 
			
		||||
		rval;                                                          \
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */
 | 
			
		||||
#error no atomic functions...
 | 
			
		||||
 | 
			
		||||
@ -402,8 +402,8 @@ DEFUN (grammar_findambig,
 | 
			
		||||
			nodegraph = cnode->cmdgraph;
 | 
			
		||||
			if (!nodegraph)
 | 
			
		||||
				continue;
 | 
			
		||||
			vty_out(vty, "scanning node %d (%s)\n",
 | 
			
		||||
				scannode - 1, node_names[scannode - 1]);
 | 
			
		||||
			vty_out(vty, "scanning node %d (%s)\n", scannode - 1,
 | 
			
		||||
				node_names[scannode - 1]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		commands = cmd_graph_permutations(nodegraph);
 | 
			
		||||
 | 
			
		||||
@ -38,9 +38,8 @@ void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
 | 
			
		||||
	he->priority = priority;
 | 
			
		||||
 | 
			
		||||
	for (pos = &hook->entries; *pos; pos = &(*pos)->next)
 | 
			
		||||
		if (hook->reverse
 | 
			
		||||
		    ? (*pos)->priority < priority
 | 
			
		||||
		    : (*pos)->priority >= priority)
 | 
			
		||||
		if (hook->reverse ? (*pos)->priority < priority
 | 
			
		||||
				  : (*pos)->priority >= priority)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
	he->next = *pos;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/hook.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								lib/hook.h
									
									
									
									
									
								
							@ -150,8 +150,8 @@ extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
 | 
			
		||||
		       NULL, false, THIS_MODULE, #func, prio)
 | 
			
		||||
#define hook_register_arg_prio(hookname, prio, func, arg)                      \
 | 
			
		||||
	_hook_register(&_hook_##hookname,                                      \
 | 
			
		||||
		       _hook_typecheck_arg_##hookname(func),                   \
 | 
			
		||||
		       arg, true, THIS_MODULE, #func, prio)
 | 
			
		||||
		       _hook_typecheck_arg_##hookname(func), arg, true,        \
 | 
			
		||||
		       THIS_MODULE, #func, prio)
 | 
			
		||||
 | 
			
		||||
extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
 | 
			
		||||
			     bool has_arg);
 | 
			
		||||
@ -190,7 +190,7 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
 | 
			
		||||
	{                                                                      \
 | 
			
		||||
		return (void *)funcptr;                                        \
 | 
			
		||||
	}
 | 
			
		||||
#define DECLARE_KOOH(hookname, arglist, passlist) \
 | 
			
		||||
#define DECLARE_KOOH(hookname, arglist, passlist)                              \
 | 
			
		||||
	DECLARE_HOOK(hookname, arglist, passlist)
 | 
			
		||||
 | 
			
		||||
/* use in source file - contains hook-related definitions.
 | 
			
		||||
@ -220,9 +220,9 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
 | 
			
		||||
		return hooksum;                                                \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define DEFINE_HOOK(hookname, arglist, passlist) \
 | 
			
		||||
#define DEFINE_HOOK(hookname, arglist, passlist)                               \
 | 
			
		||||
	DEFINE_HOOK_INT(hookname, arglist, passlist, false)
 | 
			
		||||
#define DEFINE_KOOH(hookname, arglist, passlist) \
 | 
			
		||||
#define DEFINE_KOOH(hookname, arglist, passlist)                               \
 | 
			
		||||
	DEFINE_HOOK_INT(hookname, arglist, passlist, true)
 | 
			
		||||
 | 
			
		||||
#endif /* _FRR_HOOK_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								lib/if.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								lib/if.c
									
									
									
									
									
								
							@ -48,8 +48,8 @@ RB_GENERATE(if_index_head, interface, index_entry, if_cmp_index_func);
 | 
			
		||||
 | 
			
		||||
DEFINE_QOBJ_TYPE(interface)
 | 
			
		||||
 | 
			
		||||
DEFINE_HOOK(if_add, (struct interface *ifp), (ifp))
 | 
			
		||||
DEFINE_KOOH(if_del, (struct interface *ifp), (ifp))
 | 
			
		||||
DEFINE_HOOK(if_add, (struct interface * ifp), (ifp))
 | 
			
		||||
DEFINE_KOOH(if_del, (struct interface * ifp), (ifp))
 | 
			
		||||
 | 
			
		||||
/* List of interfaces in only the default VRF */
 | 
			
		||||
int ptm_enable = 0;
 | 
			
		||||
@ -152,7 +152,7 @@ struct interface *if_create(const char *name, vrf_id_t vrf_id)
 | 
			
		||||
	SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
 | 
			
		||||
 | 
			
		||||
	QOBJ_REG(ifp, interface);
 | 
			
		||||
        hook_call(if_add, ifp);
 | 
			
		||||
	hook_call(if_add, ifp);
 | 
			
		||||
	return ifp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -181,7 +181,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
 | 
			
		||||
/* Delete interface structure. */
 | 
			
		||||
void if_delete_retain(struct interface *ifp)
 | 
			
		||||
{
 | 
			
		||||
        hook_call(if_del, ifp);
 | 
			
		||||
	hook_call(if_del, ifp);
 | 
			
		||||
	QOBJ_UNREG(ifp);
 | 
			
		||||
 | 
			
		||||
	/* Free connected address list */
 | 
			
		||||
@ -225,7 +225,7 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
 | 
			
		||||
	if (vrf_id == VRF_UNKNOWN) {
 | 
			
		||||
		struct interface *ifp;
 | 
			
		||||
 | 
			
		||||
		RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) {
 | 
			
		||||
		RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
 | 
			
		||||
			ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
 | 
			
		||||
			if (ifp)
 | 
			
		||||
				return ifp;
 | 
			
		||||
@ -404,8 +404,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty)
 | 
			
		||||
	 * this should not be considered as an update
 | 
			
		||||
	 * then create the new interface
 | 
			
		||||
	 */
 | 
			
		||||
	if (ifp->vrf_id != vrf_id &&
 | 
			
		||||
	    vrf_is_mapped_on_netns(vrf_id))
 | 
			
		||||
	if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id))
 | 
			
		||||
		return if_create(name, vrf_id);
 | 
			
		||||
	/* If it came from the kernel
 | 
			
		||||
	 * or by way of zclient, believe it and update
 | 
			
		||||
@ -477,6 +476,12 @@ int if_is_loopback(struct interface *ifp)
 | 
			
		||||
	return (ifp->flags & (IFF_LOOPBACK | IFF_NOXMIT | IFF_VIRTUAL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check interface is VRF */
 | 
			
		||||
int if_is_vrf(struct interface *ifp)
 | 
			
		||||
{
 | 
			
		||||
	return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Does this interface support broadcast ? */
 | 
			
		||||
int if_is_broadcast(struct interface *ifp)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								lib/if.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								lib/if.h
									
									
									
									
									
								
							@ -288,6 +288,7 @@ struct interface {
 | 
			
		||||
 | 
			
		||||
	QOBJ_FIELDS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RB_HEAD(if_name_head, interface);
 | 
			
		||||
RB_PROTOTYPE(if_name_head, interface, name_entry, if_cmp_func);
 | 
			
		||||
RB_HEAD(if_index_head, interface);
 | 
			
		||||
@ -337,8 +338,8 @@ DECLARE_QOBJ_TYPE(interface)
 | 
			
		||||
 * can use 1000+ so they run after the daemon has initialised daemon-specific
 | 
			
		||||
 * interface data
 | 
			
		||||
 */
 | 
			
		||||
DECLARE_HOOK(if_add, (struct interface *ifp), (ifp))
 | 
			
		||||
DECLARE_KOOH(if_del, (struct interface *ifp), (ifp))
 | 
			
		||||
DECLARE_HOOK(if_add, (struct interface * ifp), (ifp))
 | 
			
		||||
DECLARE_KOOH(if_del, (struct interface * ifp), (ifp))
 | 
			
		||||
 | 
			
		||||
/* Connected address structure. */
 | 
			
		||||
struct connected {
 | 
			
		||||
@ -460,7 +461,7 @@ extern int if_cmp_name_func(char *, char *);
 | 
			
		||||
 * else think before you use VRF_UNKNOWN
 | 
			
		||||
 */
 | 
			
		||||
extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
 | 
			
		||||
extern struct interface *if_create(const char *name,  vrf_id_t vrf_id);
 | 
			
		||||
extern struct interface *if_create(const char *name, vrf_id_t vrf_id);
 | 
			
		||||
extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);
 | 
			
		||||
extern struct interface *if_lookup_exact_address(void *matchaddr, int family,
 | 
			
		||||
						 vrf_id_t vrf_id);
 | 
			
		||||
@ -491,6 +492,7 @@ extern int if_is_running(struct interface *);
 | 
			
		||||
extern int if_is_operative(struct interface *);
 | 
			
		||||
extern int if_is_no_ptm_operative(struct interface *);
 | 
			
		||||
extern int if_is_loopback(struct interface *);
 | 
			
		||||
extern int if_is_vrf(struct interface *ifp);
 | 
			
		||||
extern int if_is_broadcast(struct interface *);
 | 
			
		||||
extern int if_is_pointopoint(struct interface *);
 | 
			
		||||
extern int if_is_multicast(struct interface *);
 | 
			
		||||
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user