Merge pull request #8767 from opensourcerouting/ospfd-gr

ospfd: introduce support for Graceful Restart (restarting mode)
This commit is contained in:
Russ White 2021-07-13 06:39:53 -04:00 committed by GitHub
commit 000df71ccd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 5888 additions and 106 deletions

View file

@ -2514,6 +2514,7 @@ AC_SUBST([frr_statedir])
AC_DEFINE_UNQUOTED([LDPD_SOCKET], ["$frr_statedir%s%s/ldpd.sock"], [ldpd control socket])
AC_DEFINE_UNQUOTED([ZEBRA_SERV_PATH], ["$frr_statedir%s%s/zserv.api"], [zebra api socket])
AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir%s%s/bfdd.sock"], [bfdd control socket])
AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$frr_statedir%s/ospfd-gr.json"], [ospfd GR state information])
AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory])
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])

View file

@ -710,8 +710,17 @@ Redistribution
Graceful Restart Helper
=======================
Graceful Restart
================
.. clicmd:: graceful-restart [grace-period (1-1800)]
Configure Graceful Restart (RFC 3623) restarting support.
When enabled, the default grace period is 120 seconds.
To perform a graceful shutdown, the "graceful-restart prepare ip ospf"
EXEC-level command needs to be issued before restarting the ospfd daemon.
.. clicmd:: graceful-restart helper-only [A.B.C.D]
@ -743,6 +752,17 @@ Graceful Restart Helper
restarts. By default, it supports both planned and
unplanned outages.
.. clicmd:: graceful-restart prepare ip ospf
Initiate a graceful restart for all OSPF instances configured with the
"graceful-restart" command. The ospfd daemon should be restarted during
the instance-specific grace period, otherwise the graceful restart will fail.
This is an EXEC-level command.
.. _showing-ospf-information:
Showing Information

View file

@ -438,6 +438,8 @@ struct cmd_node {
#define BFD_PROFILE_STR "BFD profile.\n"
#define BFD_PROFILE_NAME_STR "BFD profile name.\n"
#define SHARP_STR "Sharp Routing Protocol\n"
#define OSPF_GR_STR \
"OSPF non-stop forwarding (NSF) also known as OSPF Graceful Restart\n"
#define CMD_VNI_RANGE "(1-16777215)"
#define CONF_BACKUP_EXT ".sav"

View file

@ -1694,6 +1694,9 @@ static void ospf_abr_manage_discard_routes(struct ospf *ospf)
static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
{
if (ospf->gr_info.restart_in_progress)
return;
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("Check for NSSA-ABR Tasks():");
@ -1758,6 +1761,9 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
summary-LSA origination and flooding. */
void ospf_abr_task(struct ospf *ospf)
{
if (ospf->gr_info.restart_in_progress)
return;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_abr_task(): Start");

View file

@ -609,6 +609,16 @@ static int ospf_ase_calculate_timer(struct thread *t)
+ (stop_time.tv_usec
- start_time.tv_usec));
}
/*
* Uninstall remnant routes that were installed before the restart, but
* that are no longer valid.
*/
if (ospf->gr_info.finishing_restart) {
ospf_zebra_gr_disable(ospf);
ospf->gr_info.finishing_restart = false;
}
return 0;
}

View file

@ -1552,21 +1552,16 @@ DEFUN(no_debug_ospf_ldp_sync,
return CMD_SUCCESS;
}
DEFPY (debug_ospf_gr,
debug_ospf_gr_cmd,
"[no$no] debug ospf graceful-restart helper",
NO_STR
DEBUG_STR OSPF_STR
"Gracefull restart\n"
"Helper Information\n")
DEFPY(debug_ospf_gr, debug_ospf_gr_cmd, "[no$no] debug ospf graceful-restart",
NO_STR DEBUG_STR OSPF_STR "OSPF Graceful Restart\n")
{
if (vty->node == CONFIG_NODE)
CONF_DEBUG_ON(gr, GR_HELPER);
CONF_DEBUG_ON(gr, GR);
if (!no)
TERM_DEBUG_ON(gr, GR_HELPER);
TERM_DEBUG_ON(gr, GR);
else
TERM_DEBUG_OFF(gr, GR_HELPER);
TERM_DEBUG_OFF(gr, GR);
return CMD_SUCCESS;
}
@ -1764,9 +1759,9 @@ static int show_debugging_ospf_common(struct vty *vty)
if (IS_DEBUG_OSPF(ldp_sync, LDP_SYNC) == OSPF_DEBUG_LDP_SYNC)
vty_out(vty, " OSPF ldp-sync debugging is on\n");
/* Show debug status for GR helper. */
if (IS_DEBUG_OSPF(gr, GR_HELPER) == OSPF_DEBUG_GR_HELPER)
vty_out(vty, " OSPF Graceful Restart Helper debugging is on\n");
/* Show debug status for GR. */
if (IS_DEBUG_OSPF(gr, GR) == OSPF_DEBUG_GR)
vty_out(vty, " OSPF Graceful Restart debugging is on\n");
if (IS_DEBUG_OSPF(bfd, BFD_LIB) == OSPF_DEBUG_BFD_LIB)
vty_out(vty,
@ -1953,9 +1948,9 @@ static int config_write_debug(struct vty *vty)
write = 1;
}
/* debug ospf gr helper */
if (IS_CONF_DEBUG_OSPF(gr, GR_HELPER) == OSPF_DEBUG_GR_HELPER) {
vty_out(vty, "debug ospf%s graceful-restart helper\n", str);
/* debug ospf gr */
if (IS_CONF_DEBUG_OSPF(gr, GR) == OSPF_DEBUG_GR) {
vty_out(vty, "debug ospf%s graceful-restart\n", str);
write = 1;
}

View file

@ -64,8 +64,7 @@
#define OSPF_DEBUG_DEFAULTINFO 0x20
#define OSPF_DEBUG_LDP_SYNC 0x40
#define OSPF_DEBUG_GR_HELPER 0x01
#define OSPF_DEBUG_GR 0x03
#define OSPF_DEBUG_GR 0x01
#define OSPF_DEBUG_BFD_LIB 0x01
@ -118,7 +117,7 @@
#define IS_DEBUG_OSPF_DEFAULT_INFO IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO)
#define IS_DEBUG_OSPF_LDP_SYNC IS_DEBUG_OSPF(ldp_sync, LDP_SYNC)
#define IS_DEBUG_OSPF_GR_HELPER IS_DEBUG_OSPF(gr, GR_HELPER)
#define IS_DEBUG_OSPF_GR IS_DEBUG_OSPF(gr, GR)
#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \
(conf_debug_ospf_packet[a] & OSPF_DEBUG_##b)

View file

@ -379,13 +379,13 @@ int ospf_flood(struct ospf *ospf, struct ospf_neighbor *nbr,
SET_FLAG(new->flags, OSPF_LSA_RECEIVED);
(void)ospf_lsa_is_self_originated(ospf, new); /* Let it set the flag */
/* Received Grace LSA */
if (IS_GRACE_LSA(new)) {
/* Received non-self-originated Grace LSA */
if (IS_GRACE_LSA(new) && !IS_LSA_SELF(new)) {
if (IS_LSA_MAXAGE(new)) {
/* Handling Max age grace LSA.*/
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Received a maxage GRACE-LSA from router %pI4",
__func__, &new->data->adv_router);
@ -393,21 +393,21 @@ int ospf_flood(struct ospf *ospf, struct ospf_neighbor *nbr,
if (current) {
ospf_process_maxage_grace_lsa(ospf, new, nbr);
} else {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Grace LSA doesn't exist in lsdb, so discarding grace lsa",
__func__);
return -1;
}
} else {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Received a GRACE-LSA from router %pI4",
__func__, &new->data->adv_router);
if (ospf_process_grace_lsa(ospf, new, nbr)
== OSPF_GR_NOT_HELPER) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Not moving to HELPER role, So discarding grace LSA",
__func__);
@ -445,9 +445,9 @@ int ospf_flood(struct ospf *ospf, struct ospf_neighbor *nbr,
}
/* OSPF LSA flooding -- RFC2328 Section 13.3. */
static int ospf_flood_through_interface(struct ospf_interface *oi,
struct ospf_neighbor *inbr,
struct ospf_lsa *lsa)
int ospf_flood_through_interface(struct ospf_interface *oi,
struct ospf_neighbor *inbr,
struct ospf_lsa *lsa)
{
struct ospf_neighbor *onbr;
struct route_node *rn;
@ -1031,25 +1031,50 @@ void ospf_ls_retransmit_delete_nbr_as(struct ospf *ospf, struct ospf_lsa *lsa)
flushing an LSA from the whole domain. */
void ospf_lsa_flush_area(struct ospf_lsa *lsa, struct ospf_area *area)
{
struct ospf *ospf = area->ospf;
if (ospf_lsa_is_self_originated(ospf, lsa)
&& ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"%s:LSA[Type%d:%pI4]: Graceful Restart in progress -- not flushing self-originated LSA",
ospf_get_name(ospf), lsa->data->type,
&lsa->data->id);
return;
}
/* Reset the lsa origination time such that it gives
more time for the ACK to be received and avoid
retransmissions */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: MAXAGE set to LSA %pI4", __func__,
&lsa->data->id);
zlog_debug("%s: MaxAge set to LSA[%s]", __func__,
dump_lsa_key(lsa));
monotime(&lsa->tv_recv);
lsa->tv_orig = lsa->tv_recv;
ospf_flood_through_area(area, NULL, lsa);
ospf_lsa_maxage(area->ospf, lsa);
ospf_lsa_maxage(ospf, lsa);
}
void ospf_lsa_flush_as(struct ospf *ospf, struct ospf_lsa *lsa)
{
if (ospf_lsa_is_self_originated(ospf, lsa)
&& ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"%s:LSA[Type%d:%pI4]: Graceful Restart in progress -- not flushing self-originated LSA",
ospf_get_name(ospf), lsa->data->type,
&lsa->data->id);
return;
}
/* Reset the lsa origination time such that it gives
more time for the ACK to be received and avoid
retransmissions */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: MaxAge set to LSA[%s]", __func__,
dump_lsa_key(lsa));
monotime(&lsa->tv_recv);
lsa->tv_orig = lsa->tv_recv;
ospf_flood_through_as(ospf, NULL, lsa);

View file

@ -30,6 +30,9 @@ extern int ospf_flood_through_area(struct ospf_area *, struct ospf_neighbor *,
struct ospf_lsa *);
extern int ospf_flood_through_as(struct ospf *, struct ospf_neighbor *,
struct ospf_lsa *);
extern int ospf_flood_through_interface(struct ospf_interface *oi,
struct ospf_neighbor *inbr,
struct ospf_lsa *lsa);
extern unsigned long ospf_ls_request_count(struct ospf_neighbor *);
extern int ospf_ls_request_isempty(struct ospf_neighbor *);

824
ospfd/ospf_gr.c Normal file
View file

@ -0,0 +1,824 @@
/*
* This is an implementation of RFC 3623 Graceful OSPF Restart.
*
* Copyright 2021 NetDEF (c), All rights reserved.
* Copyright 2020 6WIND (c), All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "memory.h"
#include "command.h"
#include "table.h"
#include "vty.h"
#include "log.h"
#include "printfrr.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_opaque.h"
#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_gr.h"
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_dump.h"
#ifndef VTYSH_EXTRACT_PL
#include "ospfd/ospf_gr_clippy.c"
#endif
static void ospf_gr_nvm_delete(struct ospf *ospf);
/* Lookup self-originated Grace-LSA in the LSDB. */
static struct ospf_lsa *ospf_gr_lsa_lookup(struct ospf *ospf,
struct ospf_area *area)
{
struct ospf_lsa *lsa;
struct in_addr lsa_id;
uint32_t lsa_id_host_byte_order;
lsa_id_host_byte_order = SET_OPAQUE_LSID(OPAQUE_TYPE_GRACE_LSA, 0);
lsa_id.s_addr = htonl(lsa_id_host_byte_order);
lsa = ospf_lsa_lookup(ospf, area, OSPF_OPAQUE_LINK_LSA, lsa_id,
ospf->router_id);
return lsa;
}
/* Fill in fields of the Grace-LSA that is being originated. */
static void ospf_gr_lsa_body_set(struct ospf_gr_info *gr_info,
struct ospf_interface *oi, struct stream *s)
{
struct grace_tlv_graceperiod tlv_period = {};
struct grace_tlv_restart_reason tlv_reason = {};
struct grace_tlv_restart_addr tlv_address = {};
/* Put grace period. */
tlv_period.header.type = htons(GRACE_PERIOD_TYPE);
tlv_period.header.length = htons(GRACE_PERIOD_LENGTH);
tlv_period.interval = htonl(gr_info->grace_period);
stream_put(s, &tlv_period, sizeof(tlv_period));
/* Put restart reason. */
tlv_reason.header.type = htons(RESTART_REASON_TYPE);
tlv_reason.header.length = htons(RESTART_REASON_LENGTH);
if (gr_info->restart_support)
tlv_reason.reason = OSPF_GR_SW_RESTART;
else
tlv_reason.reason = OSPF_GR_UNKNOWN_RESTART;
stream_put(s, &tlv_reason, sizeof(tlv_reason));
/* Put IP address. */
if (oi->type == OSPF_IFTYPE_BROADCAST || oi->type == OSPF_IFTYPE_NBMA
|| oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
tlv_address.header.type = htons(RESTARTER_IP_ADDR_TYPE);
tlv_address.header.length = htons(RESTARTER_IP_ADDR_LEN);
tlv_address.addr = oi->address->u.prefix4;
stream_put(s, &tlv_address, sizeof(tlv_address));
}
}
/* Generate Grace-LSA for a given interface. */
static struct ospf_lsa *ospf_gr_lsa_new(struct ospf_interface *oi)
{
struct stream *s;
struct lsa_header *lsah;
struct ospf_lsa *new;
uint8_t options, lsa_type;
struct in_addr lsa_id;
uint32_t lsa_id_host_byte_order;
uint16_t length;
/* Create a stream for LSA. */
s = stream_new(OSPF_MAX_LSA_SIZE);
lsah = (struct lsa_header *)STREAM_DATA(s);
options = LSA_OPTIONS_GET(oi->area);
options |= LSA_OPTIONS_NSSA_GET(oi->area);
options |= OSPF_OPTION_O;
lsa_type = OSPF_OPAQUE_LINK_LSA;
lsa_id_host_byte_order = SET_OPAQUE_LSID(OPAQUE_TYPE_GRACE_LSA, 0);
lsa_id.s_addr = htonl(lsa_id_host_byte_order);
/* Set opaque-LSA header fields. */
lsa_header_set(s, options, lsa_type, lsa_id, oi->ospf->router_id);
/* Set opaque-LSA body fields. */
ospf_gr_lsa_body_set(&oi->ospf->gr_info, oi, s);
/* Set length. */
length = stream_get_endp(s);
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new_and_data(length);
if (IS_DEBUG_OSPF_GR)
zlog_debug("LSA[Type%d:%pI4]: Create an Opaque-LSA/GR instance",
lsa_type, &lsa_id);
new->area = oi->area;
new->oi = oi;
SET_FLAG(new->flags, OSPF_LSA_SELF);
memcpy(new->data, lsah, length);
stream_free(s);
return new;
}
/* Originate and install Grace-LSA for a given interface. */
static void ospf_gr_lsa_originate(struct ospf_interface *oi)
{
struct ospf_lsa *lsa, *old;
if (ospf_interface_neighbor_count(oi) == 0)
return;
/* Create new Grace-LSA. */
lsa = ospf_gr_lsa_new(oi);
if (!lsa) {
zlog_warn("%s: ospf_gr_lsa_new() failed", __func__);
return;
}
/* Find the old LSA and increase the seqno. */
old = ospf_gr_lsa_lookup(oi->ospf, oi->area);
if (old)
lsa->data->ls_seqnum = lsa_seqnum_increment(old);
/* Install this LSA into LSDB. */
if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) {
zlog_warn("%s: ospf_lsa_install() failed", __func__);
ospf_lsa_unlock(&lsa);
return;
}
/* Update new LSA origination count. */
oi->ospf->lsa_originate_count++;
/* Flood the LSA through out the interface */
ospf_flood_through_interface(oi, NULL, lsa);
}
/* Flush a given self-originated Grace-LSA. */
static struct ospf_lsa *ospf_gr_flush_grace_lsa(struct ospf_interface *oi,
struct ospf_lsa *old)
{
struct ospf_lsa *lsa;
if (ospf_interface_neighbor_count(oi) == 0)
return NULL;
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: flushing self-originated Grace-LSAs [interface %s]",
oi->ifp->name);
lsa = ospf_lsa_dup(old);
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
lsa->data->ls_seqnum = lsa_seqnum_increment(lsa);
/* Install updated LSA into LSDB. */
if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) {
zlog_warn("%s: ospf_lsa_install() failed", __func__);
ospf_lsa_unlock(&lsa);
return NULL;
}
/* Flood the LSA through out the interface */
ospf_flood_through_interface(oi, NULL, lsa);
return lsa;
}
/* Flush all self-originated Grace-LSAs. */
static void ospf_gr_flush_grace_lsas(struct ospf *ospf)
{
struct ospf_area *area;
struct listnode *anode;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) {
struct ospf_lsa *lsa;
struct ospf_interface *oi;
struct listnode *inode;
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: flushing self-originated Grace-LSAs [area %pI4]",
&area->area_id);
lsa = ospf_gr_lsa_lookup(ospf, area);
if (!lsa) {
zlog_warn("%s: Grace-LSA not found [area %pI4]",
__func__, &area->area_id);
continue;
}
for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi))
ospf_gr_flush_grace_lsa(oi, lsa);
}
}
/* Exit from the Graceful Restart mode. */
static void ospf_gr_restart_exit(struct ospf *ospf, const char *reason)
{
struct ospf_area *area;
struct listnode *onode, *anode;
if (IS_DEBUG_OSPF_GR)
zlog_debug("GR: exiting graceful restart: %s", reason);
ospf->gr_info.restart_in_progress = false;
OSPF_TIMER_OFF(ospf->gr_info.t_grace_period);
/* Record in non-volatile memory that the restart is complete. */
ospf_gr_nvm_delete(ospf);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, onode, area)) {
struct ospf_interface *oi;
/*
* 1) The router should reoriginate its router-LSAs for all
* attached areas in order to make sure they have the correct
* contents.
*/
ospf_router_lsa_update_area(area);
/*
* 2) The router should reoriginate network-LSAs on all segments
* where it is the Designated Router.
*/
for (ALL_LIST_ELEMENTS_RO(area->oiflist, anode, oi))
if (oi->state == ISM_DR)
ospf_network_lsa_update(oi);
}
/*
* 5) Any received self-originated LSAs that are no longer valid should
* be flushed.
*/
ospf_schedule_abr_task(ospf);
/*
* 3) The router reruns its OSPF routing calculations, this time
* installing the results into the system forwarding table, and
* originating summary-LSAs, Type-7 LSAs and AS-external-LSAs as
* necessary.
*
* 4) Any remnant entries in the system forwarding table that were
* installed before the restart, but that are no longer valid,
* should be removed.
*/
ospf->gr_info.finishing_restart = true;
ospf_spf_calculate_schedule(ospf, SPF_FLAG_GR_FINISH);
/* 6) Any grace-LSAs that the router originated should be flushed. */
ospf_gr_flush_grace_lsas(ospf);
}
/* Check if a Router-LSA contains a given link. */
static bool ospf_router_lsa_contains_adj(struct ospf_lsa *lsa,
struct in_addr *id)
{
struct router_lsa *rl;
rl = (struct router_lsa *)lsa->data;
for (int i = 0; i < ntohs(rl->links); i++) {
struct in_addr *link_id = &rl->link[i].link_id;
if (rl->link[i].type != LSA_LINK_TYPE_POINTOPOINT)
continue;
if (IPV4_ADDR_SAME(id, link_id))
return true;
}
return false;
}
static bool ospf_gr_check_router_lsa_consistency(struct ospf *ospf,
struct ospf_area *area,
struct ospf_lsa *lsa)
{
if (CHECK_FLAG(lsa->flags, OSPF_LSA_SELF)) {
struct ospf_lsa *lsa_self = lsa;
struct router_lsa *rl = (struct router_lsa *)lsa->data;
for (int i = 0; i < ntohs(rl->links); i++) {
struct in_addr *link_id = &rl->link[i].link_id;
struct ospf_lsa *lsa_adj;
if (rl->link[i].type != LSA_LINK_TYPE_POINTOPOINT)
continue;
lsa_adj = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
*link_id);
if (!lsa_adj)
continue;
if (!ospf_router_lsa_contains_adj(lsa_adj,
&lsa_self->data->id))
return false;
}
} else {
struct ospf_lsa *lsa_self;
lsa_self = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
ospf->router_id);
if (!lsa_self
|| !CHECK_FLAG(lsa_self->flags, OSPF_LSA_RECEIVED))
return true;
if (ospf_router_lsa_contains_adj(lsa, &ospf->router_id)
!= ospf_router_lsa_contains_adj(lsa_self, &lsa->data->id))
return false;
}
return true;
}
/*
* Check for LSAs that are inconsistent with the pre-restart LSAs, and abort the
* ongoing graceful restart when that's the case.
*/
void ospf_gr_check_lsdb_consistency(struct ospf *ospf, struct ospf_area *area)
{
struct route_node *rn;
struct ospf_lsa *lsa;
for (rn = route_top(ROUTER_LSDB(area)); rn; rn = route_next(rn)) {
lsa = rn->info;
if (!lsa)
continue;
if (!ospf_gr_check_router_lsa_consistency(ospf, area, lsa)) {
char reason[256];
snprintfrr(reason, sizeof(reason),
"detected inconsistent LSA[%s] [area %pI4]",
dump_lsa_key(lsa), &area->area_id);
ospf_gr_restart_exit(ospf, reason);
route_unlock_node(rn);
return;
}
}
}
/* Lookup neighbor by address in a given OSPF area. */
static struct ospf_neighbor *
ospf_area_nbr_lookup_by_addr(struct ospf_area *area, struct in_addr *addr)
{
struct ospf_interface *oi;
struct ospf_neighbor *nbr;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) {
nbr = ospf_nbr_lookup_by_addr(oi->nbrs, addr);
if (nbr)
return nbr;
}
return NULL;
}
/* Lookup neighbor by Router ID in a given OSPF area. */
static struct ospf_neighbor *
ospf_area_nbr_lookup_by_routerid(struct ospf_area *area, struct in_addr *id)
{
struct ospf_interface *oi;
struct ospf_neighbor *nbr;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) {
nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, id);
if (nbr)
return nbr;
}
return NULL;
}
/* Check if there's a fully formed adjacency with the given neighbor ID. */
static bool ospf_gr_check_adj_id(struct ospf_area *area,
struct in_addr *nbr_id)
{
struct ospf_neighbor *nbr;
nbr = ospf_area_nbr_lookup_by_routerid(area, nbr_id);
if (!nbr || nbr->state < NSM_Full) {
if (IS_DEBUG_OSPF_GR)
zlog_debug("GR: missing adjacency to router %pI4",
nbr_id);
return false;
}
return true;
}
static bool ospf_gr_check_adjs_lsa_transit(struct ospf_area *area,
struct in_addr *link_id)
{
struct ospf *ospf = area->ospf;
struct ospf_interface *oi;
/*
* Check if the transit network refers to a local interface (in which
* case it must be a DR for that network).
*/
oi = ospf_if_lookup_by_local_addr(ospf, NULL, *link_id);
if (oi) {
struct ospf_lsa *lsa;
struct network_lsa *nlsa;
size_t cnt;
/* Lookup Network LSA corresponding to this interface. */
lsa = ospf_lsa_lookup_by_id(area, OSPF_NETWORK_LSA, *link_id);
if (!lsa)
return false;
/* Iterate over all routers present in the network. */
nlsa = (struct network_lsa *)lsa->data;
cnt = (lsa->size - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
for (size_t i = 0; i < cnt; i++) {
struct in_addr *nbr_id = &nlsa->routers[i];
/* Skip self in the pseudonode. */
if (IPV4_ADDR_SAME(nbr_id, &ospf->router_id))
continue;
/*
* Check if there's a fully formed adjacency with this
* router.
*/
if (!ospf_gr_check_adj_id(area, nbr_id))
return false;
}
} else {
struct ospf_neighbor *nbr;
/* Check if there's a fully formed adjacency with the DR. */
nbr = ospf_area_nbr_lookup_by_addr(area, link_id);
if (!nbr || nbr->state < NSM_Full) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: missing adjacency to DR router %pI4",
link_id);
return false;
}
}
return true;
}
static bool ospf_gr_check_adjs_lsa(struct ospf_area *area, struct ospf_lsa *lsa)
{
struct router_lsa *rl = (struct router_lsa *)lsa->data;
for (int i = 0; i < ntohs(rl->links); i++) {
struct in_addr *link_id = &rl->link[i].link_id;
switch (rl->link[i].type) {
case LSA_LINK_TYPE_POINTOPOINT:
if (!ospf_gr_check_adj_id(area, link_id))
return false;
break;
case LSA_LINK_TYPE_TRANSIT:
if (!ospf_gr_check_adjs_lsa_transit(area, link_id))
return false;
break;
default:
break;
}
}
return true;
}
/*
* Check if all adjacencies prior to the restart were reestablished.
*
* This is done using pre-restart Router LSAs and pre-restart Network LSAs
* received from the helping neighbors.
*/
void ospf_gr_check_adjs(struct ospf *ospf)
{
struct ospf_area *area;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
struct ospf_lsa *lsa_self;
lsa_self = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
ospf->router_id);
if (!lsa_self || !ospf_gr_check_adjs_lsa(area, lsa_self)) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: not all adjacencies were reestablished yet [area %pI4]",
&area->area_id);
return;
}
}
ospf_gr_restart_exit(ospf, "all adjacencies were reestablished");
}
/* Handling of grace period expiry. */
static int ospf_gr_grace_period_expired(struct thread *thread)
{
struct ospf *ospf = THREAD_ARG(thread);
ospf->gr_info.t_grace_period = NULL;
ospf_gr_restart_exit(ospf, "grace period has expired");
return 0;
}
/*
* Returns the path of the file (non-volatile memory) that contains GR status
* information.
*/
static char *ospf_gr_nvm_filepath(struct ospf *ospf)
{
static char filepath[MAXPATHLEN];
char instance[16] = "";
if (ospf->instance)
snprintf(instance, sizeof(instance), "-%d", ospf->instance);
snprintf(filepath, sizeof(filepath), OSPFD_GR_STATE, instance);
return filepath;
}
/*
* Record in non-volatile memory that the given OSPF instance is attempting to
* perform a graceful restart.
*/
static void ospf_gr_nvm_update(struct ospf *ospf)
{
char *filepath;
const char *inst_name;
json_object *json;
json_object *json_instances;
json_object *json_instance;
filepath = ospf_gr_nvm_filepath(ospf);
inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME;
json = json_object_from_file(filepath);
if (json == NULL)
json = json_object_new_object();
json_object_object_get_ex(json, "instances", &json_instances);
if (!json_instances) {
json_instances = json_object_new_object();
json_object_object_add(json, "instances", json_instances);
}
json_object_object_get_ex(json_instances, inst_name, &json_instance);
if (!json_instance) {
json_instance = json_object_new_object();
json_object_object_add(json_instances, inst_name,
json_instance);
}
/*
* Record not only the grace period, but also a UNIX timestamp
* corresponding to the end of that period. That way, once ospfd is
* restarted, it will be possible to take into account the time that
* passed while ospfd wasn't running.
*/
json_object_int_add(json_instance, "gracePeriod",
ospf->gr_info.grace_period);
json_object_int_add(json_instance, "timestamp",
time(NULL) + ospf->gr_info.grace_period);
json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY);
json_object_free(json);
}
/*
* Delete GR status information about the given OSPF instance from non-volatile
* memory.
*/
static void ospf_gr_nvm_delete(struct ospf *ospf)
{
char *filepath;
const char *inst_name;
json_object *json;
json_object *json_instances;
filepath = ospf_gr_nvm_filepath(ospf);
inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME;
json = json_object_from_file(filepath);
if (json == NULL)
json = json_object_new_object();
json_object_object_get_ex(json, "instances", &json_instances);
if (!json_instances) {
json_instances = json_object_new_object();
json_object_object_add(json, "instances", json_instances);
}
json_object_object_del(json_instances, inst_name);
json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY);
json_object_free(json);
}
/*
* Fetch from non-volatile memory whether the given OSPF instance is performing
* a graceful shutdown or not.
*/
void ospf_gr_nvm_read(struct ospf *ospf)
{
char *filepath;
const char *inst_name;
json_object *json;
json_object *json_instances;
json_object *json_instance;
json_object *json_timestamp;
time_t timestamp = 0;
filepath = ospf_gr_nvm_filepath(ospf);
inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME;
json = json_object_from_file(filepath);
if (json == NULL)
json = json_object_new_object();
json_object_object_get_ex(json, "instances", &json_instances);
if (!json_instances) {
json_instances = json_object_new_object();
json_object_object_add(json, "instances", json_instances);
}
json_object_object_get_ex(json_instances, inst_name, &json_instance);
if (!json_instance) {
json_instance = json_object_new_object();
json_object_object_add(json_instances, inst_name,
json_instance);
}
json_object_object_get_ex(json_instance, "timestamp", &json_timestamp);
if (json_timestamp) {
time_t now;
unsigned long remaining_time;
/* Check if the grace period has already expired. */
now = time(NULL);
timestamp = json_object_get_int(json_timestamp);
if (now > timestamp) {
ospf_gr_restart_exit(
ospf, "grace period has expired already");
} else {
/* Schedule grace period timeout. */
ospf->gr_info.restart_in_progress = true;
remaining_time = timestamp - time(NULL);
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: remaining time until grace period expires: %lu(s)",
remaining_time);
thread_add_timer(master, ospf_gr_grace_period_expired,
ospf, remaining_time,
&ospf->gr_info.t_grace_period);
}
}
json_object_object_del(json_instances, inst_name);
json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY);
json_object_free(json);
}
/* Prepare to start a Graceful Restart. */
static void ospf_gr_prepare(void)
{
struct ospf *ospf;
struct ospf_interface *oi;
struct listnode *onode;
for (ALL_LIST_ELEMENTS_RO(om->ospf, onode, ospf)) {
struct listnode *inode;
if (!ospf->gr_info.restart_support
|| ospf->gr_info.prepare_in_progress)
continue;
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"GR: preparing to perform a graceful restart [period %u second(s)] [vrf %s]",
ospf->gr_info.grace_period,
ospf_vrf_id_to_name(ospf->vrf_id));
if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) {
zlog_warn(
"%s: failed to activate graceful restart: opaque capability not enabled",
__func__);
continue;
}
/* Freeze OSPF routes in the RIB. */
if (ospf_zebra_gr_enable(ospf, ospf->gr_info.grace_period)) {
zlog_warn(
"%s: failed to activate graceful restart: not connected to zebra",
__func__);
continue;
}
/* Send a Grace-LSA to all neighbors. */
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi))
ospf_gr_lsa_originate(oi);
/* Record end of the grace period in non-volatile memory. */
ospf_gr_nvm_update(ospf);
/*
* Mark that a Graceful Restart preparation is in progress, to
* prevent ospfd from flushing its self-originated LSAs on exit.
*/
ospf->gr_info.prepare_in_progress = true;
}
}
DEFPY(graceful_restart_prepare, graceful_restart_prepare_cmd,
"graceful-restart prepare ip ospf",
"Graceful Restart commands\n"
"Prepare upcoming graceful restart\n"
IP_STR
"Prepare to restart the OSPF process")
{
ospf_gr_prepare();
return CMD_SUCCESS;
}
DEFPY(graceful_restart, graceful_restart_cmd,
"graceful-restart [grace-period (1-1800)$grace_period]",
OSPF_GR_STR
"Maximum length of the 'grace period'\n"
"Maximum length of the 'grace period' in seconds\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
/* Check and get restart period if present. */
if (!grace_period_str)
grace_period = OSPF_DFLT_GRACE_INTERVAL;
ospf->gr_info.restart_support = true;
ospf->gr_info.grace_period = grace_period;
return CMD_SUCCESS;
}
DEFPY(no_graceful_restart, no_graceful_restart_cmd,
"no graceful-restart [period (1-1800)]",
NO_STR OSPF_GR_STR
"Maximum length of the 'grace period'\n"
"Maximum length of the 'grace period' in seconds\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
if (!ospf->gr_info.restart_support)
return CMD_SUCCESS;
if (ospf->gr_info.prepare_in_progress) {
vty_out(vty,
"%% Error: Graceful Restart preparation in progress\n");
return CMD_WARNING;
}
ospf->gr_info.restart_support = false;
ospf->gr_info.grace_period = OSPF_DFLT_GRACE_INTERVAL;
return CMD_SUCCESS;
}
void ospf_gr_init(void)
{
install_element(ENABLE_NODE, &graceful_restart_prepare_cmd);
install_element(OSPF_NODE, &graceful_restart_cmd);
install_element(OSPF_NODE, &no_graceful_restart_cmd);
}

View file

@ -21,8 +21,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_OSPF_GR_HELPER_H
#define _ZEBRA_OSPF_GR_HELPER_H
#ifndef _ZEBRA_OSPF_GR_H
#define _ZEBRA_OSPF_GR_H
#define OSPF_GR_NOT_HELPER 0
#define OSPF_GR_ACTIVE_HELPER 1
@ -32,6 +32,7 @@
#define OSPF_MAX_GRACE_INTERVAL 1800
#define OSPF_MIN_GRACE_INTERVAL 1
#define OSPF_DFLT_GRACE_INTERVAL 120
enum ospf_helper_exit_reason {
OSPF_GR_HELPER_EXIT_NONE = 0,
@ -55,7 +56,8 @@ enum ospf_gr_helper_rejected_reason {
OSPF_HELPER_NOT_A_VALID_NEIGHBOUR,
OSPF_HELPER_PLANNED_ONLY_RESTART,
OSPF_HELPER_TOPO_CHANGE_RTXMT_LIST,
OSPF_HELPER_LSA_AGE_MORE
OSPF_HELPER_LSA_AGE_MORE,
OSPF_HELPER_RESTARTING,
};
/* Ref RFC3623 appendex-A */
@ -101,7 +103,8 @@ struct ospf_helper_info {
/* Grace timer,This Router acts as
* helper until this timer until
* this timer expires*/
* this timer expires.
*/
struct thread *t_grace_timer;
/* Helper status */
@ -178,4 +181,11 @@ extern void ospf_gr_helper_supported_gracetime_set(struct ospf *ospf,
uint32_t interval);
extern void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf,
bool planned_only);
#endif /* _ZEBRA_OSPF_HELPER_H */
extern void ospf_gr_check_lsdb_consistency(struct ospf *ospf,
struct ospf_area *area);
extern void ospf_gr_check_adjs(struct ospf *ospf);
extern void ospf_gr_nvm_read(struct ospf *ospf);
extern void ospf_gr_init(void);
#endif /* _ZEBRA_OSPF_GR_H */

View file

@ -48,7 +48,7 @@
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_gr_helper.h"
#include "ospfd/ospf_gr.h"
static const char * const ospf_exit_reason_desc[] = {
"Unknown reason",
@ -72,6 +72,7 @@ static const char * const ospf_rejected_reason_desc[] = {
"Supports only planned restart but received unplanned",
"Topo change due to change in lsa rxmt list",
"LSA age is more than Grace interval",
"Router is in the process of graceful restart",
};
static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa);
@ -161,7 +162,7 @@ const char *ospf_rejected_reason2str(unsigned int reason)
*/
void ospf_gr_helper_instance_init(struct ospf *ospf)
{
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, GR Helper init.", __func__);
ospf->is_helper_supported = OSPF_GR_FALSE;
@ -187,7 +188,7 @@ void ospf_gr_helper_instance_init(struct ospf *ospf)
*/
void ospf_gr_helper_instance_stop(struct ospf *ospf)
{
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, GR helper deinit.", __func__);
ospf_enable_rtr_hash_destroy(ospf);
@ -203,7 +204,7 @@ void ospf_gr_helper_init(void)
{
int rc;
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, GR Helper init.", __func__);
rc = ospf_register_opaque_functab(
@ -225,8 +226,7 @@ void ospf_gr_helper_init(void)
*/
void ospf_gr_helper_stop(void)
{
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, GR helper deinit.", __func__);
ospf_delete_opaque_functab(OSPF_OPAQUE_LINK_LSA, OPAQUE_TYPE_GRACE_LSA);
@ -259,7 +259,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
/* Check LSA len */
if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
__func__, length);
return OSPF_GR_FAILURE;
@ -272,7 +272,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
/* Check TLV len against overall LSA */
if (sum + TLV_SIZE(tlvh) > length) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s: Malformed packet: Invalid TLV len:%u",
__func__, TLV_SIZE(tlvh));
return OSPF_GR_FAILURE;
@ -324,7 +324,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
sum += TLV_SIZE(tlvh);
break;
default:
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Malformed packet.Invalid TLV type:%d",
__func__, ntohs(tlvh->type));
@ -391,12 +391,12 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
ret = ospf_extract_grace_lsa_fields(lsa, &grace_interval, &restart_addr,
&restart_reason);
if (ret != OSPF_GR_SUCCESS) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, Wrong Grace LSA packet.", __func__);
return OSPF_GR_NOT_HELPER;
}
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Grace LSA received from %pI4, grace interval:%u, restart reason:%s",
__func__, &restart_addr, grace_interval,
@ -410,7 +410,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restart_addr);
if (!restarter) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Restarter is not a nbr(%pI4) for this router.",
__func__, &restart_addr);
@ -427,7 +427,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
lookup.advRtrAddr.s_addr = restarter->router_id.s_addr;
if (!hash_lookup(ospf->enable_rtr_list, &lookup)) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, HELPER support is disabled, So not a HELPER",
__func__);
@ -442,7 +442,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
* became a adjacency.
*/
if (!IS_NBR_STATE_FULL(restarter)) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, This Neighbour %pI4 is not in FULL state.",
__func__, &restarter->src);
@ -456,7 +456,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
*/
if (ospf->only_planned_restart
&& !OSPF_GR_IS_PLANNED_RESTART(restart_reason)) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Router supports only planned restarts but received the GRACE LSA for an unplanned restart.",
__func__);
@ -470,7 +470,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
*/
if (ospf->strict_lsa_check && !ospf_ls_retransmit_isempty(restarter)
&& ospf_check_change_in_rxmt_list(restarter)) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Changed LSA in Rxmt list. So not Helper.",
__func__);
@ -481,7 +481,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
/*LSA age must be less than the grace period */
if (ntohs(lsa->data->ls_age) >= grace_interval) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Grace LSA age(%d) is more than the grace interval(%d)",
__func__, lsa->data->ls_age, grace_interval);
@ -490,6 +490,16 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
return OSPF_GR_NOT_HELPER;
}
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s: router is in the process of graceful restart",
__func__);
restarter->gr_helper_info.rejected_reason =
OSPF_HELPER_RESTARTING;
return OSPF_GR_NOT_HELPER;
}
/* check supported grace period configured
* if configured, use this to start the grace
* timer otherwise use the interval received
@ -497,7 +507,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
*/
actual_grace_interval = grace_interval;
if (grace_interval > ospf->supported_grace_time) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Received grace period %d is larger than supported grace %d",
__func__, grace_interval,
@ -512,12 +522,12 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
if (ospf->active_restarter_cnt > 0)
ospf->active_restarter_cnt--;
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Router is already acting as a HELPER for this nbr,so restart the grace timer",
__func__);
} else {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, This Router becomes a HELPER for the neighbour %pI4",
__func__, &restarter->src);
@ -535,7 +545,7 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
/* Increment the active restarter count */
ospf->active_restarter_cnt++;
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, Grace timer started.interval:%d", __func__,
actual_grace_interval);
@ -622,10 +632,9 @@ void ospf_helper_handle_topo_chg(struct ospf *ospf, struct ospf_lsa *lsa)
if (!ospf->strict_lsa_check)
return;
if (IS_DEBUG_OSPF_GR_HELPER)
zlog_debug(
"%s, Topo change detected due to lsa LSID:%pI4 type:%d",
__func__, &lsa->data->id, lsa->data->type);
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s: Topo change detected due to LSA[%s]", __func__,
dump_lsa_key(lsa));
lsa->to_be_acknowledged = OSPF_GR_TRUE;
@ -686,7 +695,7 @@ void ospf_gr_helper_exit(struct ospf_neighbor *nbr,
if (!OSPF_GR_IS_ACTIVE_HELPER(nbr))
return;
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, Exiting from HELPER support to %pI4, due to %s",
__func__, &nbr->src, ospf_exit_reason2str(reason));
@ -717,7 +726,7 @@ void ospf_gr_helper_exit(struct ospf_neighbor *nbr,
* If no, bring down the neighbour.
*/
if (reason != OSPF_GR_HELPER_COMPLETED) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Failed GR exit, so bringing down the neighbour",
__func__);
@ -768,12 +777,12 @@ void ospf_process_maxage_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
ret = ospf_extract_grace_lsa_fields(lsa, &graceInterval, &restartAddr,
&restartReason);
if (ret != OSPF_GR_SUCCESS) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, Wrong Grace LSA packet.", __func__);
return;
}
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, GraceLSA received for neighbour %pI4", __func__,
&restartAddr);
@ -785,7 +794,7 @@ void ospf_process_maxage_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
restarter = ospf_nbr_lookup_by_addr(oi->nbrs, &restartAddr);
if (!restarter) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Restarter is not a neighbour for this router.",
__func__);

View file

@ -819,6 +819,14 @@ static struct ospf_lsa *ospf_router_lsa_originate(struct ospf_area *area)
{
struct ospf_lsa *new;
if (area->ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type%d]: Graceful Restart in progress, don't originate",
OSPF_ROUTER_LSA);
return NULL;
}
/* Create new router-LSA instance. */
if ((new = ospf_router_lsa_new(area)) == NULL) {
zlog_err("%s: ospf_router_lsa_new returned NULL", __func__);
@ -1045,6 +1053,14 @@ void ospf_network_lsa_update(struct ospf_interface *oi)
{
struct ospf_lsa *new;
if (oi->area->ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type%d]: Graceful Restart in progress, don't originate",
OSPF_NETWORK_LSA);
return;
}
if (oi->network_lsa_self != NULL) {
ospf_lsa_refresh(oi->ospf, oi->network_lsa_self);
return;
@ -1212,6 +1228,14 @@ struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p,
struct ospf_lsa *new;
struct in_addr id;
if (area->ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type%d]: Graceful Restart in progress, don't originate",
OSPF_SUMMARY_LSA);
return NULL;
}
id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p);
if (id.s_addr == 0xffffffff) {
@ -1353,6 +1377,14 @@ struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p,
struct ospf_lsa *new;
struct in_addr id;
if (area->ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type%d]: Graceful Restart in progress, don't originate",
OSPF_ASBR_SUMMARY_LSA);
return NULL;
}
id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA,
p);
@ -1799,6 +1831,13 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
struct ospf_lsa *new;
struct as_external_lsa *extnew;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Translated Type5]: Graceful Restart in progress, don't originate");
return NULL;
}
/* we cant use ospf_external_lsa_originate() as we need to set
* the OSPF_LSA_LOCAL_XLT flag, must originate by hand
*/
@ -1953,6 +1992,13 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
{
struct ospf_lsa *new;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type5]: Graceful Restart in progress, don't originate");
return NULL;
}
/* Added for NSSA project....
External LSAs are originated in ASBRs as usual, but for NSSA
@ -2779,8 +2825,8 @@ struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi,
*/
if (IS_LSA_MAXAGE(new)) {
if (IS_DEBUG_OSPF(lsa, LSA_INSTALL))
zlog_debug("LSA[Type%d:%pI4]: Install LSA %p, MaxAge",
new->data->type, &new->data->id, lsa);
zlog_debug("LSA[%s]: Install LSA %p, MaxAge",
dump_lsa_key(new), lsa);
ospf_lsa_maxage(ospf, lsa);
}
@ -2862,9 +2908,8 @@ static int ospf_maxage_lsa_remover(struct thread *thread)
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
"LSA[Type%d:%pI4]: MaxAge LSA removed from list",
lsa->data->type,
&lsa->data->id);
"LSA[%s]: MaxAge LSA removed from list",
dump_lsa_key(lsa));
if (CHECK_FLAG(lsa->flags, OSPF_LSA_PREMATURE_AGE)) {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
@ -2882,9 +2927,8 @@ static int ospf_maxage_lsa_remover(struct thread *thread)
*/
if (old != lsa) {
flog_err(EC_OSPF_LSA_MISSING,
"%s: LSA[Type%d:%pI4]: LSA not in LSDB",
__func__, lsa->data->type,
&lsa->data->id);
"%s: LSA[%s]: LSA not in LSDB",
__func__, dump_lsa_key(lsa));
continue;
}
@ -2893,9 +2937,8 @@ static int ospf_maxage_lsa_remover(struct thread *thread)
} else {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
"%s: LSA[Type%d:%pI4]: No associated LSDB!",
__func__, lsa->data->type,
&lsa->data->id);
"%s: LSA[%s]: No associated LSDB!",
__func__, dump_lsa_key(lsa));
}
}
@ -2952,9 +2995,8 @@ void ospf_lsa_maxage(struct ospf *ospf, struct ospf_lsa *lsa)
if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
"LSA[Type%d:%pI4]: %p already exists on MaxAge LSA list",
lsa->data->type, &lsa->data->id,
(void *)lsa);
"LSA[%s]: %p already exists on MaxAge LSA list",
dump_lsa_key(lsa), lsa);
return;
}

View file

@ -54,6 +54,7 @@
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_vty.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_gr.h"
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_routemap_nb.h"
@ -225,6 +226,7 @@ int main(int argc, char **argv)
ospf_route_map_init();
ospf_opaque_init();
ospf_gr_init();
ospf_gr_helper_init();
/* OSPF errors init */

View file

@ -44,7 +44,7 @@
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_gr_helper.h"
#include "ospfd/ospf_gr.h"
/* Fill in the the 'key' as appropriate to retrieve the entry for nbr
* from the ospf_interface's nbrs table. Indexed by interface address

View file

@ -22,7 +22,7 @@
#ifndef _ZEBRA_OSPF_NEIGHBOR_H
#define _ZEBRA_OSPF_NEIGHBOR_H
#include <ospfd/ospf_gr_helper.h>
#include <ospfd/ospf_gr.h>
#include <ospfd/ospf_packet.h>
/* Neighbor Data Structure */

View file

@ -49,6 +49,7 @@
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_gr.h"
#include "ospfd/ospf_errors.h"
DEFINE_HOOK(ospf_nsm_change,
@ -75,7 +76,7 @@ static int ospf_inactivity_timer(struct thread *thread)
*/
if (!OSPF_GR_IS_ACTIVE_HELPER(nbr))
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer);
else if (IS_DEBUG_OSPF_GR_HELPER)
else if (IS_DEBUG_OSPF_GR)
zlog_debug(
"%s, Acting as HELPER for this neighbour, So inactivitytimer event will not be fired.",
__func__);
@ -727,6 +728,9 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
ospf_network_lsa_update(oi);
}
}
if (state == NSM_Full && oi->ospf->gr_info.restart_in_progress)
ospf_gr_check_adjs(oi->ospf);
}
ospf_opaque_nsm_change(nbr, old_state);

View file

@ -2147,6 +2147,11 @@ void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
if ((top = oi_to_top(nbr->oi)) == NULL)
return;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"LSA[Type%d:%pI4]: processing self-originated Opaque-LSA",
lsa->data->type, &lsa->data->id);
/*
* Since these LSA entries are not yet installed into corresponding
* LSDB, just flush them without calling ospf_ls_maxage() afterward.

View file

@ -54,7 +54,7 @@
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_gr_helper.h"
#include "ospfd/ospf_gr.h"
/*
* OSPF Fragmentation / fragmented writes
@ -2025,9 +2025,11 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
ospf_ls_ack_send(nbr, lsa);
ospf_opaque_self_originated_lsa_received(nbr,
lsa);
continue;
if (!ospf->gr_info.restart_in_progress) {
ospf_opaque_self_originated_lsa_received(
nbr, lsa);
continue;
}
}
}
@ -2213,6 +2215,9 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
assert(listcount(lsas) == 0);
list_delete(&lsas);
if (ospf->gr_info.restart_in_progress)
ospf_gr_check_lsdb_consistency(oi->ospf, oi->area);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
@ -3575,14 +3580,13 @@ static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update,
struct lsa_header *lsah;
uint16_t ls_age;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_make_ls_upd: List Iteration %d",
count);
lsa = listgetdata(node);
assert(lsa->data);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: List Iteration %d LSA[%s]", __func__,
count, dump_lsa_key(lsa));
/* Will it fit? Minimum it has to fit atleast one */
if ((length + delta + ntohs(lsa->data->length) > size_noauth) &&
(count > 0))
@ -4264,7 +4268,7 @@ void ospf_ls_ack_send(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
struct ospf_interface *oi = nbr->oi;
if (IS_GRACE_LSA(lsa)) {
if (IS_DEBUG_OSPF_GR_HELPER)
if (IS_DEBUG_OSPF_GR)
zlog_debug("%s, Sending GRACE ACK to Restarter.",
__func__);
}

View file

@ -1903,6 +1903,8 @@ static int ospf_spf_calculate_schedule_worker(struct thread *thread)
strlcat(rbuf, "ASBR, ", sizeof(rbuf));
if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
strlcat(rbuf, "M, ", sizeof(rbuf));
if (spf_reason_flags & (1 << SPF_FLAG_GR_FINISH))
strlcat(rbuf, "GR, ", sizeof(rbuf));
size_t rbuflen = strlen(rbuf);
if (rbuflen >= 2)

View file

@ -69,6 +69,7 @@ typedef enum {
SPF_FLAG_ABR_STATUS_CHANGE,
SPF_FLAG_ASBR_STATUS_CHANGE,
SPF_FLAG_CONFIG_CHANGE,
SPF_FLAG_GR_FINISH,
} ospf_spf_reason_t;
extern void ospf_spf_calculate_schedule(struct ospf *, ospf_spf_reason_t);

View file

@ -12250,6 +12250,18 @@ static int ospf_cfg_write_helper_dis_rtr_walkcb(struct hash_bucket *bucket,
return HASHWALK_CONTINUE;
}
static void config_write_ospf_gr(struct vty *vty, struct ospf *ospf)
{
if (!ospf->gr_info.restart_support)
return;
if (ospf->gr_info.grace_period == OSPF_DFLT_GRACE_INTERVAL)
vty_out(vty, " graceful-restart\n");
else
vty_out(vty, " graceful-restart grace-period %u\n",
ospf->gr_info.grace_period);
}
static int config_write_ospf_gr_helper(struct vty *vty, struct ospf *ospf)
{
if (ospf->is_helper_supported)
@ -12464,7 +12476,8 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
/* Redistribute information print. */
config_write_ospf_redistribute(vty, ospf);
/* Print gr helper configs */
/* Graceful Restart print */
config_write_ospf_gr(vty, ospf);
config_write_ospf_gr_helper(vty, ospf);
/* Print external route aggregation. */

View file

@ -264,6 +264,14 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
struct ospf_path *path;
struct listnode *node;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"Zebra: Graceful Restart in progress -- not installing %pFX",
p);
return;
}
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
@ -323,6 +331,14 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
{
struct zapi_route api;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"Zebra: Graceful Restart in progress -- not uninstalling %pFX",
p);
return;
}
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
@ -340,6 +356,14 @@ void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
{
struct zapi_route api;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"Zebra: Graceful Restart in progress -- not installing %pFX",
p);
return;
}
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
@ -358,6 +382,14 @@ void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
{
struct zapi_route api;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF_GR)
zlog_debug(
"Zebra: Graceful Restart in progress -- not uninstalling %pFX",
p);
return;
}
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
@ -1180,6 +1212,36 @@ void ospf_routemap_unset(struct ospf_redist *red)
ROUTEMAP(red) = NULL;
}
static int ospf_zebra_gr_update(struct ospf *ospf, int command,
uint32_t stale_time)
{
struct zapi_cap api;
if (!zclient || zclient->sock < 0 || !ospf)
return 1;
memset(&api, 0, sizeof(struct zapi_cap));
api.cap = command;
api.stale_removal_time = stale_time;
api.vrf_id = ospf->vrf_id;
(void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient,
&api);
return 0;
}
int ospf_zebra_gr_enable(struct ospf *ospf, uint32_t stale_time)
{
return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_CAPABILITIES,
stale_time);
}
int ospf_zebra_gr_disable(struct ospf *ospf)
{
return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_DISABLE, 0);
}
/* Zebra route add and delete treatment. */
static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
{

View file

@ -88,6 +88,8 @@ extern int ospf_distribute_list_out_set(struct ospf *, int, const char *);
extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *);
extern void ospf_routemap_set(struct ospf_redist *, const char *);
extern void ospf_routemap_unset(struct ospf_redist *);
extern int ospf_zebra_gr_enable(struct ospf *ospf, uint32_t stale_time);
extern int ospf_zebra_gr_disable(struct ospf *ospf);
extern int ospf_distance_set(struct vty *, struct ospf *, const char *,
const char *, const char *);
extern int ospf_distance_unset(struct vty *, struct ospf *, const char *,

View file

@ -60,7 +60,7 @@
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_ase.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_gr_helper.h"
#include "ospfd/ospf_gr.h"
DEFINE_QOBJ_TYPE(ospf);
@ -420,6 +420,12 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
/*
* Read from non-volatile memory whether this instance is performing a
* graceful restart or not.
*/
ospf_gr_nvm_read(new);
return new;
}
@ -708,7 +714,8 @@ static void ospf_finish_final(struct ospf *ospf)
ospf_opaque_finish();
ospf_flush_self_originated_lsas_now(ospf);
if (!ospf->gr_info.prepare_in_progress)
ospf_flush_self_originated_lsas_now(ospf);
/* Unregister redistribution */
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
@ -805,6 +812,7 @@ static void ospf_finish_final(struct ospf *ospf)
OSPF_TIMER_OFF(ospf->t_sr_update);
OSPF_TIMER_OFF(ospf->t_default_routemap_timer);
OSPF_TIMER_OFF(ospf->t_external_aggr);
OSPF_TIMER_OFF(ospf->gr_info.t_grace_period);
LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
ospf_discard_from_db(ospf, ospf->lsdb, lsa);
@ -826,7 +834,8 @@ static void ospf_finish_final(struct ospf *ospf)
if (ospf->old_table)
ospf_route_table_free(ospf->old_table);
if (ospf->new_table) {
ospf_route_delete(ospf, ospf->new_table);
if (!ospf->gr_info.prepare_in_progress)
ospf_route_delete(ospf, ospf->new_table);
ospf_route_table_free(ospf->new_table);
}
if (ospf->old_rtrs)
@ -834,11 +843,13 @@ static void ospf_finish_final(struct ospf *ospf)
if (ospf->new_rtrs)
ospf_rtrs_free(ospf->new_rtrs);
if (ospf->new_external_route) {
ospf_route_delete(ospf, ospf->new_external_route);
if (!ospf->gr_info.prepare_in_progress)
ospf_route_delete(ospf, ospf->new_external_route);
ospf_route_table_free(ospf->new_external_route);
}
if (ospf->old_external_route) {
ospf_route_delete(ospf, ospf->old_external_route);
if (!ospf->gr_info.prepare_in_progress)
ospf_route_delete(ospf, ospf->old_external_route);
ospf_route_table_free(ospf->old_external_route);
}
if (ospf->external_lsas) {

View file

@ -134,6 +134,16 @@ enum protection_type {
OSPF_TI_LFA_NODE_PROTECTION,
};
/* OSPF nonstop forwarding aka Graceful Restart */
struct ospf_gr_info {
bool restart_support;
bool restart_in_progress;
bool prepare_in_progress;
bool finishing_restart;
uint32_t grace_period;
struct thread *t_grace_period;
};
/* OSPF instance structure. */
struct ospf {
/* OSPF's running state based on the '[no] router ospf [<instance>]'
@ -384,6 +394,9 @@ struct ospf {
/* MPLS LDP-IGP Sync */
struct ldp_sync_info_cmd ldp_sync_cmd;
/* OSPF Graceful Restart info */
struct ospf_gr_info gr_info;
/* TI-LFA support for all interfaces. */
bool ti_lfa_enabled;
enum protection_type ti_lfa_protection_type;

View file

@ -8,6 +8,7 @@ sbin_PROGRAMS += ospfd/ospfd
vtysh_scan += \
ospfd/ospf_bfd.c \
ospfd/ospf_dump.c \
ospfd/ospf_gr.c \
ospfd/ospf_ldp_sync.c \
ospfd/ospf_opaque.c \
ospfd/ospf_ri.c \
@ -35,6 +36,7 @@ ospfd_libfrrospf_a_SOURCES = \
ospfd/ospf_errors.c \
ospfd/ospf_ext.c \
ospfd/ospf_flood.c \
ospfd/ospf_gr.c \
ospfd/ospf_ia.c \
ospfd/ospf_interface.c \
ospfd/ospf_ism.c \
@ -82,6 +84,7 @@ clippy_scan += \
ospfd/ospf_vty.c \
ospfd/ospf_ldp_sync.c \
ospfd/ospf_dump.c \
ospfd/ospf_gr.c \
# end
noinst_HEADERS += \
@ -100,6 +103,7 @@ noinst_HEADERS += \
ospfd/ospf_network.h \
ospfd/ospf_packet.h \
ospfd/ospf_ri.h \
ospfd/ospf_gr.h \
ospfd/ospf_route.h \
ospfd/ospf_routemap_nb.h \
ospfd/ospf_spf.h \
@ -108,7 +112,6 @@ noinst_HEADERS += \
ospfd/ospf_te.h \
ospfd/ospf_vty.h \
ospfd/ospf_zebra.h \
ospfd/ospf_gr_helper.h \
# end
ospfd_ospfd_LDADD = ospfd/libfrrospf.a lib/libfrr.la $(LIBCAP) $(LIBM)

View file

@ -365,7 +365,7 @@ def create_common_configuration(
return True
def kill_router_daemons(tgen, router, daemons):
def kill_router_daemons(tgen, router, daemons, save_config=True):
"""
Router's current config would be saved to /etc/frr/ for each daemon
and daemon would be killed forcefully using SIGKILL.
@ -379,9 +379,10 @@ def kill_router_daemons(tgen, router, daemons):
try:
router_list = tgen.routers()
# Saving router config to /etc/frr, which will be loaded to router
# when it starts
router_list[router].vtysh_cmd("write memory")
if save_config:
# Saving router config to /etc/frr, which will be loaded to router
# when it starts
router_list[router].vtysh_cmd("write memory")
# Kill Daemons
result = router_list[router].killDaemons(daemons)

View file

@ -0,0 +1,32 @@
password 1
hostname rt1
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 1
!
interface eth-rt2
ip ospf network point-to-point
ip ospf area 1
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 1.1.1.1
capability opaque
redistribute connected
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,98 @@
{
"routerId":"1.1.1.1",
"areas":{
"0.0.0.1":{
"routerLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"1.1.1.1",
"numOfRouterLinks":3
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":2
}
],
"summaryLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"6.6.6.6",
"advertisedRouter":"2.2.2.2"
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,11 @@
{
"neighbors":{
"2.2.2.2":[
{
"state":"Full\/DROther",
"address":"10.0.1.2",
"ifaceName":"eth-rt2:10.0.1.1"
}
]
}
}

View file

@ -0,0 +1,180 @@
{
"1.1.1.1\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.1",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"2.2.2.2\/32":{
"routeType":"N IA",
"cost":10,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"3.3.3.3\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"4.4.4.4\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"5.5.5.5\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"6.6.6.6\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"7.7.7.7\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"10.0.1.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.1",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt2"
}
]
},
"10.0.2.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"10.0.3.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"10.0.4.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"10.0.5.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"10.0.6.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"2.2.2.2":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.1",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":30,
"area":"0.0.0.1",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":40,
"nexthops":[
{
"ip":"10.0.1.2",
"via":"eth-rt2"
}
]
}
}

View file

@ -0,0 +1,210 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.1.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
]
}

View file

@ -0,0 +1,23 @@
password 1
hostname rt1
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 1.1.1.1/32
!
interface stub1
ip address 172.16.1.1/24
!
interface eth-rt2
ip address 10.0.1.1/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,37 @@
password 1
hostname rt2
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 0
!
interface eth-rt1
ip ospf network point-to-point
ip ospf area 1
ip ospf hello-interval 3
ip ospf dead-interval 9
!
interface eth-rt3
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 2.2.2.2
capability opaque
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,160 @@
{
"routerId":"2.2.2.2",
"areas":{
"0.0.0.0":{
"routerLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":3
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"3.3.3.3",
"numOfRouterLinks":7
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":3
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2"
}
]
},
"0.0.0.1":{
"routerLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"1.1.1.1",
"numOfRouterLinks":3
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":2
}
],
"summaryLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"6.6.6.6",
"advertisedRouter":"2.2.2.2"
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,18 @@
{
"neighbors":{
"1.1.1.1":[
{
"state":"Full\/DROther",
"address":"10.0.1.1",
"ifaceName":"eth-rt1:10.0.1.2"
}
],
"3.3.3.3":[
{
"state":"Full\/DROther",
"address":"10.0.2.3",
"ifaceName":"eth-rt3:10.0.2.2"
}
]
}
}

View file

@ -0,0 +1,201 @@
{
"1.1.1.1\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.1",
"nexthops":[
{
"ip":"10.0.1.1",
"via":"eth-rt1"
}
]
},
"2.2.2.2\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"3.3.3.3\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"4.4.4.4\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"5.5.5.5\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"6.6.6.6\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"7.7.7.7\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"10.0.1.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.1",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt1"
}
]
},
"10.0.2.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt3"
}
]
},
"10.0.3.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"10.0.4.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"10.0.5.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"10.0.6.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"1.1.1.1":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.1",
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.1.1",
"via":"eth-rt1"
}
]
},
"4.4.4.4":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
},
"172.16.1.0\/24":{
"routeType":"N E2",
"cost":10,
"nexthops":[
{
"ip":"10.0.1.1",
"via":"eth-rt1"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":30,
"nexthops":[
{
"ip":"10.0.2.3",
"via":"eth-rt3"
}
]
}
}

View file

@ -0,0 +1,224 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.1.1",
"afi":"ipv4",
"interfaceName":"eth-rt1"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt1"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"172.16.1.0\/24":[
{
"prefix":"172.16.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.1.1",
"afi":"ipv4",
"interfaceName":"eth-rt1"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
]
}

View file

@ -0,0 +1,23 @@
password 1
hostname rt2
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 2.2.2.2/32
!
interface eth-rt1
ip address 10.0.1.2/24
!
interface eth-rt3
ip address 10.0.2.2/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,43 @@
password 1
hostname rt3
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 0
!
interface eth-rt2
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
interface eth-rt4
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
interface eth-rt6
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 3.3.3.3
capability opaque
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,83 @@
{
"routerId":"3.3.3.3",
"areas":{
"0.0.0.0":{
"routerLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":3
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"3.3.3.3",
"numOfRouterLinks":7
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":3
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2"
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,25 @@
{
"neighbors":{
"2.2.2.2":[
{
"state":"Full\/DROther",
"address":"10.0.2.2",
"ifaceName":"eth-rt2:10.0.2.3"
}
],
"4.4.4.4":[
{
"state":"Full\/DROther",
"address":"10.0.3.4",
"ifaceName":"eth-rt4:10.0.3.3"
}
],
"6.6.6.6":[
{
"state":"Full\/DROther",
"address":"10.0.4.6",
"ifaceName":"eth-rt6:10.0.4.3"
}
]
}
}

View file

@ -0,0 +1,214 @@
{
"1.1.1.1\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"2.2.2.2\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"3.3.3.3\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"4.4.4.4\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.4",
"via":"eth-rt4"
}
]
},
"5.5.5.5\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.4",
"via":"eth-rt4"
}
]
},
"6.6.6.6\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.6",
"via":"eth-rt6"
}
]
},
"7.7.7.7\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.6",
"via":"eth-rt6"
}
]
},
"10.0.1.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"10.0.2.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt2"
}
]
},
"10.0.3.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt4"
}
]
},
"10.0.4.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt6"
}
]
},
"10.0.5.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.4",
"via":"eth-rt4"
}
]
},
"10.0.6.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.6",
"via":"eth-rt6"
}
]
},
"1.1.1.1":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"2.2.2.2":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"4.4.4.4":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.3.4",
"via":"eth-rt4"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.4.6",
"via":"eth-rt6"
}
]
},
"172.16.1.0\/24":{
"routeType":"N E2",
"cost":20,
"nexthops":[
{
"ip":"10.0.2.2",
"via":"eth-rt2"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":20,
"nexthops":[
{
"ip":"10.0.4.6",
"via":"eth-rt6"
}
]
}
}

View file

@ -0,0 +1,223 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.3.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.4.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt2"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"172.16.1.0\/24":[
{
"prefix":"172.16.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.2.2",
"afi":"ipv4",
"interfaceName":"eth-rt2"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
]
}

View file

@ -0,0 +1,26 @@
password 1
hostname rt3
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 3.3.3.3/32
!
interface eth-rt2
ip address 10.0.2.3/24
!
interface eth-rt4
ip address 10.0.3.3/24
!
interface eth-rt6
ip address 10.0.4.3/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,37 @@
password 1
hostname rt4
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 0
!
interface eth-rt3
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
interface eth-rt5
ip ospf network point-to-point
ip ospf area 2
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 4.4.4.4
capability opaque
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,164 @@
{
"routerId":"4.4.4.4",
"areas":{
"0.0.0.0":{
"routerLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":3
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"3.3.3.3",
"numOfRouterLinks":7
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":3
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2"
}
]
},
"0.0.0.2":{
"routerLinkStates":[
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":2
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"5.5.5.5",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"4.4.4.4"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"4.4.4.4"
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,18 @@
{
"neighbors":{
"3.3.3.3":[
{
"state":"Full\/DROther",
"address":"10.0.3.3",
"ifaceName":"eth-rt3:10.0.3.4"
}
],
"5.5.5.5":[
{
"state":"Full\/DROther",
"address":"10.0.5.5",
"ifaceName":"eth-rt5:10.0.5.4"
}
]
}
}

View file

@ -0,0 +1,202 @@
{
"1.1.1.1\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"2.2.2.2\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"3.3.3.3\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"4.4.4.4\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"5.5.5.5\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.5",
"via":"eth-rt5"
}
]
},
"6.6.6.6\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"7.7.7.7\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"10.0.1.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"10.0.2.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"10.0.3.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt3"
}
]
},
"10.0.4.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"10.0.5.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.2",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt5"
}
]
},
"10.0.6.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"1.1.1.1":{
"routeType":"R ",
"cost":30,
"area":"0.0.0.0",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"2.2.2.2":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"172.16.1.0\/24":{
"routeType":"N E2",
"cost":30,
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":30,
"nexthops":[
{
"ip":"10.0.3.3",
"via":"eth-rt3"
}
]
}
}

View file

@ -0,0 +1,224 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.5.5",
"afi":"ipv4",
"interfaceName":"eth-rt5"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt5"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"172.16.1.0\/24":[
{
"prefix":"172.16.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.3.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
]
}

View file

@ -0,0 +1,23 @@
password 1
hostname rt4
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 4.4.4.4/32
!
interface eth-rt3
ip address 10.0.3.4/24
!
interface eth-rt5
ip address 10.0.5.4/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,31 @@
password 1
hostname rt5
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 2
!
interface eth-rt4
ip ospf network point-to-point
ip ospf area 2
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 5.5.5.5
capability opaque
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,102 @@
{
"routerId":"5.5.5.5",
"areas":{
"0.0.0.2":{
"routerLinkStates":[
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":2
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"5.5.5.5",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"4.4.4.4"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"4.4.4.4"
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,11 @@
{
"neighbors":{
"4.4.4.4":[
{
"state":"Full\/DROther",
"address":"10.0.5.4",
"ifaceName":"eth-rt4:10.0.5.5"
}
]
}
}

View file

@ -0,0 +1,203 @@
{
"1.1.1.1\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"2.2.2.2\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"3.3.3.3\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"4.4.4.4\/32":{
"routeType":"N IA",
"cost":10,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"5.5.5.5\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.2",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"6.6.6.6\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"7.7.7.7\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"10.0.1.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"10.0.2.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"10.0.3.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"10.0.4.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"10.0.5.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.2",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt4"
}
]
},
"10.0.6.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.2",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"1.1.1.1":{
"routeType":"R ",
"cost":40,
"area":"0.0.0.2",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"4.4.4.4":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.2",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":30,
"area":"0.0.0.2",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"172.16.1.0\/24":{
"routeType":"N E2",
"cost":40,
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":40,
"nexthops":[
{
"ip":"10.0.5.4",
"via":"eth-rt4"
}
]
}
}

View file

@ -0,0 +1,225 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt4"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"172.16.1.0\/24":[
{
"prefix":"172.16.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.5.4",
"afi":"ipv4",
"interfaceName":"eth-rt4"
}
]
}
]
}

View file

@ -0,0 +1,20 @@
password 1
hostname rt5
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 5.5.5.5/32
!
interface eth-rt4
ip address 10.0.5.5/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,38 @@
password 1
hostname rt6
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 0
!
interface eth-rt3
ip ospf network point-to-point
ip ospf area 0
ip ospf hello-interval 3
ip ospf dead-interval 9
!
interface eth-rt7
ip ospf network point-to-point
ip ospf area 3
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 6.6.6.6
capability opaque
area 3 nssa
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,168 @@
{
"routerId":"6.6.6.6",
"areas":{
"0.0.0.0":{
"routerLinkStates":[
{
"lsId":"2.2.2.2",
"advertisedRouter":"2.2.2.2",
"numOfRouterLinks":3
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"3.3.3.3",
"numOfRouterLinks":7
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"4.4.4.4",
"numOfRouterLinks":3
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"7.7.7.7\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"2.2.2.2",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"4.4.4.4",
"summaryAddress":"10.0.5.0\/24"
},
{
"lsId":"10.0.6.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.6.0\/24"
}
],
"asbrSummaryLinkStates":[
{
"lsId":"1.1.1.1",
"advertisedRouter":"2.2.2.2"
}
]
},
"0.0.0.3":{
"routerLinkStates":[
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":2
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"7.7.7.7",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"0.0.0.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"0.0.0.0\/0"
},
{
"lsId":"1.1.1.1",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.5.0\/24"
}
],
"nssaExternalLinkStates":[
{
"lsId":"192.168.1.0",
"advertisedRouter":"7.7.7.7",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"172.16.1.0",
"advertisedRouter":"1.1.1.1",
"metricType":"E2",
"route":"172.16.1.0\/24",
"tag":0
},
{
"lsId":"192.168.1.0",
"advertisedRouter":"6.6.6.6",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,18 @@
{
"neighbors":{
"3.3.3.3":[
{
"state":"Full\/DROther",
"address":"10.0.4.3",
"ifaceName":"eth-rt3:10.0.4.6"
}
],
"7.7.7.7":[
{
"state":"Full\/DROther",
"address":"10.0.6.7",
"ifaceName":"eth-rt7:10.0.6.6"
}
]
}
}

View file

@ -0,0 +1,214 @@
{
"1.1.1.1\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"2.2.2.2\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"3.3.3.3\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"4.4.4.4\/32":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"5.5.5.5\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"6.6.6.6\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"7.7.7.7\/32":{
"routeType":"N",
"cost":10,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.7",
"via":"eth-rt7"
}
]
},
"10.0.1.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"10.0.2.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"10.0.3.0\/24":{
"routeType":"N",
"cost":20,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"10.0.4.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.0",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt3"
}
]
},
"10.0.5.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.0",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"10.0.6.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.3",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt7"
}
]
},
"1.1.1.1":{
"routeType":"R ",
"cost":30,
"area":"0.0.0.0",
"IA":true,
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"2.2.2.2":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"4.4.4.4":{
"routeType":"R ",
"cost":20,
"area":"0.0.0.0",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"7.7.7.7":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.3",
"routerType":"asbr",
"nexthops":[
{
"ip":"10.0.6.7",
"via":"eth-rt7"
}
]
},
"172.16.1.0\/24":{
"routeType":"N E2",
"cost":30,
"nexthops":[
{
"ip":"10.0.4.3",
"via":"eth-rt3"
}
]
},
"192.168.1.0\/24":{
"routeType":"N E2",
"cost":10,
"nexthops":[
{
"ip":"10.0.6.7",
"via":"eth-rt7"
}
]
}
}

View file

@ -0,0 +1,224 @@
{
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.6.7",
"afi":"ipv4",
"interfaceName":"eth-rt7"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt7"
}
]
}
],
"172.16.1.0\/24":[
{
"prefix":"172.16.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.4.3",
"afi":"ipv4",
"interfaceName":"eth-rt3"
}
]
}
],
"192.168.1.0\/24":[
{
"prefix":"192.168.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.6.7",
"afi":"ipv4",
"interfaceName":"eth-rt7"
}
]
}
]
}

View file

@ -0,0 +1,23 @@
password 1
hostname rt6
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 6.6.6.6/32
!
interface eth-rt3
ip address 10.0.4.6/24
!
interface eth-rt7
ip address 10.0.6.6/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,33 @@
password 1
hostname rt7
log file ospfd.log
log commands
!
debug ospf zebra
debug ospf event
debug ospf lsa
debug ospf te
debug ospf packet all
debug ospf packet ls-update detail
debug ospf ism
debug ospf nsm
debug ospf nssa
debug ospf graceful-restart
!
interface lo
ip ospf area 3
!
interface eth-rt6
ip ospf network point-to-point
ip ospf area 3
ip ospf hello-interval 3
ip ospf dead-interval 9
!
router ospf
router-id 7.7.7.7
capability opaque
redistribute connected
area 3 nssa
graceful-restart grace-period 120
graceful-restart helper-only
!

View file

@ -0,0 +1,99 @@
{
"routerId":"7.7.7.7",
"areas":{
"0.0.0.3":{
"routerLinkStates":[
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"numOfRouterLinks":2
},
{
"lsId":"7.7.7.7",
"advertisedRouter":"7.7.7.7",
"numOfRouterLinks":3
}
],
"summaryLinkStates":[
{
"lsId":"0.0.0.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"0.0.0.0\/0"
},
{
"lsId":"1.1.1.1",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"1.1.1.1\/32"
},
{
"lsId":"2.2.2.2",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"2.2.2.2\/32"
},
{
"lsId":"3.3.3.3",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"3.3.3.3\/32"
},
{
"lsId":"4.4.4.4",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"4.4.4.4\/32"
},
{
"lsId":"5.5.5.5",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"5.5.5.5\/32"
},
{
"lsId":"6.6.6.6",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"6.6.6.6\/32"
},
{
"lsId":"10.0.1.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.1.0\/24"
},
{
"lsId":"10.0.2.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.2.0\/24"
},
{
"lsId":"10.0.3.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.3.0\/24"
},
{
"lsId":"10.0.4.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.4.0\/24"
},
{
"lsId":"10.0.5.0",
"advertisedRouter":"6.6.6.6",
"summaryAddress":"10.0.5.0\/24"
}
],
"nssaExternalLinkStates":[
{
"lsId":"192.168.1.0",
"advertisedRouter":"7.7.7.7",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}
},
"asExternalLinkStates":[
{
"lsId":"192.168.1.0",
"advertisedRouter":"7.7.7.7",
"metricType":"E2",
"route":"192.168.1.0\/24",
"tag":0
}
]
}

View file

@ -0,0 +1,11 @@
{
"neighbors":{
"6.6.6.6":[
{
"state":"Full\/DROther",
"address":"10.0.6.6",
"ifaceName":"eth-rt6:10.0.6.7"
}
]
}
}

View file

@ -0,0 +1,168 @@
{
"0.0.0.0\/0":{
"routeType":"N IA",
"cost":11,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"1.1.1.1\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"2.2.2.2\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"3.3.3.3\/32":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"4.4.4.4\/32":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"5.5.5.5\/32":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"6.6.6.6\/32":{
"routeType":"N IA",
"cost":10,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"7.7.7.7\/32":{
"routeType":"N",
"cost":0,
"area":"0.0.0.3",
"nexthops":[
{
"ip":" ",
"directly attached to":"lo"
}
]
},
"10.0.1.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"10.0.2.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"10.0.3.0\/24":{
"routeType":"N IA",
"cost":30,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"10.0.4.0\/24":{
"routeType":"N IA",
"cost":20,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"10.0.5.0\/24":{
"routeType":"N IA",
"cost":40,
"area":"0.0.0.3",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
},
"10.0.6.0\/24":{
"routeType":"N",
"cost":10,
"area":"0.0.0.3",
"nexthops":[
{
"ip":" ",
"directly attached to":"eth-rt6"
}
]
},
"6.6.6.6":{
"routeType":"R ",
"cost":10,
"area":"0.0.0.3",
"routerType":"abr",
"nexthops":[
{
"ip":"10.0.6.6",
"via":"eth-rt6"
}
]
}
}

View file

@ -0,0 +1,210 @@
{
"0.0.0.0\/0":[
{
"prefix":"0.0.0.0\/0",
"protocol":"ospf",
"distance":110,
"metric":11,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"1.1.1.1\/32":[
{
"prefix":"1.1.1.1\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"2.2.2.2\/32":[
{
"prefix":"2.2.2.2\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"3.3.3.3\/32":[
{
"prefix":"3.3.3.3\/32",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"4.4.4.4\/32":[
{
"prefix":"4.4.4.4\/32",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"5.5.5.5\/32":[
{
"prefix":"5.5.5.5\/32",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"6.6.6.6\/32":[
{
"prefix":"6.6.6.6\/32",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"7.7.7.7\/32":[
{
"prefix":"7.7.7.7\/32",
"protocol":"ospf",
"distance":110,
"metric":0,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"lo"
}
]
}
],
"10.0.1.0\/24":[
{
"prefix":"10.0.1.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.2.0\/24":[
{
"prefix":"10.0.2.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.3.0\/24":[
{
"prefix":"10.0.3.0\/24",
"protocol":"ospf",
"distance":110,
"metric":30,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.4.0\/24":[
{
"prefix":"10.0.4.0\/24",
"protocol":"ospf",
"distance":110,
"metric":20,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.5.0\/24":[
{
"prefix":"10.0.5.0\/24",
"protocol":"ospf",
"distance":110,
"metric":40,
"nexthops":[
{
"ip":"10.0.6.6",
"afi":"ipv4",
"interfaceName":"eth-rt6"
}
]
}
],
"10.0.6.0\/24":[
{
"prefix":"10.0.6.0\/24",
"protocol":"ospf",
"distance":110,
"metric":10,
"nexthops":[
{
"directlyConnected":true,
"interfaceName":"eth-rt6"
}
]
}
]
}

View file

@ -0,0 +1,23 @@
password 1
hostname rt7
log file zebra.log
log commands
!
debug zebra event
debug zebra packet
debug zebra rib
debug zebra kernel
!
interface lo
ip address 7.7.7.7/32
!
interface stub1
ip address 192.168.1.1/24
!
interface eth-rt6
ip address 10.0.6.7/24
!
ip forwarding
!
line vty
!

View file

@ -0,0 +1,393 @@
#!/usr/bin/env python
#
# test_ospf_gr_topo1.py
# Part of NetDEF Topology Tests
#
# Copyright (c) 2021 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
"""
test_ospf_gr_topo1.py:
+---------+
| RT1 |
| 1.1.1.1 |
+---------+
|eth-rt2
|
|10.0.1.0/24
|
|eth-rt1
+---------+
| RT2 |
| 2.2.2.2 |
+---------+
|eth-rt3
|
|10.0.2.0/24
|
|eth-rt2
+---------+
| RT3 |
| 3.3.3.3 |
+---------+
eth-rt4| |eth-rt6
| |
10.0.3.0/24 | | 10.0.4.0/24
+---------+ +--------+
| |
|eth-rt3 |eth-rt3
+---------+ +---------+
| RT4 | | RT6 |
| 4.4.4.4 | | 6.6.6.6 |
+---------+ +---------+
|eth-rt5 |eth-rt7
| |
|10.0.5.0/24 |10.0.6.0/24
| |
|eth-rt4 |eth-rt6
+---------+ +---------+
| RT5 | | RT7 |
| 5.5.5.5 | | 7.7.7.7 |
+---------+ +---------+
"""
import os
import sys
import pytest
import json
import re
import tempfile
from time import sleep
from functools import partial
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# 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
from lib.common_config import (
kill_router_daemons,
start_router_daemons,
)
# Required to instantiate the topology builder class.
from mininet.topo import Topo
pytestmark = [pytest.mark.ospfd]
# Global multi-dimensional dictionary containing all expected outputs
outputs = {}
class TemplateTopo(Topo):
"Test topology builder"
def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
#
# Define FRR Routers
#
for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
tgen.add_router(router)
#
# Define connections
#
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["rt1"], nodeif="eth-rt2")
switch.add_link(tgen.gears["rt2"], nodeif="eth-rt1")
switch = tgen.add_switch("s2")
switch.add_link(tgen.gears["rt1"], nodeif="stub1")
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["rt2"], nodeif="eth-rt3")
switch.add_link(tgen.gears["rt3"], nodeif="eth-rt2")
switch = tgen.add_switch("s4")
switch.add_link(tgen.gears["rt3"], nodeif="eth-rt4")
switch.add_link(tgen.gears["rt4"], nodeif="eth-rt3")
switch = tgen.add_switch("s5")
switch.add_link(tgen.gears["rt3"], nodeif="eth-rt6")
switch.add_link(tgen.gears["rt6"], nodeif="eth-rt3")
switch = tgen.add_switch("s6")
switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
switch = tgen.add_switch("s7")
switch.add_link(tgen.gears["rt6"], nodeif="eth-rt7")
switch.add_link(tgen.gears["rt7"], nodeif="eth-rt6")
switch = tgen.add_switch("s8")
switch.add_link(tgen.gears["rt7"], nodeif="stub1")
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
# For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
)
tgen.start_router()
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
# This function tears down the whole topology.
tgen.stop_topology()
def router_compare_json_output(rname, command, reference, tries):
"Compare router JSON output"
logger.info('Comparing router "%s" "%s" output', rname, command)
tgen = get_topogen()
filename = "{}/{}/{}".format(CWD, rname, reference)
expected = json.loads(open(filename).read())
test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
_, diff = topotest.run_and_expect(test_func, None, count=tries, wait=0.5)
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
def check_routers(initial_convergence=False, exiting=None, restarting=None):
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
# Check the RIB first, which should be preserved across restarts in
# all routers of the routing domain.
if initial_convergence == True:
tries = 240
else:
tries = 1
router_compare_json_output(
rname, "show ip route ospf json", "show_ip_route.json", tries
)
# Check that all adjacencies are up and running (except when there's
# an OSPF instance that is shutting down).
if exiting == None:
tries = 240
router_compare_json_output(
rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json", tries
)
# Check the OSPF RIB and LSDB.
# In the restarting router, wait up to one minute for the LSDB to converge.
if exiting != rname:
if initial_convergence == True or restarting == rname:
tries = 240
else:
tries = 1
router_compare_json_output(
rname, "show ip ospf database json", "show_ip_ospf_database.json", tries
)
router_compare_json_output(
rname, "show ip ospf route json", "show_ip_ospf_route.json", tries
)
#
# Test initial network convergence
#
def test_initial_convergence():
logger.info("Test: verify initial network convergence")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
check_routers(initial_convergence=True)
#
# Test rt1 performing a graceful restart
#
def test_gr_rt1():
logger.info("Test: verify rt1 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False)
check_routers(exiting="rt1")
start_router_daemons(tgen, "rt1", ["ospfd"])
check_routers(restarting="rt1")
#
# Test rt2 performing a graceful restart
#
def test_gr_rt2():
logger.info("Test: verify rt2 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False)
check_routers(exiting="rt2")
start_router_daemons(tgen, "rt2", ["ospfd"])
check_routers(restarting="rt2")
#
# Test rt3 performing a graceful restart
#
def test_gr_rt3():
logger.info("Test: verify rt3 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False)
check_routers(exiting="rt3")
start_router_daemons(tgen, "rt3", ["ospfd"])
check_routers(restarting="rt3")
#
# Test rt4 performing a graceful restart
#
def test_gr_rt4():
logger.info("Test: verify rt4 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False)
check_routers(exiting="rt4")
start_router_daemons(tgen, "rt4", ["ospfd"])
check_routers(restarting="rt4")
#
# Test rt5 performing a graceful restart
#
def test_gr_rt5():
logger.info("Test: verify rt5 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False)
check_routers(exiting="rt5")
start_router_daemons(tgen, "rt5", ["ospfd"])
check_routers(restarting="rt5")
#
# Test rt6 performing a graceful restart
#
def test_gr_rt6():
logger.info("Test: verify rt6 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False)
check_routers(exiting="rt6")
start_router_daemons(tgen, "rt6", ["ospfd"])
check_routers(restarting="rt6")
#
# Test rt7 performing a graceful restart
#
def test_gr_rt7():
logger.info("Test: verify rt7 performing a graceful restart")
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"')
sleep(3)
kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False)
check_routers(exiting="rt7")
start_router_daemons(tgen, "rt7", ["ospfd"])
check_routers(restarting="rt7")
# Memory leak test template
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))