mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-17 19:05:44 +00:00
commit
effd4c7bdd
@ -2059,7 +2059,8 @@ void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
void ospf_apiserver_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct opaque_lsa {
|
struct opaque_lsa {
|
||||||
struct lsa_header header;
|
struct lsa_header header;
|
||||||
@ -2070,6 +2071,9 @@ void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
|||||||
struct opaque_lsa *olsa;
|
struct opaque_lsa *olsa;
|
||||||
int opaquelen;
|
int opaquelen;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
olsa = (struct opaque_lsa *)lsa->data;
|
olsa = (struct opaque_lsa *)lsa->data;
|
||||||
|
|
||||||
if (VALID_OPAQUE_INFO_LEN(lsa->data))
|
if (VALID_OPAQUE_INFO_LEN(lsa->data))
|
||||||
|
@ -182,7 +182,8 @@ extern void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr,
|
|||||||
extern void ospf_apiserver_config_write_router(struct vty *vty);
|
extern void ospf_apiserver_config_write_router(struct vty *vty);
|
||||||
extern void ospf_apiserver_config_write_if(struct vty *vty,
|
extern void ospf_apiserver_config_write_if(struct vty *vty,
|
||||||
struct interface *ifp);
|
struct interface *ifp);
|
||||||
extern void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
extern void ospf_apiserver_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
extern int ospf_ospf_apiserver_lsa_originator(void *arg);
|
extern int ospf_ospf_apiserver_lsa_originator(void *arg);
|
||||||
extern struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa);
|
extern struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa);
|
||||||
extern void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
|
extern void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
|
||||||
|
@ -80,7 +80,8 @@ static struct ospf_ext_lp OspfEXT;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Extended Prefix Opaque LSA related callback functions */
|
/* Extended Prefix Opaque LSA related callback functions */
|
||||||
static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
static int ospf_ext_pref_lsa_originate(void *arg);
|
static int ospf_ext_pref_lsa_originate(void *arg);
|
||||||
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa);
|
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa);
|
||||||
static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
|
static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti,
|
||||||
@ -90,7 +91,8 @@ static int ospf_ext_link_new_if(struct interface *ifp);
|
|||||||
static int ospf_ext_link_del_if(struct interface *ifp);
|
static int ospf_ext_link_del_if(struct interface *ifp);
|
||||||
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status);
|
static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status);
|
||||||
static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status);
|
static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status);
|
||||||
static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
static int ospf_ext_link_lsa_originate(void *arg);
|
static int ospf_ext_link_lsa_originate(void *arg);
|
||||||
static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa);
|
static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa);
|
||||||
static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
|
static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
|
||||||
@ -1846,12 +1848,16 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extended Link TLVs */
|
/* Extended Link TLVs */
|
||||||
static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct lsa_header *lsah = lsa->data;
|
struct lsa_header *lsah = lsa->data;
|
||||||
struct tlv_header *tlvh;
|
struct tlv_header *tlvh;
|
||||||
uint16_t length = 0, sum = 0;
|
uint16_t length = 0, sum = 0;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Initialize TLV browsing */
|
/* Initialize TLV browsing */
|
||||||
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
||||||
|
|
||||||
@ -1932,12 +1938,16 @@ static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extended Prefix TLVs */
|
/* Extended Prefix TLVs */
|
||||||
static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct lsa_header *lsah = lsa->data;
|
struct lsa_header *lsah = lsa->data;
|
||||||
struct tlv_header *tlvh;
|
struct tlv_header *tlvh;
|
||||||
uint16_t length = 0, sum = 0;
|
uint16_t length = 0, sum = 0;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Initialize TLV browsing */
|
/* Initialize TLV browsing */
|
||||||
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
||||||
|
|
||||||
|
@ -75,7 +75,8 @@ static const char * const ospf_rejected_reason_desc[] = {
|
|||||||
"Router is in the process of graceful restart",
|
"Router is in the process of graceful restart",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa);
|
static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr);
|
static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr);
|
||||||
|
|
||||||
static unsigned int ospf_enable_rtr_hash_key(const void *data)
|
static unsigned int ospf_enable_rtr_hash_key(const void *data)
|
||||||
@ -1012,7 +1013,8 @@ void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf,
|
|||||||
* Returns:
|
* Returns:
|
||||||
* Nothing.
|
* Nothing.
|
||||||
*/
|
*/
|
||||||
static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
|
static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct lsa_header *lsah = NULL;
|
struct lsa_header *lsah = NULL;
|
||||||
struct tlv_header *tlvh = NULL;
|
struct tlv_header *tlvh = NULL;
|
||||||
@ -1022,6 +1024,9 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
|
|||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
lsah = (struct lsa_header *)lsa->data;
|
lsah = (struct lsa_header *)lsa->data;
|
||||||
|
|
||||||
if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
|
if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
|
||||||
|
@ -274,7 +274,8 @@ struct ospf_opaque_functab {
|
|||||||
void (*config_write_router)(struct vty *vty);
|
void (*config_write_router)(struct vty *vty);
|
||||||
void (*config_write_if)(struct vty *vty, struct interface *ifp);
|
void (*config_write_if)(struct vty *vty, struct interface *ifp);
|
||||||
void (*config_write_debug)(struct vty *vty);
|
void (*config_write_debug)(struct vty *vty);
|
||||||
void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa);
|
void (*show_opaque_info)(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
int (*lsa_originator)(void *arg);
|
int (*lsa_originator)(void *arg);
|
||||||
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa);
|
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa);
|
||||||
int (*new_lsa_hook)(struct ospf_lsa *lsa);
|
int (*new_lsa_hook)(struct ospf_lsa *lsa);
|
||||||
@ -373,7 +374,8 @@ int ospf_register_opaque_functab(
|
|||||||
void (*config_write_router)(struct vty *vty),
|
void (*config_write_router)(struct vty *vty),
|
||||||
void (*config_write_if)(struct vty *vty, struct interface *ifp),
|
void (*config_write_if)(struct vty *vty, struct interface *ifp),
|
||||||
void (*config_write_debug)(struct vty *vty),
|
void (*config_write_debug)(struct vty *vty),
|
||||||
void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa),
|
void (*show_opaque_info)(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa),
|
||||||
int (*lsa_originator)(void *arg),
|
int (*lsa_originator)(void *arg),
|
||||||
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa),
|
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa),
|
||||||
int (*new_lsa_hook)(struct ospf_lsa *lsa),
|
int (*new_lsa_hook)(struct ospf_lsa *lsa),
|
||||||
@ -1182,6 +1184,16 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa,
|
|||||||
VALID_OPAQUE_INFO_LEN(lsah)
|
VALID_OPAQUE_INFO_LEN(lsah)
|
||||||
? ""
|
? ""
|
||||||
: "(Invalid length?)");
|
: "(Invalid length?)");
|
||||||
|
} else {
|
||||||
|
json_object_string_add(
|
||||||
|
json, "opaqueType",
|
||||||
|
ospf_opaque_type_name(opaque_type));
|
||||||
|
json_object_int_add(json, "opaqueId", opaque_id);
|
||||||
|
json_object_int_add(json, "opaqueDataLength",
|
||||||
|
ntohs(lsah->length)
|
||||||
|
- OSPF_LSA_HEADER_SIZE);
|
||||||
|
json_object_boolean_add(json, "opaqueDataLengthValid",
|
||||||
|
VALID_OPAQUE_INFO_LEN(lsah));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zlog_debug(" Opaque-Type %u (%s)", opaque_type,
|
zlog_debug(" Opaque-Type %u (%s)", opaque_type,
|
||||||
@ -1197,7 +1209,7 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa,
|
|||||||
/* Call individual output functions. */
|
/* Call individual output functions. */
|
||||||
if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL)
|
if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL)
|
||||||
if (functab->show_opaque_info != NULL)
|
if (functab->show_opaque_info != NULL)
|
||||||
(*functab->show_opaque_info)(vty, lsa);
|
(*functab->show_opaque_info)(vty, json, lsa);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,8 @@ extern int ospf_register_opaque_functab(
|
|||||||
void (*config_write_router)(struct vty *vty),
|
void (*config_write_router)(struct vty *vty),
|
||||||
void (*config_write_if)(struct vty *vty, struct interface *ifp),
|
void (*config_write_if)(struct vty *vty, struct interface *ifp),
|
||||||
void (*config_write_debug)(struct vty *vty),
|
void (*config_write_debug)(struct vty *vty),
|
||||||
void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa),
|
void (*show_opaque_info)(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa),
|
||||||
int (*lsa_originator)(void *arg),
|
int (*lsa_originator)(void *arg),
|
||||||
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa),
|
struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa),
|
||||||
int (*new_lsa_hook)(struct ospf_lsa *lsa),
|
int (*new_lsa_hook)(struct ospf_lsa *lsa),
|
||||||
|
@ -73,7 +73,9 @@ static struct ospf_router_info OspfRI;
|
|||||||
static void ospf_router_info_ism_change(struct ospf_interface *oi,
|
static void ospf_router_info_ism_change(struct ospf_interface *oi,
|
||||||
int old_status);
|
int old_status);
|
||||||
static void ospf_router_info_config_write_router(struct vty *vty);
|
static void ospf_router_info_config_write_router(struct vty *vty);
|
||||||
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
static void ospf_router_info_show_info(struct vty *vty,
|
||||||
|
struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
static int ospf_router_info_lsa_originate(void *arg);
|
static int ospf_router_info_lsa_originate(void *arg);
|
||||||
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
|
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
|
||||||
static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
|
static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
|
||||||
@ -1552,12 +1554,17 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
|
|||||||
return TLV_SIZE(tlvh);
|
return TLV_SIZE(tlvh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
static void ospf_router_info_show_info(struct vty *vty,
|
||||||
|
struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct lsa_header *lsah = lsa->data;
|
struct lsa_header *lsah = lsa->data;
|
||||||
struct tlv_header *tlvh;
|
struct tlv_header *tlvh;
|
||||||
uint16_t length = 0, sum = 0;
|
uint16_t length = 0, sum = 0;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Initialize TLV browsing */
|
/* Initialize TLV browsing */
|
||||||
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
length = lsa->size - OSPF_LSA_HEADER_SIZE;
|
||||||
|
|
||||||
|
@ -87,7 +87,8 @@ static int ospf_mpls_te_del_if(struct interface *ifp);
|
|||||||
static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
|
static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status);
|
||||||
static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
|
static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status);
|
||||||
static void ospf_mpls_te_config_write_router(struct vty *vty);
|
static void ospf_mpls_te_config_write_router(struct vty *vty);
|
||||||
static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa);
|
static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa);
|
||||||
static int ospf_mpls_te_lsa_originate_area(void *arg);
|
static int ospf_mpls_te_lsa_originate_area(void *arg);
|
||||||
static int ospf_mpls_te_lsa_inter_as_as(void *arg);
|
static int ospf_mpls_te_lsa_inter_as_as(void *arg);
|
||||||
static int ospf_mpls_te_lsa_inter_as_area(void *arg);
|
static int ospf_mpls_te_lsa_inter_as_area(void *arg);
|
||||||
@ -3783,7 +3784,8 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct lsa_header *lsah = lsa->data;
|
struct lsa_header *lsah = lsa->data;
|
||||||
struct tlv_header *tlvh, *next;
|
struct tlv_header *tlvh, *next;
|
||||||
@ -3791,6 +3793,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
|||||||
uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
|
uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh,
|
||||||
uint16_t subtotal, uint16_t total) = NULL;
|
uint16_t subtotal, uint16_t total) = NULL;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
return;
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
total = lsa->size - OSPF_LSA_HEADER_SIZE;
|
total = lsa->size - OSPF_LSA_HEADER_SIZE;
|
||||||
|
|
||||||
|
@ -171,14 +171,60 @@ def router_compare_json_output(rname, command, reference, tries):
|
|||||||
assert diff is None, assertmsg
|
assert diff is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
def expect_grace_lsa(restarting, helper):
|
||||||
|
"""
|
||||||
|
Check if the given helper neighbor has already received a Grace-LSA from
|
||||||
|
the router performing a graceful restart.
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"'{}': checking if a Grace-LSA was received from '{}'".format(
|
||||||
|
helper, restarting
|
||||||
|
)
|
||||||
|
)
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
tgen.gears[helper],
|
||||||
|
"show ipv6 ospf6 database json",
|
||||||
|
{
|
||||||
|
"interfaceScopedLinkStateDb": [
|
||||||
|
{
|
||||||
|
"lsa": [
|
||||||
|
{
|
||||||
|
"type": "GR",
|
||||||
|
"advRouter": restarting,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||||
|
assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting)
|
||||||
|
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
||||||
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
|
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
|
||||||
# Check the RIB first, which should be preserved across restarts in
|
# Check the RIB first, which should be preserved across restarts in
|
||||||
# all routers of the routing domain.
|
# all routers of the routing domain.
|
||||||
|
# If we are not on initial convergence *but* we are checking
|
||||||
|
# after a restart. Looking in the zebra rib for installed
|
||||||
|
# is a recipe for test failure. Why? because if we are restarting
|
||||||
|
# then ospf is in the process of establishing neighbors and passing
|
||||||
|
# new routes to zebra. Zebra will not mark the route as installed
|
||||||
|
# when it receives a replacement from ospf until it has finished
|
||||||
|
# processing it. Let's give it a few seconds to allow this to happen
|
||||||
|
# under load.
|
||||||
if initial_convergence == True:
|
if initial_convergence == True:
|
||||||
tries = 240
|
tries = 240
|
||||||
else:
|
else:
|
||||||
tries = 1
|
if restarting != None:
|
||||||
|
tries = 40
|
||||||
|
else:
|
||||||
|
tries = 1
|
||||||
router_compare_json_output(
|
router_compare_json_output(
|
||||||
rname, "show ipv6 route ospf json", "show_ipv6_route.json", tries
|
rname, "show ipv6 route ospf json", "show_ipv6_route.json", tries
|
||||||
)
|
)
|
||||||
@ -212,6 +258,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_gr_is_in_zebra(rname):
|
||||||
|
retry = True
|
||||||
|
retry_times = 10
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
while retry and retry_times > 0:
|
||||||
|
out = tgen.net[rname].cmd(
|
||||||
|
'vtysh -c "show zebra client" | grep "Client: ospf6$" -A 40 | grep "Capabilities "'
|
||||||
|
)
|
||||||
|
|
||||||
|
if "Graceful Restart" not in out:
|
||||||
|
sleep(2)
|
||||||
|
retry_times -= 1
|
||||||
|
else:
|
||||||
|
retry = False
|
||||||
|
|
||||||
|
assertmsg = "%s does not appear to have Graceful Restart setup" % rname
|
||||||
|
assert not retry and retry_times > 0, assertmsg
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test initial network convergence
|
# Test initial network convergence
|
||||||
#
|
#
|
||||||
@ -238,10 +304,10 @@ def test_gr_rt1():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="1.1.1.1", helper="rt2")
|
||||||
|
ensure_gr_is_in_zebra("rt1")
|
||||||
kill_router_daemons(tgen, "rt1", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt1", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt1")
|
check_routers(exiting="rt1")
|
||||||
|
|
||||||
start_router_daemons(tgen, "rt1", ["ospf6d"])
|
start_router_daemons(tgen, "rt1", ["ospf6d"])
|
||||||
check_routers(restarting="rt1")
|
check_routers(restarting="rt1")
|
||||||
|
|
||||||
@ -258,7 +324,9 @@ def test_gr_rt2():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="2.2.2.2", helper="rt1")
|
||||||
|
expect_grace_lsa(restarting="2.2.2.2", helper="rt3")
|
||||||
|
ensure_gr_is_in_zebra("rt2")
|
||||||
kill_router_daemons(tgen, "rt2", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt2", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt2")
|
check_routers(exiting="rt2")
|
||||||
|
|
||||||
@ -278,7 +346,10 @@ def test_gr_rt3():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="3.3.3.3", helper="rt2")
|
||||||
|
expect_grace_lsa(restarting="3.3.3.3", helper="rt4")
|
||||||
|
expect_grace_lsa(restarting="3.3.3.3", helper="rt6")
|
||||||
|
ensure_gr_is_in_zebra("rt3")
|
||||||
kill_router_daemons(tgen, "rt3", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt3", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt3")
|
check_routers(exiting="rt3")
|
||||||
|
|
||||||
@ -298,7 +369,9 @@ def test_gr_rt4():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="4.4.4.4", helper="rt3")
|
||||||
|
expect_grace_lsa(restarting="4.4.4.4", helper="rt5")
|
||||||
|
ensure_gr_is_in_zebra("rt4")
|
||||||
kill_router_daemons(tgen, "rt4", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt4", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt4")
|
check_routers(exiting="rt4")
|
||||||
|
|
||||||
@ -318,7 +391,8 @@ def test_gr_rt5():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="5.5.5.5", helper="rt4")
|
||||||
|
ensure_gr_is_in_zebra("rt5")
|
||||||
kill_router_daemons(tgen, "rt5", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt5", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt5")
|
check_routers(exiting="rt5")
|
||||||
|
|
||||||
@ -338,7 +412,9 @@ def test_gr_rt6():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="6.6.6.6", helper="rt3")
|
||||||
|
expect_grace_lsa(restarting="6.6.6.6", helper="rt7")
|
||||||
|
ensure_gr_is_in_zebra("rt6")
|
||||||
kill_router_daemons(tgen, "rt6", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt6", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt6")
|
check_routers(exiting="rt6")
|
||||||
|
|
||||||
@ -358,7 +434,8 @@ def test_gr_rt7():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"')
|
||||||
sleep(5)
|
expect_grace_lsa(restarting="6.6.6.6", helper="rt6")
|
||||||
|
ensure_gr_is_in_zebra("rt7")
|
||||||
kill_router_daemons(tgen, "rt7", ["ospf6d"], save_config=False)
|
kill_router_daemons(tgen, "rt7", ["ospf6d"], save_config=False)
|
||||||
check_routers(exiting="rt7")
|
check_routers(exiting="rt7")
|
||||||
|
|
||||||
|
@ -180,14 +180,60 @@ def router_compare_json_output(rname, command, reference, tries):
|
|||||||
assert diff is None, assertmsg
|
assert diff is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
def expect_grace_lsa(restarting, area, helper):
|
||||||
|
"""
|
||||||
|
Check if the given helper neighbor has already received a Grace-LSA from
|
||||||
|
the router performing a graceful restart.
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"'{}': checking if a Grace-LSA was received from '{}'".format(
|
||||||
|
helper, restarting
|
||||||
|
)
|
||||||
|
)
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
tgen.gears[helper],
|
||||||
|
"show ip ospf database opaque-link json",
|
||||||
|
{
|
||||||
|
"linkLocalOpaqueLsa": {
|
||||||
|
"areas": {
|
||||||
|
area: [
|
||||||
|
{
|
||||||
|
"advertisingRouter": restarting,
|
||||||
|
"opaqueType": "Grace-LSA",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||||
|
assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting)
|
||||||
|
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
|
||||||
def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
||||||
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
|
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
|
||||||
# Check the RIB first, which should be preserved across restarts in
|
# Check the RIB first, which should be preserved across restarts in
|
||||||
# all routers of the routing domain.
|
# all routers of the routing domain.
|
||||||
|
# If we are not on initial convergence *but* we are checking
|
||||||
|
# after a restart. Looking in the zebra rib for installed
|
||||||
|
# is a recipe for test failure. Why? because if we are restarting
|
||||||
|
# then ospf is in the process of establishing neighbors and passing
|
||||||
|
# new routes to zebra. Zebra will not mark the route as installed
|
||||||
|
# when it receives a replacement from ospf until it has finished
|
||||||
|
# processing it. Let's give it a few seconds to allow this to happen
|
||||||
|
# under load.
|
||||||
if initial_convergence == True:
|
if initial_convergence == True:
|
||||||
tries = 240
|
tries = 240
|
||||||
else:
|
else:
|
||||||
tries = 1
|
if restarting != None:
|
||||||
|
tries = 40
|
||||||
|
else:
|
||||||
|
tries = 1
|
||||||
router_compare_json_output(
|
router_compare_json_output(
|
||||||
rname, "show ip route ospf json", "show_ip_route.json", tries
|
rname, "show ip route ospf json", "show_ip_route.json", tries
|
||||||
)
|
)
|
||||||
@ -215,6 +261,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_gr_is_in_zebra(rname):
|
||||||
|
retry = True
|
||||||
|
retry_times = 10
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
while retry and retry_times > 0:
|
||||||
|
out = tgen.net[rname].cmd(
|
||||||
|
'vtysh -c "show zebra client" | grep "Client: ospf$" -A 40 | grep "Capabilities "'
|
||||||
|
)
|
||||||
|
|
||||||
|
if "Graceful Restart" not in out:
|
||||||
|
sleep(2)
|
||||||
|
retry_times -= 1
|
||||||
|
else:
|
||||||
|
retry = False
|
||||||
|
|
||||||
|
assertmsg = "%s does not appear to have Graceful Restart setup" % rname
|
||||||
|
assert not retry and retry_times > 0, assertmsg
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test initial network convergence
|
# Test initial network convergence
|
||||||
#
|
#
|
||||||
@ -241,7 +307,8 @@ def test_gr_rt1():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="1.1.1.1", area="0.0.0.1", helper="rt2")
|
||||||
|
ensure_gr_is_in_zebra("rt1")
|
||||||
kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt1")
|
check_routers(exiting="rt1")
|
||||||
|
|
||||||
@ -261,7 +328,9 @@ def test_gr_rt2():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.1", helper="rt1")
|
||||||
|
expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.0", helper="rt3")
|
||||||
|
ensure_gr_is_in_zebra("rt2")
|
||||||
kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt2")
|
check_routers(exiting="rt2")
|
||||||
|
|
||||||
@ -281,7 +350,10 @@ def test_gr_rt3():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt2")
|
||||||
|
expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt4")
|
||||||
|
expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt6")
|
||||||
|
ensure_gr_is_in_zebra("rt3")
|
||||||
kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt3")
|
check_routers(exiting="rt3")
|
||||||
|
|
||||||
@ -301,7 +373,9 @@ def test_gr_rt4():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.0", helper="rt3")
|
||||||
|
expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.2", helper="rt5")
|
||||||
|
ensure_gr_is_in_zebra("rt4")
|
||||||
kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt4")
|
check_routers(exiting="rt4")
|
||||||
|
|
||||||
@ -321,7 +395,8 @@ def test_gr_rt5():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="5.5.5.5", area="0.0.0.2", helper="rt4")
|
||||||
|
ensure_gr_is_in_zebra("rt5")
|
||||||
kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt5")
|
check_routers(exiting="rt5")
|
||||||
|
|
||||||
@ -341,7 +416,9 @@ def test_gr_rt6():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.0", helper="rt3")
|
||||||
|
expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.3", helper="rt7")
|
||||||
|
ensure_gr_is_in_zebra("rt6")
|
||||||
kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt6")
|
check_routers(exiting="rt6")
|
||||||
|
|
||||||
@ -361,7 +438,8 @@ def test_gr_rt7():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
|
||||||
sleep(3)
|
expect_grace_lsa(restarting="7.7.7.7", area="0.0.0.3", helper="rt6")
|
||||||
|
ensure_gr_is_in_zebra("rt7")
|
||||||
kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False)
|
kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False)
|
||||||
check_routers(exiting="rt7")
|
check_routers(exiting="rt7")
|
||||||
|
|
||||||
|
@ -1007,7 +1007,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
|||||||
char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
|
char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
|
||||||
time_t connect_time, last_read_time, last_write_time;
|
time_t connect_time, last_read_time, last_write_time;
|
||||||
uint32_t last_read_cmd, last_write_cmd;
|
uint32_t last_read_cmd, last_write_cmd;
|
||||||
struct client_gr_info *info = NULL;
|
|
||||||
|
|
||||||
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
|
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
|
||||||
if (client->instance)
|
if (client->instance)
|
||||||
@ -1100,22 +1099,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
|||||||
client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt);
|
client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt);
|
||||||
vty_out(vty, "Errors: %u\n", client->error_cnt);
|
vty_out(vty, "Errors: %u\n", client->error_cnt);
|
||||||
|
|
||||||
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
|
|
||||||
vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
|
|
||||||
vty_out(vty, "Capabilities : ");
|
|
||||||
switch (info->capabilities) {
|
|
||||||
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
|
||||||
vty_out(vty, "Graceful Restart\n");
|
|
||||||
break;
|
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
|
||||||
case ZEBRA_CLIENT_GR_DISABLE:
|
|
||||||
case ZEBRA_CLIENT_RIB_STALE_TIME:
|
|
||||||
vty_out(vty, "None\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined DEV_BUILD
|
#if defined DEV_BUILD
|
||||||
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
|
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
|
||||||
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
|
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
|
||||||
@ -1151,7 +1134,8 @@ static void zebra_show_stale_client_detail(struct vty *vty,
|
|||||||
vty_out(vty, "Capabilities : ");
|
vty_out(vty, "Capabilities : ");
|
||||||
switch (info->capabilities) {
|
switch (info->capabilities) {
|
||||||
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
||||||
vty_out(vty, "Graceful Restart\n");
|
vty_out(vty, "Graceful Restart(%u seconds)\n",
|
||||||
|
info->stale_removal_time);
|
||||||
break;
|
break;
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
||||||
|
Loading…
Reference in New Issue
Block a user