summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c22
-rw-r--r--bgpd/bgp_evpn.c10
-rw-r--r--bgpd/bgp_fsm.c10
-rw-r--r--bgpd/bgp_open.c32
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_packet.c5
-rw-r--r--bgpd/bgp_route.c6
-rw-r--r--bgpd/bgp_updgrp.c25
-rw-r--r--bgpd/bgp_updgrp.h5
-rw-r--r--bgpd/bgp_vty.c86
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--bgpd/bgp_zebra.h2
-rw-r--r--bgpd/bgpd.c17
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--doc/user/ospfd.rst14
-rw-r--r--isisd/isis_misc.c16
-rw-r--r--lib/asn.h8
-rw-r--r--lib/libospf.h1
-rw-r--r--nhrpd/nhrp_route.c6
-rw-r--r--ospfd/ospf_flood.c9
-rw-r--r--ospfd/ospf_gr.c11
-rw-r--r--ospfd/ospf_interface.c45
-rw-r--r--ospfd/ospf_interface.h3
-rw-r--r--ospfd/ospf_lsa.c1
-rw-r--r--ospfd/ospf_network.c38
-rw-r--r--ospfd/ospf_opaque.c6
-rw-r--r--ospfd/ospf_packet.c16
-rw-r--r--ospfd/ospf_vty.c79
-rw-r--r--pimd/pim_cmd_common.c10
-rw-r--r--sharpd/sharp_vty.c12
-rw-r--r--sharpd/sharp_zebra.c1
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.py2
-rw-r--r--tests/topotests/bgp_flowspec/peer1/exabgp.cfg1
-rw-r--r--tests/topotests/bgp_flowspec/test_bgp_flowspec_topo.py3
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf2
-rw-r--r--tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py8
-rw-r--r--tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py4
-rwxr-xr-xtests/topotests/conftest.py48
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/isisd.conf1
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/isisd.conf3
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step1/show_yang_interface_isis_adjacencies.ref8
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/isisd.conf3
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref8
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/isisd.conf4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step1/show_yang_interface_isis_adjacencies.ref8
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/isisd.conf4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step1/show_yang_interface_isis_adjacencies.ref8
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/isisd.conf2
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step1/show_yang_interface_isis_adjacencies.ref4
-rwxr-xr-xtests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py3
-rw-r--r--tests/topotests/lib/topotest.py10
-rw-r--r--tests/topotests/nhrp_topo/r1/sharp_route4.json46
-rw-r--r--tests/topotests/nhrp_topo/test_nhrp_topo.py38
-rw-r--r--tests/topotests/ospfapi/test_ospf_clientapi.py439
-rw-r--r--tests/topotests/zebra_rib/test_zebra_rib.py4
-rwxr-xr-xtools/frr-reload.py20
-rw-r--r--zebra/interface.c28
-rw-r--r--zebra/kernel_netlink.c7
-rw-r--r--zebra/redistribute.c11
-rw-r--r--zebra/rib.h4
-rw-r--r--zebra/zebra_nhg.c9
65 files changed, 990 insertions, 265 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 34422bf514..4a5b0ba066 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2138,6 +2138,15 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
+ /* if the ORIGINATOR_ID attribute is received from an external
+ * neighbor, it SHALL be discarded using the approach of "attribute
+ * discard".
+ */
+ if (peer->sort == BGP_PEER_EBGP) {
+ stream_forward_getp(peer->curr, length);
+ return BGP_ATTR_PARSE_PROCEED;
+ }
+
/* if received from an internal neighbor, it SHALL be considered
* malformed if its length is not equal to 4. If malformed, the
* UPDATE message SHALL be handled using the approach of "treat-as-
@@ -2174,6 +2183,15 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
+ /* if the CLUSTER_LIST attribute is received from an external
+ * neighbor, it SHALL be discarded using the approach of "attribute
+ * discard".
+ */
+ if (peer->sort == BGP_PEER_EBGP) {
+ stream_forward_getp(peer->curr, length);
+ return BGP_ATTR_PARSE_PROCEED;
+ }
+
/* if received from an internal neighbor, it SHALL be considered
* malformed if its length is not a non-zero multiple of 4. If
* malformed, the UPDATE message SHALL be handled using the approach
@@ -2658,7 +2676,9 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
if (BGP_ATTR_ENCAP == type) {
subtype = stream_getc(BGP_INPUT(peer));
- sublength = stream_getc(BGP_INPUT(peer));
+ sublength = (subtype < 128)
+ ? stream_getc(BGP_INPUT(peer))
+ : stream_getw(BGP_INPUT(peer));
length -= 2;
#ifdef ENABLE_BGP_VNC
} else {
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 625b7e59dc..a33f59cf5b 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -936,7 +936,10 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip,
esi);
- return zclient_send_message(zclient);
+ if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
+ return -1;
+
+ return 0;
}
/*
@@ -988,7 +991,10 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
- return zclient_send_message(zclient);
+ if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
+ return -1;
+
+ return 0;
}
/*
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 4e8894cb44..2cea9971e6 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -2258,12 +2258,6 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
peer, afi, safi, ORF_TYPE_PREFIX,
REFRESH_IMMEDIATE, 0,
BGP_ROUTE_REFRESH_NORMAL);
- else if (CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
- bgp_route_refresh_send(
- peer, afi, safi, ORF_TYPE_PREFIX_OLD,
- REFRESH_IMMEDIATE, 0,
- BGP_ROUTE_REFRESH_NORMAL);
}
}
@@ -2272,9 +2266,7 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer)
if (CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ORF_PREFIX_RM_ADV))
if (CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
+ PEER_CAP_ORF_PREFIX_SM_RCV))
SET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_ORF_WAIT_REFRESH);
}
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 84f770f7db..1b266314fb 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -36,7 +36,6 @@ static const struct message capcode_str[] = {
{CAPABILITY_CODE_ADDPATH, "AddPath"},
{CAPABILITY_CODE_DYNAMIC, "Dynamic"},
{CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"},
- {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
{CAPABILITY_CODE_FQDN, "FQDN"},
{CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
{CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
@@ -55,7 +54,6 @@ static const size_t cap_minsizes[] = {
[CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
[CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN,
- [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
[CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
[CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
[CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
@@ -78,7 +76,6 @@ static const size_t cap_modsizes[] = {
[CAPABILITY_CODE_ADDPATH] = 4,
[CAPABILITY_CODE_DYNAMIC] = 1,
[CAPABILITY_CODE_ENHE] = 6,
- [CAPABILITY_CODE_ORF_OLD] = 1,
[CAPABILITY_CODE_FQDN] = 1,
[CAPABILITY_CODE_ENHANCED_RR] = 1,
[CAPABILITY_CODE_EXT_MESSAGE] = 1,
@@ -345,7 +342,6 @@ static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi,
static const struct message orf_type_str[] = {
{ORF_TYPE_RESERVED, "Reserved"},
{ORF_TYPE_PREFIX, "Prefixlist"},
- {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"},
{0}};
static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"},
@@ -434,22 +430,6 @@ static int bgp_capability_orf_entry(struct peer *peer,
continue;
}
break;
- case CAPABILITY_CODE_ORF_OLD:
- switch (type) {
- case ORF_TYPE_RESERVED:
- if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- "%s Addr-family %d/%d has reserved ORF type, ignoring",
- peer->host, afi, safi);
- break;
- case ORF_TYPE_PREFIX_OLD:
- break;
- default:
- bgp_capability_orf_not_support(
- peer, pkt_afi, pkt_safi, type, mode);
- continue;
- }
- break;
default:
bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
type, mode);
@@ -476,9 +456,6 @@ static int bgp_capability_orf_entry(struct peer *peer,
if (hdr->code == CAPABILITY_CODE_ORF) {
sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
- } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) {
- sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
- rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
} else {
bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
type, mode);
@@ -1006,7 +983,6 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_MP:
case CAPABILITY_CODE_REFRESH:
case CAPABILITY_CODE_ORF:
- case CAPABILITY_CODE_ORF_OLD:
case CAPABILITY_CODE_RESTART:
case CAPABILITY_CODE_AS4:
case CAPABILITY_CODE_ADDPATH:
@@ -1076,7 +1052,6 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
SET_FLAG(peer->cap, PEER_CAP_REFRESH_RCV);
} break;
case CAPABILITY_CODE_ORF:
- case CAPABILITY_CODE_ORF_OLD:
ret = bgp_capability_orf_entry(peer, &caphdr);
break;
case CAPABILITY_CODE_RESTART:
@@ -1486,9 +1461,7 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
/* Address Prefix ORF */
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
|| CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) {
- stream_putc(s, (code == CAPABILITY_CODE_ORF
- ? ORF_TYPE_PREFIX
- : ORF_TYPE_PREFIX_OLD));
+ stream_putc(s, ORF_TYPE_PREFIX);
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_ORF_PREFIX_SM)
@@ -1881,9 +1854,6 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
|| CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_ORF_PREFIX_RM)) {
bgp_open_capability_orf(s, peer, afi, safi,
- CAPABILITY_CODE_ORF_OLD,
- ext_opt_params);
- bgp_open_capability_orf(s, peer, afi, safi,
CAPABILITY_CODE_ORF,
ext_opt_params);
}
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index c767100293..b18dbaa04f 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -38,7 +38,6 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_FQDN 73 /* Advertise hostname capability */
#define CAPABILITY_CODE_SOFT_VERSION 75 /* Software Version capability */
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
-#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
#define CAPABILITY_CODE_EXT_MESSAGE 6 /* Extended Message Support */
#define CAPABILITY_CODE_ROLE 9 /* Role Capability */
@@ -63,7 +62,6 @@ struct graceful_restart_af {
/* ORF Type */
#define ORF_TYPE_RESERVED 0
#define ORF_TYPE_PREFIX 64
-#define ORF_TYPE_PREFIX_OLD 128
/* ORF Mode */
#define ORF_MODE_RECEIVE 1
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index d30ba68347..ab9e940997 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1116,7 +1116,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
stream_putc(s, 0);
stream_putc(s, pkt_safi);
- if (orf_type == ORF_TYPE_PREFIX || orf_type == ORF_TYPE_PREFIX_OLD)
+ if (orf_type == ORF_TYPE_PREFIX)
if (remove || filter->plist[FILTER_IN].plist) {
uint16_t orf_len;
unsigned long orfp;
@@ -2375,8 +2375,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
/* orf_len in bounds? */
if ((stream_pnt(s) + orf_len) > end)
break; /* XXX: Notify instead?? */
- if (orf_type == ORF_TYPE_PREFIX
- || orf_type == ORF_TYPE_PREFIX_OLD) {
+ if (orf_type == ORF_TYPE_PREFIX) {
uint8_t *p_pnt = stream_pnt(s);
uint8_t *p_end = stream_pnt(s) + orf_len;
struct orf_prefix orfp;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0b821acfae..24be160656 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2181,10 +2181,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* ORF prefix-list filter check */
- if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
- && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
+ if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) &&
+ CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV))
if (peer->orf_plist[afi][safi]) {
if (prefix_list_apply(peer->orf_plist[afi][safi], p)
== PREFIX_DENY) {
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 0fe6180bea..849f669932 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -420,8 +420,6 @@ static unsigned int updgrp_hash_key_make(const void *p)
*/
if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)
|| CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
|| CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT))
key = jhash_1word(jhash(peer->host, strlen(peer->host), SEED2),
key);
@@ -492,15 +490,12 @@ static unsigned int updgrp_hash_key_make(const void *p)
: "(NONE)",
peer->shared_network &&
peer_afi_active_nego(peer, AFI_IP6));
- zlog_debug(
- "%pBP Update Group Hash: Lonesoul: %d ORF prefix: %u ORF old: %u max prefix out: %ju",
- peer, !!CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL),
- CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_RCV),
- CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV),
- (intmax_t)CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_OUT));
+ zlog_debug("%pBP Update Group Hash: Lonesoul: %d ORF prefix: %u max prefix out: %ju",
+ peer, !!CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL),
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV),
+ (intmax_t)CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_OUT));
zlog_debug(
"%pBP Update Group Hash: local role: %u AIGP: %d SOO: %s",
peer, peer->local_role,
@@ -637,11 +632,9 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network))
return false;
- if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL)
- || CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(pe1->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
- && !sockunion_same(&pe1->su, &pe2->su))
+ if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL) ||
+ CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)) &&
+ !sockunion_same(&pe1->su, &pe2->su))
return false;
return true;
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 67c384ba02..70e7ac30b5 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -55,9 +55,8 @@
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
#define PEER_UPDGRP_AF_CAP_FLAGS \
- (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \
- | PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
- | PEER_CAP_ENHE_AF_NEGO)
+ (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ADDPATH_AF_TX_ADV | \
+ PEER_CAP_ADDPATH_AF_RX_RCV | PEER_CAP_ENHE_AF_NEGO)
enum bpacket_attr_vec_type { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX };
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index cf74919e97..7942797528 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -11854,7 +11854,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
&peer->ibuf->count,
memory_order_relaxed);
- vty_out(vty, "4 ");
+ vty_out(vty, "4");
vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation),
&peer->as);
if (show_wide)
@@ -11930,14 +11930,23 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
}
/* Make sure `Desc` column is the lastest in
* the output.
+ * If the description is not set, try
+ * to print the software version if the
+ * capability is enabled and received.
*/
if (peer->desc)
vty_out(vty, " %s",
bgp_peer_description_stripped(
peer->desc,
show_wide ? 64 : 20));
- else
+ else if (peer->soft_version) {
+ vty_out(vty, " %s",
+ bgp_peer_description_stripped(
+ peer->soft_version,
+ show_wide ? 64 : 20));
+ } else {
vty_out(vty, " N/A");
+ }
vty_out(vty, "\n");
}
@@ -12659,7 +12668,6 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
int orf_pfx_count;
json_object *json_af = NULL;
json_object *json_prefA = NULL;
- json_object *json_prefB = NULL;
json_object *json_addr = NULL;
json_object *json_advmap = NULL;
@@ -12702,37 +12710,13 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
json_prefA);
}
- if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) {
- json_object_int_add(json_af, "orfOldType",
- ORF_TYPE_PREFIX_OLD);
- json_prefB = json_object_new_object();
- bgp_show_peer_afi_orf_cap(
- vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV,
- PEER_CAP_ORF_PREFIX_RM_ADV,
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV,
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json,
- json_prefB);
- json_object_object_add(json_af, "orfOldPrefixList",
- json_prefB);
- }
-
- if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
json_object_object_add(json_addr, "afDependentCap",
json_af);
else
@@ -13019,17 +13003,13 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
} else {
vty_out(vty, " Not part of any update group\n");
}
- if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
vty_out(vty, " AF-dependant capabilities:\n");
if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
@@ -13048,22 +13028,6 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
PEER_CAP_ORF_PREFIX_SM_RCV,
PEER_CAP_ORF_PREFIX_RM_RCV, use_json, NULL);
}
- if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_ADV)
- || CHECK_FLAG(p->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) {
- vty_out(vty,
- " Outbound Route Filter (ORF) type (%d) Prefix-list:\n",
- ORF_TYPE_PREFIX_OLD);
- bgp_show_peer_afi_orf_cap(
- vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV,
- PEER_CAP_ORF_PREFIX_RM_ADV,
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV,
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, NULL);
- }
snprintf(orf_pfx_name, sizeof(orf_pfx_name), "%s.%d.%d",
p->host, afi, safi);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 430ea0f9a2..1320906339 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1085,7 +1085,7 @@ static void bgp_zebra_tm_connect(struct event *t)
}
bgp_tm_status_connected = true;
if (!bgp_tm_chunk_obtained) {
- if (bgp_zebra_get_table_range(bgp_tm_chunk_size,
+ if (bgp_zebra_get_table_range(zclient, bgp_tm_chunk_size,
&bgp_tm_min,
&bgp_tm_max) >= 0) {
bgp_tm_chunk_obtained = true;
@@ -1129,14 +1129,14 @@ void bgp_zebra_init_tm_connect(struct bgp *bgp)
&bgp_tm_thread_connect);
}
-int bgp_zebra_get_table_range(uint32_t chunk_size,
+int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
uint32_t *start, uint32_t *end)
{
int ret;
if (!bgp_tm_status_connected)
return -1;
- ret = tm_get_table_chunk(zclient, chunk_size, start, end);
+ ret = tm_get_table_chunk(zc, chunk_size, start, end);
if (ret < 0) {
flog_err(EC_BGP_TABLE_CHUNK,
"BGP: Error getting table chunk %u", chunk_size);
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 3d7d71d9b4..a0f7819460 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -24,7 +24,7 @@ extern void bgp_zebra_init_tm_connect(struct bgp *bgp);
extern uint32_t bgp_zebra_tm_get_id(void);
extern bool bgp_zebra_tm_chunk_obtained(void);
extern void bgp_zebra_destroy(void);
-extern int bgp_zebra_get_table_range(uint32_t chunk_size,
+extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
uint32_t *start, uint32_t *end);
extern int bgp_if_update_all(void);
extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 5544c59df8..5c97f90c55 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -6964,11 +6964,8 @@ static void peer_prefix_list_update(struct prefix_list *plist)
*/
if (CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ORF_PREFIX_SM_ADV) &&
- (CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_RCV) ||
- CHECK_FLAG(
- peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV))
peer_clear_soft(
peer, afi, safi,
BGP_CLEAR_SOFT_IN_ORF_PREFIX);
@@ -7935,19 +7932,15 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
if (CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_ADV)
- && (CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_RCV)
- || CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
+ PEER_CAP_ORF_PREFIX_SM_ADV) &&
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV)) {
struct bgp_filter *filter = &peer->filter[afi][safi];
uint8_t prefix_type;
if (CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ORF_PREFIX_RM_RCV))
prefix_type = ORF_TYPE_PREFIX;
- else
- prefix_type = ORF_TYPE_PREFIX_OLD;
if (filter->plist[FILTER_IN].plist) {
if (CHECK_FLAG(peer->af_sflags[afi][safi],
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index b8208cecee..edf9234424 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1280,8 +1280,6 @@ struct peer {
#define PEER_CAP_ORF_PREFIX_RM_ADV (1U << 1) /* receive-mode advertised */
#define PEER_CAP_ORF_PREFIX_SM_RCV (1U << 2) /* send-mode received */
#define PEER_CAP_ORF_PREFIX_RM_RCV (1U << 3) /* receive-mode received */
-#define PEER_CAP_ORF_PREFIX_SM_OLD_RCV (1U << 4) /* send-mode received */
-#define PEER_CAP_ORF_PREFIX_RM_OLD_RCV (1U << 5) /* receive-mode received */
#define PEER_CAP_RESTART_AF_RCV (1U << 6) /* graceful restart afi/safi received */
#define PEER_CAP_RESTART_AF_PRESERVE_RCV (1U << 7) /* graceful restart afi/safi F-bit received */
#define PEER_CAP_ADDPATH_AF_TX_ADV (1U << 8) /* addpath tx advertised */
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 3430d8a282..232b1c3934 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -912,7 +912,7 @@ Opaque LSA
- *ospfd* supports Opaque LSA (:rfc:`2370`) as partial support for
+ *ospfd* supports Opaque LSA (:rfc:`5250`) as partial support for
MPLS Traffic Engineering LSAs. The opaque-lsa capability must be
enabled in the configuration. An alternate command could be
"mpls-te on" (:ref:`ospf-traffic-engineering`). Note that FRR
@@ -920,6 +920,18 @@ Opaque LSA
extensions that are used with MPLS-TE; it does not support a
complete RSVP-TE solution.
+.. clicmd:: ip ospf capability opaque [A.B.C.D]
+
+ Enable or disable OSPF LSA database exchange and flooding on an interface.
+ The default is that opaque capability is enabled as long as the opaque
+ capability is enabled with the :clicmd:`capability opaque` command at the
+ OSPF instance level (using the command above). Note that disabling opaque
+ LSA support on an interface will impact the applications using opaque LSAs
+ if the opaque LSAs are not received on other flooding paths by all the
+ OSPF routers using those applications. For example, OSPF Graceful Restart
+ uses opaque-link LSAs and disabling support on an interface will disable
+ graceful restart signaling on that interface.
+
.. clicmd:: show ip ospf [vrf <NAME|all>] database (opaque-link|opaque-area|opaque-external)
.. clicmd:: show ip ospf [vrf <NAME|all>] database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 09ffa3479a..e4ef6c8dfa 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -474,20 +474,20 @@ void log_multiline(int priority, const char *prefix, const char *format, ...)
char *log_uptime(time_t uptime, char *buf, size_t nbuf)
{
- struct tm *tm;
+ struct tm tm;
time_t difftime = time(NULL);
difftime -= uptime;
- tm = gmtime(&difftime);
+ gmtime_r(&difftime, &tm);
if (difftime < ONE_DAY_SECOND)
- snprintf(buf, nbuf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
- tm->tm_sec);
+ snprintf(buf, nbuf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
+ tm.tm_sec);
else if (difftime < ONE_WEEK_SECOND)
- snprintf(buf, nbuf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
- tm->tm_min);
+ snprintf(buf, nbuf, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
+ tm.tm_min);
else
- snprintf(buf, nbuf, "%02dw%dd%02dh", tm->tm_yday / 7,
- tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
+ snprintf(buf, nbuf, "%02dw%dd%02dh", tm.tm_yday / 7,
+ tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
return buf;
}
diff --git a/lib/asn.h b/lib/asn.h
index 81a42c658d..a7394fa52b 100644
--- a/lib/asn.h
+++ b/lib/asn.h
@@ -66,10 +66,10 @@ extern char *asn_asn2string(const as_t *as, char *buf, size_t len,
((mode == ASNOTATION_DOT) ? "%pASD" : \
((mode == ASNOTATION_DOTPLUS) ? "%pASE" : \
"%pASP"))
-#define ASN_FORMAT_SPACE(mode) \
- ((mode == ASNOTATION_DOT) ? "%10pASD" : \
- ((mode == ASNOTATION_DOTPLUS) ? "%10pASE" : \
- "%10pASP"))
+#define ASN_FORMAT_SPACE(mode) \
+ ((mode == ASNOTATION_DOT) \
+ ? "%11pASD" \
+ : ((mode == ASNOTATION_DOTPLUS) ? "%11pASE" : "%11pASP"))
/* for test */
extern void asn_relax_as_zero(bool relax);
diff --git a/lib/libospf.h b/lib/libospf.h
index 9eaca9a1a8..e3c1adb810 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -69,6 +69,7 @@ extern "C" {
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
+#define OSPF_OPAQUE_CAPABLE_DEFAULT true
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
#define OSPF_AREA_RANGE_COST_UNSPEC -1U
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index bf7ba5f650..060e60314d 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -108,11 +108,10 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
void nhrp_route_announce(int add, enum nhrp_cache_type type,
const struct prefix *p, struct interface *ifp,
- const union sockunion *nexthop, uint32_t mtu)
+ const union sockunion *nexthop_ref, uint32_t mtu)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
- union sockunion *nexthop_ref = (union sockunion *)nexthop;
if (zclient->sock < 0)
return;
@@ -125,9 +124,10 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type,
switch (type) {
case NHRP_CACHE_NEGATIVE:
+ /* Fill in a blackhole nexthop */
zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
ifp = NULL;
- nexthop = NULL;
+ nexthop_ref = NULL;
break;
case NHRP_CACHE_DYNAMIC:
case NHRP_CACHE_NHS:
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 5ae15fd887..dd8c9268f1 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -568,6 +568,15 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
if (!ospf_if_is_enable(oi))
return 0;
+ if (IS_OPAQUE_LSA(lsa->data->type) &&
+ !OSPF_IF_PARAM(oi, opaque_capable)) {
+ if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
+ zlog_debug(
+ "%s: Skipping interface %s (%s) with opaque disabled.",
+ __func__, IF_NAME(oi), ospf_get_name(oi->ospf));
+ return 0;
+ }
+
/* If flood reduction is configured, set the DC bit on the lsa. */
if (IS_LSA_SELF(lsa)) {
if (OSPF_FR_CONFIG(oi->area->ospf, oi->area)) {
diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c
index 2a346f2388..c23c42052f 100644
--- a/ospfd/ospf_gr.c
+++ b/ospfd/ospf_gr.c
@@ -773,8 +773,15 @@ static void ospf_gr_prepare(void)
}
/* Send a Grace-LSA to all neighbors. */
- for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi))
- ospf_gr_lsa_originate(oi, OSPF_GR_SW_RESTART, false);
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) {
+ if (OSPF_IF_PARAM(oi, opaque_capable))
+ ospf_gr_lsa_originate(oi, OSPF_GR_SW_RESTART,
+ false);
+ else
+ zlog_debug(
+ "GR: skipping grace LSA on interface %s (%s) with opaque capability disabled",
+ IF_NAME(oi), ospf_get_name(oi->ospf));
+ }
/* Record end of the grace period in non-volatile memory. */
ospf_gr_nvm_update(ospf, true);
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 9e6acdbf0d..72de198116 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -271,6 +271,10 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
QOBJ_REG(oi, ospf_interface);
+ /* If first oi, check per-intf write socket */
+ if (ospf->oi_running && ospf->intf_socket_enabled)
+ ospf_ifp_sock_init(ifp);
+
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf interface %s vrf %s id %u created",
__func__, ifp->name, ospf_get_name(ospf),
@@ -327,6 +331,8 @@ void ospf_if_cleanup(struct ospf_interface *oi)
void ospf_if_free(struct ospf_interface *oi)
{
+ struct interface *ifp = oi->ifp;
+
ospf_if_down(oi);
ospf_fifo_free(oi->obuf);
@@ -361,6 +367,10 @@ void ospf_if_free(struct ospf_interface *oi)
event_cancel_event(master, oi);
+ /* If last oi, close per-interface socket */
+ if (ospf_oi_count(ifp) == 0)
+ ospf_ifp_sock_close(ifp);
+
memset(oi, 0, sizeof(*oi));
XFREE(MTYPE_OSPF_IF, oi);
}
@@ -538,6 +548,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
UNSET_IF_PARAM(oip, auth_crypt);
UNSET_IF_PARAM(oip, auth_type);
UNSET_IF_PARAM(oip, if_area);
+ UNSET_IF_PARAM(oip, opaque_capable);
oip->auth_crypt = list_new();
@@ -546,6 +557,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
oip->ptp_dmvpn = 0;
oip->p2mp_delay_reflood = OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ oip->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
return oip;
}
@@ -575,19 +587,20 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
oip = rn->info;
route_unlock_node(rn);
- if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd)
- && !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay)
- && !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval)
- && !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface)
- && !OSPF_IF_PARAM_CONFIGURED(oip, v_hello)
- && !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello)
- && !OSPF_IF_PARAM_CONFIGURED(oip, v_wait)
- && !OSPF_IF_PARAM_CONFIGURED(oip, priority)
- && !OSPF_IF_PARAM_CONFIGURED(oip, type)
- && !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple)
- && !OSPF_IF_PARAM_CONFIGURED(oip, auth_type)
- && !OSPF_IF_PARAM_CONFIGURED(oip, if_area)
- && listcount(oip->auth_crypt) == 0) {
+ if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, v_hello) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, v_wait) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, priority) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, type) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, auth_type) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
+ listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
rn->info = NULL;
route_unlock_node(rn);
@@ -693,6 +706,9 @@ int ospf_if_new_hook(struct interface *ifp)
SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type);
IF_DEF_PARAMS(ifp)->auth_type = OSPF_AUTH_NOTSET;
+ SET_IF_PARAM(IF_DEF_PARAMS(ifp), opaque_capable);
+ IF_DEF_PARAMS(ifp)->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
+
rc = ospf_opaque_new_if(ifp);
return rc;
}
@@ -1404,7 +1420,8 @@ static int ospf_ifp_up(struct interface *ifp)
/* Open per-intf write socket if configured */
ospf = ifp->vrf->info;
- if (ospf && ospf->intf_socket_enabled)
+
+ if (ospf && ospf->oi_running && ospf->intf_socket_enabled)
ospf_ifp_sock_init(ifp);
ospf_if_recalculate_output_cost(ifp);
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index ec1afa1b8b..38ec45c757 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -112,6 +112,9 @@ struct ospf_if_params {
/* point-to-multipoint delayed reflooding configuration */
bool p2mp_delay_reflood;
+
+ /* Opaque LSA capability at interface level (see RFC5250) */
+ DECLARE_IF_PARAM(bool, opaque_capable);
};
enum { MEMBER_ALLROUTERS = 0,
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 67f1faf8a9..27e7e02759 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2007,7 +2007,6 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
/* add translated flag, checksum and lock new lsa */
SET_FLAG(new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */
- new = ospf_lsa_lock(new);
return new;
}
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index aff8ed05c7..801f75ad18 100644
--- a/ospfd/ospf_network.c
+++ b/ospfd/ospf_network.c
@@ -159,7 +159,8 @@ int ospf_if_ipmulticast(int fd, struct prefix *p, ifindex_t ifindex)
* Helper to open and set up a socket; returns the new fd on success,
* -1 on error.
*/
-static int sock_init_common(vrf_id_t vrf_id, const char *name, int *pfd)
+static int sock_init_common(vrf_id_t vrf_id, const char *name, int proto,
+ int *pfd)
{
int ospf_sock;
int ret, hincl = 1;
@@ -170,8 +171,7 @@ static int sock_init_common(vrf_id_t vrf_id, const char *name, int *pfd)
}
frr_with_privs(&ospfd_privs) {
- ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
- vrf_id, name);
+ ospf_sock = vrf_socket(AF_INET, SOCK_RAW, proto, vrf_id, name);
if (ospf_sock < 0) {
flog_err(EC_LIB_SOCKET, "%s: socket: %s", __func__,
safe_strerror(errno));
@@ -244,7 +244,8 @@ int ospf_sock_init(struct ospf *ospf)
if (ospf->fd > 0)
return -1;
- ret = sock_init_common(ospf->vrf_id, ospf->name, &(ospf->fd));
+ ret = sock_init_common(ospf->vrf_id, ospf->name, IPPROTO_OSPFIGP,
+ &(ospf->fd));
if (ret >= 0) /* Update socket buffer sizes */
ospf_sock_bufsize_update(ospf, ospf->fd, OSPF_SOCK_BOTH);
@@ -258,8 +259,8 @@ int ospf_sock_init(struct ospf *ospf)
int ospf_ifp_sock_init(struct interface *ifp)
{
struct ospf_if_info *oii;
- struct ospf_interface *oi;
- struct ospf *ospf;
+ struct ospf_interface *oi = NULL;
+ struct ospf *ospf = NULL;
struct route_node *rn;
int ret;
@@ -270,17 +271,26 @@ int ospf_ifp_sock_init(struct interface *ifp)
if (oii->oii_fd > 0)
return 0;
- rn = route_top(IF_OIFS(ifp));
- if (rn && rn->info) {
- oi = rn->info;
- ospf = oi->ospf;
- } else
+ for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
+ if (rn && rn->info) {
+ oi = rn->info;
+ ospf = oi->ospf;
+ break;
+ }
+ }
+
+ if (ospf == NULL)
return -1;
- ret = sock_init_common(ifp->vrf->vrf_id, ifp->name, &oii->oii_fd);
+ ret = sock_init_common(ifp->vrf->vrf_id, ifp->name, IPPROTO_OSPFIGP,
+ &oii->oii_fd);
- if (ret >= 0) /* Update socket buffer sizes */
- ospf_sock_bufsize_update(ospf, oii->oii_fd, OSPF_SOCK_BOTH);
+ if (ret >= 0) { /* Update socket buffer sizes */
+ /* Write-only, so no recv buf */
+ setsockopt_so_recvbuf(oii->oii_fd, 0);
+
+ ospf_sock_bufsize_update(ospf, oii->oii_fd, OSPF_SOCK_SEND);
+ }
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, ifp->name,
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 6894c6a009..27f47a6d79 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -1851,9 +1851,9 @@ static void ospf_opaque_type9_lsa_reoriginate_timer(struct event *t)
return;
}
- if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)
- || !ospf_if_is_enable(oi)
- || ospf_nbr_count_opaque_capable(oi) == 0) {
+ if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE) ||
+ !OSPF_IF_PARAM(oi, opaque_capable) || !ospf_if_is_enable(oi) ||
+ ospf_nbr_count_opaque_capable(oi) == 0) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...",
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 105c04c7a1..cfa0d5d574 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -953,8 +953,9 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
}
#endif /* REJECT_IF_TBIT_ON */
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)
- && CHECK_FLAG(hello->options, OSPF_OPTION_O)) {
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable) &&
+ CHECK_FLAG(hello->options, OSPF_OPTION_O)) {
/*
* This router does know the correct usage of O-bit
* the bit should be set in DD packet only.
@@ -1362,8 +1363,9 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
}
#endif /* REJECT_IF_TBIT_ON */
- if (CHECK_FLAG(dd->options, OSPF_OPTION_O)
- && !CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) {
+ if (CHECK_FLAG(dd->options, OSPF_OPTION_O) &&
+ (!CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) ||
+ !OSPF_IF_PARAM(oi, opaque_capable))) {
/*
* This node is not configured to handle O-bit, for now.
* Clear it to ignore unsupported capability proposed by
@@ -1448,7 +1450,8 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
/* This is where the real Options are saved */
nbr->options = dd->options;
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) {
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"Neighbor[%pI4] is %sOpaque-capable.",
@@ -3435,7 +3438,8 @@ static int ospf_make_db_desc(struct ospf_interface *oi,
/* Set Options. */
options = OPTIONS(oi);
- if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE))
+ if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) &&
+ OSPF_IF_PARAM(oi, opaque_capable))
SET_FLAG(options, OSPF_OPTION_O);
if (OSPF_FR_CONFIG(oi->ospf, oi->area))
SET_FLAG(options, OSPF_OPTION_DC);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 863055bf42..54fd60af23 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3811,6 +3811,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
lookup_msg(ospf_ism_state_msg,
oi->state, NULL));
json_object_int_add(json_oi, "priority", PRIORITY(oi));
+ json_object_boolean_add(
+ json_interface_sub, "opaqueCapable",
+ OSPF_IF_PARAM(oi, opaque_capable));
} else {
vty_out(vty, " Area %s\n",
ospf_area_desc_string(oi->area));
@@ -3830,6 +3833,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
OSPF_IF_PARAM(oi, transmit_delay),
lookup_msg(ospf_ism_state_msg, oi->state, NULL),
PRIORITY(oi));
+ if (!OSPF_IF_PARAM(oi, opaque_capable))
+ vty_out(vty,
+ " Opaque LSA capability disabled on interface\n");
}
/* Show DR information. */
@@ -9803,6 +9809,61 @@ DEFUN (no_ip_ospf_mtu_ignore,
return CMD_SUCCESS;
}
+DEFPY(ip_ospf_capability_opaque, ip_ospf_capability_opaque_addr_cmd,
+ "[no] ip ospf capability opaque [A.B.C.D]$ip_addr",
+ NO_STR
+ "IP Information\n"
+ "OSPF interface commands\n"
+ "Disable OSPF capability on this interface\n"
+ "Disable OSPF opaque LSA capability on this interface\n"
+ "Address of interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct route_node *rn;
+ bool old_opaque_capable;
+ bool opaque_capable_change;
+
+ struct ospf_if_params *params;
+ params = IF_DEF_PARAMS(ifp);
+
+ if (ip_addr.s_addr != INADDR_ANY) {
+ params = ospf_get_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+
+ old_opaque_capable = params->opaque_capable;
+ params->opaque_capable = (no) ? false : true;
+ opaque_capable_change = (old_opaque_capable != params->opaque_capable);
+ if (params->opaque_capable != OSPF_OPAQUE_CAPABLE_DEFAULT)
+ SET_IF_PARAM(params, opaque_capable);
+ else {
+ UNSET_IF_PARAM(params, opaque_capable);
+ if (params != IF_DEF_PARAMS(ifp)) {
+ ospf_free_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+ }
+
+ /*
+ * If there is a change to the opaque capability, flap the interface
+ * to reset all the neighbor adjacencies.
+ */
+ if (opaque_capable_change) {
+ for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
+ struct ospf_interface *oi = rn->info;
+
+ if (oi && (oi->state > ISM_Down) &&
+ (ip_addr.s_addr == INADDR_ANY ||
+ IPV4_ADDR_SAME(&oi->address->u.prefix4,
+ &ip_addr))) {
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
+ OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
+ }
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_max_metric_router_lsa_admin,
ospf_max_metric_router_lsa_admin_cmd,
@@ -12167,6 +12228,21 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
if (params && params->ldp_sync_info)
ospf_ldp_sync_if_write_config(vty, params);
+ /* Capability opaque print. */
+ if (OSPF_IF_PARAM_CONFIGURED(params, opaque_capable) &&
+ params->opaque_capable !=
+ OSPF_OPAQUE_CAPABLE_DEFAULT) {
+ if (params->opaque_capable == false)
+ vty_out(vty,
+ " no ip ospf capability opaque");
+ else
+ vty_out(vty,
+ " ip ospf capability opaque");
+ if (params != IF_DEF_PARAMS(ifp) && rn)
+ vty_out(vty, " %pI4", &rn->p.u.prefix4);
+ vty_out(vty, "\n");
+ }
+
while (1) {
if (rn == NULL)
rn = route_top(IF_OIFS_PARAMS(ifp));
@@ -12976,6 +13052,9 @@ static void ospf_vty_if_init(void)
install_element(INTERFACE_NODE, &ip_ospf_passive_cmd);
install_element(INTERFACE_NODE, &no_ip_ospf_passive_cmd);
+ /* "ip ospf capability opaque" commands. */
+ install_element(INTERFACE_NODE, &ip_ospf_capability_opaque_addr_cmd);
+
/* These commands are compatibitliy for previous version. */
install_element(INTERFACE_NODE, &ospf_authentication_key_cmd);
install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd);
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index 6af19cadd7..716cb8db5b 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -2844,6 +2844,8 @@ static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
json_object *json_row = NULL;
json_object *json_ifp = NULL;
json_object *json_arr = NULL;
+ struct pim_interface *pim_ifp = NULL;
+ bool pim_enable = false;
for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
first_ifindex = nh_node->ifindex;
@@ -2863,6 +2865,14 @@ static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
json_ifp = json_object_new_object();
json_object_string_add(json_ifp, "interface",
ifp ? ifp->name : "NULL");
+
+ if (ifp)
+ pim_ifp = ifp->info;
+
+ if (pim_ifp && pim_ifp->pim_enable)
+ pim_enable = true;
+
+ json_object_boolean_add(json_ifp, "pimEnabled", pim_enable);
#if PIM_IPV == 4
json_object_string_addf(json_ifp, "nexthop", "%pI4",
&nh_node->gate.ipv4);
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 3a2a7aa407..f0a75a5fc2 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -179,7 +179,7 @@ DEFPY (install_routes,
<nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
nexthop-group NHGNAME$nexthop_group>\
[backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
- (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
+ (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD] [no-recurse$norecurse]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
@@ -201,7 +201,8 @@ DEFPY (install_routes,
"Should we repeat this command\n"
"How many times to repeat this command\n"
"What opaque data to send down\n"
- "The opaque data\n")
+ "The opaque data\n"
+ "No recursive nexthops\n")
{
struct vrf *vrf;
struct prefix prefix;
@@ -210,6 +211,7 @@ DEFPY (install_routes,
sg.r.total_routes = routes;
sg.r.installed_routes = 0;
+ sg.r.flags = 0;
if (rpt >= 2)
sg.r.repeat = rpt * 2;
@@ -317,12 +319,16 @@ DEFPY (install_routes,
else
sg.r.opaque[0] = '\0';
+ /* Default is to ask for recursive nexthop resolution */
+ if (norecurse == NULL)
+ SET_FLAG(sg.r.flags, ZEBRA_FLAG_ALLOW_RECURSION);
+
sg.r.inst = instance;
sg.r.vrf_id = vrf->vrf_id;
rts = routes;
sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
&sg.r.nhop_group, &sg.r.backup_nhop_group,
- rts, 0, sg.r.opaque);
+ rts, sg.r.flags, sg.r.opaque);
return CMD_SUCCESS;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index df18118b02..c095fec17b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -247,7 +247,6 @@ static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance,
memcpy(&api.prefix, p, sizeof(*p));
api.flags = flags;
- SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
/* Only send via ID if nhgroup has been successfully installed */
diff --git a/tests/.gitignore b/tests/.gitignore
index f00177abd8..681438f4a5 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -29,6 +29,7 @@ frr_northbound*
/lib/test_buffer
/lib/test_checksum
/lib/test_frrscript
+/lib/test_darr
/lib/test_frrlua
/lib/test_graph
/lib/test_grpc
diff --git a/tests/topotests/bgp_features/test_bgp_features.py b/tests/topotests/bgp_features/test_bgp_features.py
index e033a0f005..43f4905d41 100644
--- a/tests/topotests/bgp_features/test_bgp_features.py
+++ b/tests/topotests/bgp_features/test_bgp_features.py
@@ -1063,7 +1063,7 @@ def test_bgp_delayopen_dual():
delay_stop = int(time.time())
assertmsg = "BGP peering between r2 and r5 was established before DelayOpenTimer (30sec) on r2 could expire"
- assert (delay_stop - delay_start) > 30, assertmsg
+ assert (delay_stop - delay_start) >= 30, assertmsg
# 3.8 unset delayopen on R2 and R5
logger.info("Disabling DelayOpenTimer for neighbor r5 on r2")
diff --git a/tests/topotests/bgp_flowspec/peer1/exabgp.cfg b/tests/topotests/bgp_flowspec/peer1/exabgp.cfg
index cd1fae5aba..383a95b6dd 100644
--- a/tests/topotests/bgp_flowspec/peer1/exabgp.cfg
+++ b/tests/topotests/bgp_flowspec/peer1/exabgp.cfg
@@ -1,5 +1,6 @@
neighbor 10.0.1.1 {
router-id 10.0.1.101;
+hold-time 10;
local-address 10.0.1.101;
local-as 100;
peer-as 100;
diff --git a/tests/topotests/bgp_flowspec/test_bgp_flowspec_topo.py b/tests/topotests/bgp_flowspec/test_bgp_flowspec_topo.py
index b1bec1034b..a2be85962f 100644
--- a/tests/topotests/bgp_flowspec/test_bgp_flowspec_topo.py
+++ b/tests/topotests/bgp_flowspec/test_bgp_flowspec_topo.py
@@ -138,11 +138,12 @@ def test_bgp_convergence():
test_func = functools.partial(
topotest.router_json_cmp, router, "show bgp summary json", expected
)
- _, res = topotest.run_and_expect(test_func, None, count=90, wait=0.5)
+ _, res = topotest.run_and_expect(test_func, None, count=210, wait=1)
assertmsg = "BGP router network did not converge"
if res is not None:
generate_support_bundle()
assert res is None, assertmsg
+ generate_support_bundle()
def test_bgp_flowspec():
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
index 8d42cfc0d8..72211fee7f 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
@@ -5,7 +5,7 @@ password zebra
log stdout notifications
log commands
-log file bgpd.log debugging
+log file bgpd.log
#debug bgp vpn leak-to-vrf
#debug bgp vpn leak-from-vrf
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf
index 7b42b770b5..edb3b699f9 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r2/bgpd.conf
@@ -4,7 +4,7 @@ hostname r2
password zebra
log stdout notifications
log commands
-log file bgpd.log debugging
+log file bgpd.log
router bgp 5226
bgp router-id 2.2.2.2
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf
index ca9e627172..ed76ed3c63 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf
@@ -4,7 +4,7 @@ hostname r4
password zebra
log stdout notifications
log commands
-log file bgpd.log debug
+log file bgpd.log
#debug bgp vpn label
#debug bgp nht
diff --git a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py
index ebaab60341..c97cd0bdda 100644
--- a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py
+++ b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py
@@ -83,7 +83,7 @@ def test_bgp_path_attribute_discard():
"paths": [
{
"valid": True,
- "originatorId": "10.0.0.2",
+ "originatorId": None,
"community": {
"string": "65001:102",
},
@@ -98,12 +98,12 @@ def test_bgp_path_attribute_discard():
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
assert result is None, "Failed bgp convergence"
- step("Discard atomic-aggregate, community, and originator-id attributes from peer1")
+ step("Discard atomic-aggregate, and community attributes from peer1")
r1.vtysh_cmd(
"""
configure terminal
router bgp
- neighbor 10.0.0.2 path-attribute discard 6 8 9
+ neighbor 10.0.0.2 path-attribute discard 6 8
"""
)
@@ -137,7 +137,7 @@ def test_bgp_path_attribute_discard():
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
assert (
result is None
- ), "Failed to discard path attributes (atomic-aggregate, community, and originator-id)"
+ ), "Failed to discard path attributes (atomic-aggregate, community)"
def test_memory_leak():
diff --git a/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py b/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py
index 934c2ff16a..ce278ed7a7 100644
--- a/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py
+++ b/tests/topotests/bgp_vpnv4_per_nexthop_label/test_bgp_vpnv4_per_nexthop_label.py
@@ -242,6 +242,10 @@ def check_show_mpls_table(router, blacklist=None, label_list=None, whitelist=Non
if label_list is not None:
label_list.add(in_label)
for nh in label_info["nexthops"]:
+ if "installed" not in nh.keys():
+ return "{} {} is not installed yet on {}".format(
+ in_label, label_info, router.name
+ )
if nh["installed"] != True or nh["type"] != "BGP":
return "{}, show mpls table, nexthop is not installed".format(
router.name
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index cb25d63a36..f829ed2d12 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -297,6 +297,52 @@ def check_for_memleaks():
pytest.fail("memleaks found for daemons: " + " ".join(daemons))
+def check_for_core_dumps():
+ dumps = []
+ tgen = get_topogen() # pylint: disable=redefined-outer-name
+ latest = []
+
+ if tgen is not None:
+ logdir = tgen.logdir
+ cores = glob.glob(os.path.join(logdir, "*/*.dmp"))
+
+ if cores:
+ logger.error("Cores found:\n\t%s", "\n\t".join(cores))
+ pytest.fail("Core files found")
+
+
+def check_for_backtraces():
+ backtraces = []
+ tgen = get_topogen() # pylint: disable=redefined-outer-name
+ latest = []
+ existing = []
+ if tgen is not None:
+ logdir = tgen.logdir
+ if hasattr(tgen, "backtraces_existing_files"):
+ existing = tgen.backtraces_existing_files
+ latest = glob.glob(os.path.join(logdir, "*/*.log"))
+
+ daemons = []
+ for vfile in latest:
+ if vfile in existing:
+ continue
+ with open(vfile, encoding="ascii") as vf:
+ vfcontent = vf.read()
+ backtrace = vfcontent.count("Backtrace:")
+ if backtrace:
+ existing.append(vfile) # have backtrace don't check again
+ emsg = "Backtrace found in {}, failing test".format(vfile)
+ backtraces.append(emsg)
+
+ if tgen is not None:
+ tgen.backtrace_existing_files = existing
+
+ if backtraces:
+ logger.error("Backtraces found in test suite, erroring")
+ logger.error(backtraces)
+ pytest.fail("Backtraces found")
+
+
@pytest.fixture(autouse=True, scope="module")
def module_autouse(request):
basename = get_test_logdir(request.node.nodeid, True)
@@ -320,6 +366,8 @@ def module_check_memtest(request):
if request.config.option.memleaks:
if get_topogen() is not None:
check_for_memleaks()
+ check_for_backtraces()
+ check_for_core_dumps()
#
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt1/isisd.conf
index 955bd5caa0..620523512a 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt1/isisd.conf
@@ -16,6 +16,7 @@ interface lo
interface eth-sw1
ip router isis 1
ipv6 router isis 1
+ isis hello-interval 1
isis hello-multiplier 3
isis priority 100
isis fast-reroute ti-lfa
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
index 26f0dffa7a..d86f9ef658 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,14 +11,14 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0003",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 64,
"state": "up"
},
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0002",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 64,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt2/isisd.conf
index f971c658d4..9c4b86208b 100644
--- a/tests/topotests/isis_tilfa_topo1/rt2/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt2/isisd.conf
@@ -15,6 +15,7 @@ interface lo
interface eth-sw1
ip router isis 1
ipv6 router isis 1
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -22,6 +23,7 @@ interface eth-rt4-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -29,6 +31,7 @@ interface eth-rt4-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_yang_interface_isis_adjacencies.ref
index 1ea72a528b..69b6159d62 100644
--- a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,7 +11,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0004",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -30,7 +30,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0004",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -49,14 +49,14 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0001",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 100,
"state": "up"
},
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0003",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 64,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt3/isisd.conf
index 64f091cfed..1883575b7b 100644
--- a/tests/topotests/isis_tilfa_topo1/rt3/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt3/isisd.conf
@@ -15,6 +15,7 @@ interface lo
interface eth-sw1
ip router isis 1
ipv6 router isis 1
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -22,6 +23,7 @@ interface eth-rt5-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -29,6 +31,7 @@ interface eth-rt5-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
index d174b4a475..e75d5fe859 100644
--- a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,7 +11,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0005",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -30,7 +30,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0005",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -49,14 +49,14 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0001",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 100,
"state": "up"
},
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0002",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 64,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt4/isisd.conf
index 9223852f79..94f80d39d5 100644
--- a/tests/topotests/isis_tilfa_topo1/rt4/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt4/isisd.conf
@@ -16,6 +16,7 @@ interface eth-rt2-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -23,6 +24,7 @@ interface eth-rt2-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -30,6 +32,7 @@ interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -37,6 +40,7 @@ interface eth-rt6
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_yang_interface_isis_adjacencies.ref
index 2eb64b6fc9..1d2c559588 100644
--- a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,7 +11,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0002",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -30,7 +30,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0002",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -49,7 +49,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0005",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -68,7 +68,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0006",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt5/isisd.conf
index a08534cf30..e83ae9677b 100644
--- a/tests/topotests/isis_tilfa_topo1/rt5/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt5/isisd.conf
@@ -16,6 +16,7 @@ interface eth-rt3-1
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -23,6 +24,7 @@ interface eth-rt3-2
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -30,6 +32,7 @@ interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -37,6 +40,7 @@ interface eth-rt6
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_yang_interface_isis_adjacencies.ref
index 1ff8c2cd4e..f94b09e161 100644
--- a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,7 +11,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0003",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -30,7 +30,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0003",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -49,7 +49,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0004",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -68,7 +68,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0006",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/isisd.conf b/tests/topotests/isis_tilfa_topo1/rt6/isisd.conf
index d92f822b8d..462492e909 100644
--- a/tests/topotests/isis_tilfa_topo1/rt6/isisd.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt6/isisd.conf
@@ -16,6 +16,7 @@ interface eth-rt4
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
@@ -23,6 +24,7 @@ interface eth-rt5
ip router isis 1
ipv6 router isis 1
isis network point-to-point
+ isis hello-interval 1
isis hello-multiplier 3
isis fast-reroute ti-lfa
!
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_yang_interface_isis_adjacencies.ref
index 734832358f..9d4d47b2af 100644
--- a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_yang_interface_isis_adjacencies.ref
@@ -11,7 +11,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0004",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
@@ -30,7 +30,7 @@
{
"neighbor-sys-type": "level-1",
"neighbor-sysid": "0000.0000.0005",
- "hold-timer": 9,
+ "hold-timer": 3,
"neighbor-priority": 0,
"state": "up"
}
diff --git a/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py b/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
index 1ed52ab76d..f0724b9da6 100755
--- a/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
+++ b/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
@@ -1021,7 +1021,8 @@ def test_rt6_step14():
rname,
"show ipv6 route isis json",
outputs[rname][11]["show_ipv6_route.ref"],
- count=10,
+ count=20,
+ wait=2,
)
router_compare_json_output(
rname,
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 845d3e3b53..7371230057 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1189,8 +1189,8 @@ def rlimit_atleast(rname, min_value, raises=False):
def fix_netns_limits(ns):
# Maximum read and write socket buffer sizes
- sysctl_atleast(ns, "net.ipv4.tcp_rmem", [10 * 1024, 87380, 16 * 2**20])
- sysctl_atleast(ns, "net.ipv4.tcp_wmem", [10 * 1024, 87380, 16 * 2**20])
+ sysctl_atleast(ns, "net.ipv4.tcp_rmem", [10 * 1024, 87380, 16 * 2 ** 20])
+ sysctl_atleast(ns, "net.ipv4.tcp_wmem", [10 * 1024, 87380, 16 * 2 ** 20])
sysctl_assure(ns, "net.ipv4.conf.all.rp_filter", 0)
sysctl_assure(ns, "net.ipv4.conf.default.rp_filter", 0)
@@ -1249,8 +1249,8 @@ def fix_host_limits():
sysctl_atleast(None, "net.core.netdev_max_backlog", 4 * 1024)
# Maximum read and write socket buffer sizes
- sysctl_atleast(None, "net.core.rmem_max", 16 * 2**20)
- sysctl_atleast(None, "net.core.wmem_max", 16 * 2**20)
+ sysctl_atleast(None, "net.core.rmem_max", 16 * 2 ** 20)
+ sysctl_atleast(None, "net.core.wmem_max", 16 * 2 ** 20)
# Garbage Collection Settings for ARP and Neighbors
sysctl_atleast(None, "net.ipv4.neigh.default.gc_thresh2", 4 * 1024)
@@ -1642,8 +1642,6 @@ class Router(Node):
# TODO remove the following lines after all tests are migrated to Topogen.
# Try to find relevant old logfiles in /tmp and delete them
map(os.remove, glob.glob("{}/{}/*.log".format(self.logdir, self.name)))
- # Remove old core files
- map(os.remove, glob.glob("{}/{}/*.dmp".format(self.logdir, self.name)))
# Remove IP addresses from OS first - we have them in zebra.conf
self.removeIPs()
# If ldp is used, check for LDP to be compiled and Linux Kernel to be 4.5 or higher
diff --git a/tests/topotests/nhrp_topo/r1/sharp_route4.json b/tests/topotests/nhrp_topo/r1/sharp_route4.json
new file mode 100644
index 0000000000..4c4b8eaccd
--- /dev/null
+++ b/tests/topotests/nhrp_topo/r1/sharp_route4.json
@@ -0,0 +1,46 @@
+{
+ "4.4.4.1\/32":[
+ {
+ "prefix":"4.4.4.1\/32",
+ "prefixLen":32,
+ "protocol":"sharp",
+ "vrfId":0,
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "installed":true,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.255.255.2",
+ "interfaceName":"r1-gre0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.1\/32":[
+ {
+ "prefix":"5.5.5.1\/32",
+ "prefixLen":32,
+ "protocol":"sharp",
+ "vrfId":0,
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "installed":true,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.255.255.2",
+ "interfaceName":"r1-gre0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/nhrp_topo/test_nhrp_topo.py b/tests/topotests/nhrp_topo/test_nhrp_topo.py
index 879f5250ec..78b82eda79 100644
--- a/tests/topotests/nhrp_topo/test_nhrp_topo.py
+++ b/tests/topotests/nhrp_topo/test_nhrp_topo.py
@@ -108,6 +108,12 @@ def setup_module(mod):
TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname))
)
+ # Include sharpd for r1
+ if rname == "r1":
+ router.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
+
# Initialize all routers.
logger.info("Launching NHRP")
for name in router_list:
@@ -201,6 +207,38 @@ def test_nhrp_connection():
logger.info("Check Ping IPv4 from R1 to R2 OK")
+def test_route_install():
+ "Test use of NHRP routes by other protocols (sharpd here)."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing route install over NHRP tunnel")
+
+ # Install sharpd routes over an NHRP route
+ r1 = tgen.gears["r1"]
+
+ # Install one recursive and one non-recursive sharpd route
+ r1.vtysh_cmd("sharp install route 4.4.4.1 nexthop 10.255.255.2 1")
+
+ r1.vtysh_cmd("sharp install route 5.5.5.1 nexthop 10.255.255.2 1 no-recurse")
+
+ json_file = "{}/{}/sharp_route4.json".format(CWD, "r1")
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route sharp json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
+
+ logger.info("Sharp routes:")
+ output = r1.vtysh_cmd("show ip route sharp")
+ logger.info(output)
+
+ assertmsg = '"{}" JSON route output mismatches'.format(r1.name)
+ assert result is None, assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py
index 39ebbcfb62..7a7ea85e2f 100644
--- a/tests/topotests/ospfapi/test_ospf_clientapi.py
+++ b/tests/topotests/ospfapi/test_ospf_clientapi.py
@@ -17,6 +17,7 @@ import subprocess
import sys
import time
from datetime import datetime, timedelta
+from functools import partial
import pytest
from lib.common_config import (
@@ -31,6 +32,12 @@ from lib.micronet import Timeout, comm_error
from lib.topogen import Topogen, TopoRouter
from lib.topotest import interface_set_status, json_cmp
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
pytestmark = [pytest.mark.ospfd]
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -1142,6 +1149,438 @@ def test_ospf_opaque_restart(tgen):
_test_opaque_add_restart_add(tgen, apibin)
+def _test_opaque_interface_disable(tgen, apibin):
+ "Test disabling opaque capability on an interface"
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+ tc_name = "opaque_interface_disable"
+
+ p = None
+ pread = None
+ # Log to our stdin, stderr
+ pout = open(os.path.join(r1.net.logdir, "r1/intf-disable.log"), "a+")
+ try:
+ # STEP 1 in test_ospf_opaque_interface_disable and STEP 56 in CI tests
+ step("Disable OSPF opaque LSA Copability on r1's interface to r2")
+ r1.vtysh_multicmd("conf t\ninterface r1-eth0\nno ip ospf capability opaque")
+ time.sleep(15)
+
+ # STEP 2 in test_ospf_opaque_interface_disable and STEP 57 in CI tests
+ step("Verify the r1 configuration of 'no ip ospf capability opaque'")
+ no_capability_opaque_cfg = (
+ tgen.net["r1"]
+ .cmd(
+ 'vtysh -c "show running ospfd" | grep "^ no ip ospf capability opaque"'
+ )
+ .rstrip()
+ )
+ assertmsg = (
+ "'no ip ospf capability opaque' applied, but not present in configuration"
+ )
+ assert no_capability_opaque_cfg == " no ip ospf capability opaque", assertmsg
+
+ # STEP 3 in test_ospf_opaque_interface_disable and STEP 58 in CI tests
+ step("Verify the ospf opaque option is not applied to the r1 interface")
+ r1_interface_without_opaque = {
+ "interfaces": {
+ "r1-eth0": {
+ "ifUp": True,
+ "ospfEnabled": True,
+ "ipAddress": "10.0.1.1",
+ "ospfIfType": "Broadcast",
+ "opaqueCapable": False,
+ }
+ }
+ }
+ r1_interface_with_opaque = {
+ "interfaces": {
+ "r1-eth0": {
+ "ifUp": True,
+ "ospfEnabled": True,
+ "ipAddress": "10.0.1.1",
+ "ospfIfType": "Broadcast",
+ "opaqueCapable": True,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf interface json", r1_interface_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF interface doesn't have opaque capability disabled"
+ assert result is None, assertmsg
+
+ r1_neighbor_without_opaque = {
+ "neighbors": {
+ "2.0.0.0": [
+ {
+ "optionsList": "*|-|-|-|-|-|E|-",
+ }
+ ]
+ }
+ }
+ r2_neighbor_without_opaque = {
+ "neighbors": {
+ "1.0.0.0": [
+ {
+ "optionsList": "*|-|-|-|-|-|E|-",
+ }
+ ]
+ }
+ }
+ # STEP 4 in test_ospf_opaque_interface_disable and STEP 59 in CI tests
+ step("Verify that the r1 neighbor options don't include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor detail json", r1_neighbor_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF neighbor has opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 5 in test_ospf_opaque_interface_disable and STEP 60 in CI tests
+ step("Verify that the r1 neighbor options don't include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf neighbor detail json", r2_neighbor_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF neighbor has opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 6 in test_ospf_opaque_interface_disable and STEP 61 in CI tests
+ step(
+ "Verify no r2 configuration of 'no ip ospf capability opaque' in r2 configuration"
+ )
+ rc, _, _ = tgen.net["r2"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False
+ )
+ assertmsg = "'no ip ospf capability opaque' not applied, but not present in r2 configuration"
+ assert rc, assertmsg
+
+ # STEP 7 in test_ospf_opaque_interface_disable and STEP 62 in CI tests
+ step("Verify the ospf opaque option is applied to the r2 interface")
+ r2_interface_without_opaque = {
+ "interfaces": {
+ "r2-eth0": {
+ "ifUp": True,
+ "ospfEnabled": True,
+ "ipAddress": "10.0.1.2",
+ "ospfIfType": "Broadcast",
+ "opaqueCapable": False,
+ }
+ }
+ }
+ r2_interface_with_opaque = {
+ "interfaces": {
+ "r2-eth0": {
+ "ifUp": True,
+ "ospfEnabled": True,
+ "ipAddress": "10.0.1.2",
+ "ospfIfType": "Broadcast",
+ "opaqueCapable": True,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf interface json", r2_interface_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF interface has opaque capability disabled"
+ assert result is None, assertmsg
+
+ # STEP 8 in test_ospf_opaque_interface_disable and STEP 63 in CI tests
+ step("Install opaque LSAs on r1")
+ pread = r2.popen(
+ ["/usr/bin/timeout", "120", apibin, "-v", "--logtag=READER", "wait,120"],
+ encoding=None, # don't buffer
+ stdin=subprocess.DEVNULL,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ p = r1.popen(
+ [
+ apibin,
+ "-v",
+ "add,9,10.0.1.1,230,1,feedaceedeadbeef",
+ "add,10,1.2.3.4,231,1,feedaceecafebeef",
+ "add,11,232,1,feedaceebaddbeef",
+ "wait,20",
+ ]
+ )
+ opaque_LSAs_in_database = {
+ "areas": {
+ "1.2.3.4": {
+ "linkLocalOpaqueLsa": [
+ {
+ "lsId": "230.0.0.1",
+ "advertisedRouter": "1.0.0.0",
+ "sequenceNumber": "80000001",
+ },
+ ],
+ "linkLocalOpaqueLsaCount": 1,
+ "areaLocalOpaqueLsa": [
+ {
+ "lsId": "231.0.0.1",
+ "advertisedRouter": "1.0.0.0",
+ "sequenceNumber": "80000001",
+ },
+ ],
+ "areaLocalOpaqueLsaCount": 1,
+ },
+ },
+ "asExternalOpaqueLsa": [
+ {
+ "lsId": "232.0.0.1",
+ "advertisedRouter": "1.0.0.0",
+ "sequenceNumber": "80000001",
+ },
+ ],
+ "asExternalOpaqueLsaCount": 1,
+ }
+ opaque_area_empty_database = {
+ "routerId":"2.0.0.0",
+ "areaLocalOpaqueLsa":{
+ "areas":{
+ "1.2.3.4":[
+ ]
+ }
+ }
+ }
+
+ # STEP 9 in test_ospf_opaque_interface_disable and STEP 64 in CI tests
+ step("Check that LSAs are added on r1")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf database json", opaque_LSAs_in_database
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF database doesn't contain opaque LSAs"
+ assert result is None, assertmsg
+
+ # STEP 10 in test_ospf_opaque_interface_disable and STEP 65 in CI tests
+ step("Check that LSAs are not added on r2")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf database opaque-area json",
+ opaque_area_empty_database, True
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF area database contains opaque LSAs"
+ assert result is None, assertmsg
+
+ # STEP 11 in test_ospf_opaque_interface_disable and STEP 66 in CI tests
+ step("Enable OSPF opaque LSA Copability on r1's interface to r2")
+ r1.vtysh_multicmd("conf t\ninterface r1-eth0\nip ospf capability opaque")
+ time.sleep(15)
+
+ # STEP 12 in test_ospf_opaque_interface_disable and STEP 67 in CI tests
+ step("Verify no r1 configuration of 'no ip ospf capability opaque'")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False
+ )
+ assertmsg = "'no ip ospf capability opaque' not applied, but not present in r1 configuration"
+ assert rc, assertmsg
+
+ # STEP 13 in test_ospf_opaque_interface_disable and STEP 68 in CI tests
+ step("Verify the ospf opaque option is applied to the r1 interface")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf interface json", r1_interface_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF interface doesn't have opaque capability disabled"
+ assert result is None, assertmsg
+
+ r1_neighbor_with_opaque = {
+ "neighbors": {
+ "2.0.0.0": [
+ {
+ "optionsList": "*|O|-|-|-|-|E|-",
+ }
+ ]
+ }
+ }
+ r2_neighbor_with_opaque = {
+ "neighbors": {
+ "1.0.0.0": [
+ {
+ "optionsList": "*|O|-|-|-|-|E|-",
+ }
+ ]
+ }
+ }
+ # STEP 14 in test_ospf_opaque_interface_disable and STEP 69 in CI tests
+ step("Verify that the r1 neighbor options include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor detail json", r1_neighbor_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF neighbor doesn't have opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 15 in test_ospf_opaque_interface_disable and STEP 70 in CI tests
+ step("Verify that the r2 neighbor options include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf neighbor detail json", r2_neighbor_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF neighbor doesn't have opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 16 in test_ospf_opaque_interface_disable and STEP 71 in CI tests
+ step("Check that LSAs are now added to r2")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf database json", opaque_LSAs_in_database
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF database doesn't contains opaque LSAs"
+ assert result is None, assertmsg
+
+ # STEP 17 in test_ospf_opaque_interface_disable and STEP 72 in CI tests
+ step(
+ "Disable Opaque Capability on r2's interface to r1 using the interface address"
+ )
+ r2.vtysh_multicmd(
+ "conf t\ninterface r2-eth0\nno ip ospf capability opaque 10.0.1.2"
+ )
+
+ # STEP 18 in test_ospf_opaque_interface_disable and STEP 73 in CI tests
+ step("Clear the OSPF process on r2 to clear the OSPF LSDB")
+ r2.vtysh_multicmd("clear ip ospf process")
+ time.sleep(15)
+
+ # STEP 19 in test_ospf_opaque_interface_disable and STEP 74 in CI tests
+ step("Verify the r2 configuration of 'no ip ospf capability opaque 10.0.1.2'")
+ no_capability_opaque_cfg = (
+ tgen.net["r2"]
+ .cmd_nostatus(
+ 'vtysh -c "show running ospfd" | grep "^ no ip ospf capability opaque 10.0.1.2"'
+ )
+ .rstrip()
+ )
+ assertmsg = "'no ip ospf capability opaque 10.0.1.2' applied, but not present in configuration"
+ assert (
+ no_capability_opaque_cfg == " no ip ospf capability opaque 10.0.1.2"
+ ), assertmsg
+
+ # STEP 20 in test_ospf_opaque_interface_disable and STEP 75 in CI tests
+ step("Verify the ospf opaque option is not applied to the r2 interface")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf interface json", r2_interface_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF interface doesn't have opaque capability disabled"
+ assert result is None, assertmsg
+
+ # STEP 21 in test_ospf_opaque_interface_disable and STEP 76 in CI tests
+ step("Verify that the r1 neighbor options don't include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor detail json", r1_neighbor_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF neighbor has opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 22 in test_ospf_opaque_interface_disable and STEP 77 in CI tests
+ step("Verify that the r2 neighbor options don't include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf neighbor detail json", r2_neighbor_without_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF neighbor has opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 23 in test_ospf_opaque_interface_disable and STEP 78 in CI tests
+ step("Verify that r1 still has the opaque LSAs")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf database json", opaque_LSAs_in_database
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF database doesn't contain opaque LSAs"
+ assert result is None, assertmsg
+
+ # STEP 24 in test_ospf_opaque_interface_disable and STEP 79 in CI tests
+ step("Verify that r2 doesn't have the opaque LSAs")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf database opaque-area json",
+ opaque_area_empty_database, True
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF area database contains opaque LSAs"
+ assert result is None, assertmsg
+
+ # STEP 25 in test_ospf_opaque_interface_disable and STEP 80 in CI tests
+ step("Remove the 'no ip ospf capability opaque 10.0.1.2' config from r2 ")
+ r2.vtysh_multicmd(
+ "conf t\ninterface r2-eth0\nip ospf capability opaque 10.0.1.2"
+ )
+ time.sleep(15)
+
+ # STEP 26 in test_ospf_opaque_interface_disable and STEP 81 in CI tests
+ step("Verify the r2 removal of 'no ip ospf capability opaque 10.0.1.2'")
+ rc, _, _ = tgen.net["r2"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False
+ )
+ assertmsg = "'no ip ospf capability opaque' not applied, but not present in r2 configuration"
+ assert rc, assertmsg
+
+ # STEP 27 in test_ospf_opaque_interface_disable and STEP 82 in CI tests
+ step("Verify the ospf opaque option is applied to the r2 interface")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf interface json", r2_interface_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF interface doesn't have opaque capability disabled"
+ assert result is None, assertmsg
+
+ # STEP 28 in test_ospf_opaque_interface_disable and STEP 83 in CI tests
+ step("Verify that the r2 neighbor options include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf neighbor detail json", r2_neighbor_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF neighbor doesn't have opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 29 in test_ospf_opaque_interface_disable and STEP 84 in CI tests
+ step("Verify that the r1 neighbor options include opaque")
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor detail json", r1_neighbor_with_opaque
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r1 OSPF neighbor doesn't have opaque option in optionsList"
+ assert result is None, assertmsg
+
+ # STEP 30 in test_ospf_opaque_interface_disable and STEP 85 in CLI tests
+ step("Verify that r2 now has the opaque LSAs")
+ test_func = partial(
+ topotest.router_json_cmp, r2, "show ip ospf database json", opaque_LSAs_in_database
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "r2 OSPF database doesn't contain opaque LSAs"
+ assert result is None, assertmsg
+
+ except Exception:
+ if p:
+ p.terminate()
+ if p.wait():
+ comm_error(p)
+ p = None
+ raise
+ finally:
+ if pread:
+ pread.terminate()
+ pread.wait()
+ if p:
+ p.terminate()
+ p.wait()
+
+
+@pytest.mark.parametrize("tgen", [2], indirect=True)
+def test_ospf_opaque_interface_disable(tgen):
+ apibin = os.path.join(CLIENTDIR, "ospfclient.py")
+ rc, o, e = tgen.gears["r2"].net.cmd_status([apibin, "--help"])
+ logging.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", apibin, rc, o, e)
+ _test_opaque_interface_disable(tgen, apibin)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py
index c45ac82d30..05036fa7ad 100644
--- a/tests/topotests/zebra_rib/test_zebra_rib.py
+++ b/tests/topotests/zebra_rib/test_zebra_rib.py
@@ -255,7 +255,7 @@ def test_route_map_usage():
)
ok, result = topotest.run_and_expect(
- check_static_map_correct_runs, "", count=5, wait=1
+ check_static_map_correct_runs, "", count=10, wait=1
)
assert ok, result
@@ -275,7 +275,7 @@ def test_route_map_usage():
)
ok, result = topotest.run_and_expect(
- check_sharp_map_correct_runs, "", count=5, wait=1
+ check_sharp_map_correct_runs, "", count=10, wait=1
)
assert ok, result
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index 69a986ba0d..3a7561cb69 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1577,11 +1577,31 @@ def compare_context_objects(newconf, running):
pcclist_to_del = []
candidates_to_add = []
delete_bgpd = False
+ area_stub_no_sum = "area (\S+) stub no-summary"
# Find contexts that are in newconf but not in running
# Find contexts that are in running but not in newconf
for (running_ctx_keys, running_ctx) in iteritems(running.contexts):
+ if running_ctx_keys in newconf.contexts:
+ newconf_ctx = newconf.contexts[running_ctx_keys]
+
+ for line in running_ctx.lines:
+ # ospf area <> stub no-summary line removal requires
+ # to remoe area <> stub as no form of original
+ # retains the stub form.
+ # lines_to_del will contain:
+ # no area <x> stub no-summary and
+ # no area <x> stub
+ if (
+ running_ctx_keys[0].startswith("router ospf")
+ and line not in newconf_ctx.dlines
+ ):
+ re_area_stub_no_sum = re.search(area_stub_no_sum, line)
+ if re_area_stub_no_sum:
+ new_del_line = "area %s stub" % re_area_stub_no_sum.group(1)
+ lines_to_del.append((running_ctx_keys, new_del_line))
+
if running_ctx_keys not in newconf.contexts:
# We check that the len is 1 here so that we only look at ('router bgp 10')
diff --git a/zebra/interface.c b/zebra/interface.c
index e923c0a187..989763d13c 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -610,6 +610,11 @@ void if_add_update(struct interface *ifp)
if_addr_wakeup(ifp);
+ if (if_data->mpls_config == IF_ZEBRA_DATA_ON)
+ dplane_intf_mpls_modify_state(ifp, true);
+ else if (if_data->mpls_config == IF_ZEBRA_DATA_OFF)
+ dplane_intf_mpls_modify_state(ifp, false);
+
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"interface %s vrf %s(%u) index %d becomes active.",
@@ -1368,6 +1373,13 @@ static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx,
bool pd_reason_val;
bool down;
+ if (!ifp) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: Can't find ifp", __func__);
+
+ return;
+ }
+
dp_res = dplane_ctx_get_status(ctx);
pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx);
down = dplane_ctx_intf_is_protodown(ctx);
@@ -1444,7 +1456,7 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
linkdown_set = &zrouter.default_linkdownv6;
}
} else {
- zif = ifp ? ifp->info : NULL;
+ zif = ifp->info;
if (!zif) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -1524,10 +1536,16 @@ static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex,
if (exist_id != VRF_DEFAULT) {
vrf = vrf_lookup_by_id(exist_id);
- flog_err(
- EC_ZEBRA_VRF_MISCONFIGURED,
- "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
- name, ifindex, vrf->name, vrf->vrf_id);
+ if (vrf)
+ flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
+ "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
+ name, ifindex, vrf->name,
+ vrf->vrf_id);
+ else
+ flog_err(EC_ZEBRA_VRF_NOT_FOUND,
+ "VRF %s id %u does not exist",
+ name, ifindex);
+
exit(-1);
}
}
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index f0d4427688..c98f1ce60c 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -1289,18 +1289,15 @@ int netlink_request(struct nlsock *nl, void *req)
return 0;
}
-static int nl_batch_read_resp(struct nl_batch *bth)
+static int nl_batch_read_resp(struct nl_batch *bth, struct nlsock *nl)
{
struct nlmsghdr *h;
struct sockaddr_nl snl;
struct msghdr msg = {};
int status, seq;
- struct nlsock *nl;
struct zebra_dplane_ctx *ctx;
bool ignore_msg;
- nl = kernel_netlink_nlsock_lookup(bth->zns->sock);
-
msg.msg_name = (void *)&snl;
msg.msg_namelen = sizeof(snl);
@@ -1493,7 +1490,7 @@ static void nl_batch_send(struct nl_batch *bth)
err = true;
if (!err) {
- if (nl_batch_read_resp(bth) == -1)
+ if (nl_batch_read_resp(bth, nl) == -1)
err = true;
}
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 47ecbc0b44..11b7b7cf82 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -256,12 +256,11 @@ void redistribute_delete(const struct route_node *rn,
table = new_re->table;
}
- zlog_debug(
- "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
- vrfid, table, rn, old_re, old_inst,
- old_re ? zebra_route_string(old_re->type) : "None",
- new_re, new_inst,
- new_re ? zebra_route_string(new_re->type) : "None");
+ zlog_debug("(%u:%u):%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
+ vrfid, table, rn, old_re, old_inst,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re, new_inst,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Skip invalid (e.g. linklocal) prefix */
diff --git a/zebra/rib.h b/zebra/rib.h
index 65cc1ffab9..64bbaf3e76 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -167,6 +167,10 @@ struct route_entry {
#define RIB_KERNEL_ROUTE(R) RKERNEL_ROUTE((R)->type)
+/* Define route types that are equivalent to "connected". */
+#define RIB_CONNECTED_ROUTE(R) \
+ ((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_NHRP)
+
/* meta-queue structure:
* sub-queue 0: nexthop group objects
* sub-queue 1: EVPN/VxLAN objects
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index e44f6ee4e0..bb507893b0 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2392,7 +2392,10 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
continue;
}
- if ((match->type == ZEBRA_ROUTE_CONNECT) ||
+ /* If the candidate match's type is considered "connected",
+ * we consider it first.
+ */
+ if (RIB_CONNECTED_ROUTE(match) ||
(RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type))) {
match = zebra_nhg_connected_ifindex(rn, match,
nexthop->ifindex);
@@ -2413,6 +2416,10 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
return 0;
}
+ /* NHRP special case: need to indicate onlink */
+ if (match->type == ZEBRA_ROUTE_NHRP)
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
+
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug(
"%s: CONNECT match %p (%pNG), newhop %pNHv",