Merge pull request #8935 from rgirada/ospfv3_gr_helper

ospf6d: Support for ospfv3  graceful restart  helper functionality
This commit is contained in:
Renato Westphal 2021-08-19 15:01:34 -03:00 committed by GitHub
commit f70b917249
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1869 additions and 22 deletions

View File

@ -258,6 +258,39 @@ Redistribute routes to OSPF6
argument injects the default route regardless of it being present in the argument injects the default route regardless of it being present in the
router. Metric values and route-map can also be specified optionally. router. Metric values and route-map can also be specified optionally.
Graceful Restart Helper
=======================
.. clicmd:: graceful-restart helper-only [A.B.C.D]
Configure Graceful Restart (RFC 5187) helper support.
By default, helper support is disabled for all neighbours.
This config enables/disables helper support on this router
for all neighbours.
To enable/disable helper support for a specific
neighbour, the router-id (A.B.C.D) has to be specified.
.. clicmd:: graceful-restart helper strict-lsa-checking
If 'strict-lsa-checking' is configured then the helper will
abort the Graceful Restart when a LSA change occurs which
affects the restarting router.
By default 'strict-lsa-checking' is enabled"
.. clicmd:: graceful-restart helper supported-grace-time (10-1800)
Supports as HELPER for configured grace period.
.. clicmd:: graceful-restart helper planned-only
It helps to support as HELPER only for planned
restarts. By default, it supports both planned and
unplanned outages.
.. _showing-ospf6-information: .. _showing-ospf6-information:
Showing OSPF6 information Showing OSPF6 information
@ -351,6 +384,19 @@ Showing OSPF6 information
JSON object, with each router having "cost", "isLeafNode" and "children" as JSON object, with each router having "cost", "isLeafNode" and "children" as
arguments. arguments.
.. clicmd:: show ipv6 ospf6 graceful-restart helper [detail] [json]
This command shows the graceful-restart helper details including helper
configuration parameters.
Debugging OSPF6
===============
.. clicmd:: debug ospf6 graceful-restart
This command enables/disables debug information for ospf6 graceful restart
helper functionality.
.. _ospf6-debugging: .. _ospf6-debugging:

View File

@ -41,6 +41,7 @@
#include "ospf6_flood.h" #include "ospf6_flood.h"
#include "ospf6_nssa.h" #include "ospf6_nssa.h"
#include "ospf6_gr.h"
unsigned char conf_debug_ospf6_flooding; unsigned char conf_debug_ospf6_flooding;
@ -323,6 +324,22 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
/* actually install */ /* actually install */
lsa->installed = now; lsa->installed = now;
/* Topo change handling */
if (CHECK_LSA_TOPO_CHG_ELIGIBLE(ntohs(lsa->header->type))) {
/* check if it is new lsa ? or existing lsa got modified ?*/
if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) {
struct ospf6 *ospf6;
ospf6 = ospf6_get_by_lsdb(lsa);
assert(ospf6);
ospf6_helper_handle_topo_chg(ospf6, lsa);
}
}
ospf6_lsdb_add(lsa, lsa->lsdb); ospf6_lsdb_add(lsa, lsa->lsdb);
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) { if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
@ -1016,6 +1033,50 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
!= from->ospf6_if->area->ospf6->router_id) != from->ospf6_if->area->ospf6->router_id)
ospf6_flood(from, new); ospf6_flood(from, new);
/* Received Grace-LSA */
if (IS_GRACE_LSA(new)) {
struct ospf6 *ospf6;
ospf6 = ospf6_get_by_lsdb(new);
assert(ospf6);
if (OSPF6_LSA_IS_MAXAGE(new)) {
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Received a maxage GraceLSA from router %pI4",
__func__,
&new->header->adv_router);
if (old) {
ospf6_process_maxage_grace_lsa(
ospf6, new, from);
} else {
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, GraceLSA doesn't exist in lsdb, so discarding GraceLSA",
__func__);
return;
}
} else {
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Received a GraceLSA from router %pI4",
__func__,
&new->header->adv_router);
if (ospf6_process_grace_lsa(ospf6, new, from)
== OSPF6_GR_NOT_HELPER) {
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Not moving to HELPER role, So dicarding GraceLSA",
__func__);
return;
}
}
}
/* (d), installing lsdb, which may cause routing /* (d), installing lsdb, which may cause routing
table calculation (replacing database copy) */ table calculation (replacing database copy) */
ospf6_install_lsa(new); ospf6_install_lsa(new);

161
ospf6d/ospf6_gr.h Normal file
View File

@ -0,0 +1,161 @@
/*
* OSPF6 Graceful Retsart helper functions.
*
* Copyright (C) 2021-22 Vmware, Inc.
* Rajesh Kumar Girada
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef OSPF6_GR_H
#define OSPF6_GR_H
#define OSPF6_GR_NOT_HELPER 0
#define OSPF6_GR_ACTIVE_HELPER 1
#define OSPF6_GR_HELPER_NO_LSACHECK 0
#define OSPF6_GR_HELPER_LSACHECK 1
#define OSPF6_MAX_GRACE_INTERVAL 1800
#define OSPF6_MIN_GRACE_INTERVAL 1
/* Debug option */
extern unsigned char conf_debug_ospf6_gr;
#define OSPF6_DEBUG_GR 0x01
#define OSPF6_DEBUG_GR_ON() (conf_debug_ospf6_gr |= OSPF6_DEBUG_GR)
#define OSPF6_DEBUG_GR_OFF() (conf_debug_ospf6_gr &= ~OSPF6_DEBUG_GR)
#define IS_DEBUG_OSPF6_GR conf_debug_ospf6_gr
enum ospf6_helper_exit_reason {
OSPF6_GR_HELPER_EXIT_NONE = 0,
OSPF6_GR_HELPER_INPROGRESS,
OSPF6_GR_HELPER_TOPO_CHG,
OSPF6_GR_HELPER_GRACE_TIMEOUT,
OSPF6_GR_HELPER_COMPLETED
};
enum ospf6_gr_restart_reason {
OSPF6_GR_UNKNOWN_RESTART = 0,
OSPF6_GR_SW_RESTART = 1,
OSPF6_GR_SW_UPGRADE = 2,
OSPF6_GR_SWITCH_REDUNDANT_CARD = 3,
OSPF6_GR_INVALID_REASON_CODE = 4
};
enum ospf6_gr_helper_rejected_reason {
OSPF6_HELPER_REJECTED_NONE,
OSPF6_HELPER_SUPPORT_DISABLED,
OSPF6_HELPER_NOT_A_VALID_NEIGHBOUR,
OSPF6_HELPER_PLANNED_ONLY_RESTART,
OSPF6_HELPER_TOPO_CHANGE_RTXMT_LIST,
OSPF6_HELPER_LSA_AGE_MORE
};
#ifdef roundup
#define ROUNDUP(val, gran) roundup(val, gran)
#else /* roundup */
#define ROUNDUP(val, gran) (((val)-1 | (gran)-1) + 1)
#endif /* roundup */
/*
* Generic TLV (type, length, value) macros
*/
struct tlv_header {
uint16_t type; /* Type of Value */
uint16_t length; /* Length of Value portion only, in bytes */
};
#define TLV_HDR_SIZE (sizeof(struct tlv_header))
#define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(uint32_t)))
#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
#define TLV_HDR_TOP(lsah) \
(struct tlv_header *)((char *)(lsah) + OSPF6_LSA_HEADER_SIZE)
#define TLV_HDR_NEXT(tlvh) \
(struct tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
/* Ref RFC5187 appendix-A */
/* Grace period TLV */
#define GRACE_PERIOD_TYPE 1
#define GRACE_PERIOD_LENGTH 4
struct grace_tlv_graceperiod {
struct tlv_header header;
uint32_t interval;
};
#define GRACE_PERIOD_TLV_SIZE sizeof(struct grace_tlv_graceperiod)
/* Restart reason TLV */
#define RESTART_REASON_TYPE 2
#define RESTART_REASON_LENGTH 1
struct grace_tlv_restart_reason {
struct tlv_header header;
uint8_t reason;
uint8_t reserved[3];
};
#define GRACE_RESTART_REASON_TLV_SIZE sizeof(struct grace_tlv_restart_reason)
#define OSPF6_GRACE_LSA_MIN_SIZE \
GRACE_PERIOD_TLV_SIZE + GRACE_RESTART_REASON_TLV_SIZE
struct advRtr {
in_addr_t advRtrAddr;
};
#define OSPF6_HELPER_ENABLE_RTR_COUNT(ospf) \
(ospf6->ospf6_helper_cfg.enable_rtr_list->count)
/* Check , it is a planned restart */
#define OSPF6_GR_IS_PLANNED_RESTART(reason) \
((reason == OSPF6_GR_SW_RESTART) || (reason == OSPF6_GR_SW_UPGRADE))
/* Check the router is HELPER for current neighbour */
#define OSPF6_GR_IS_ACTIVE_HELPER(N) \
((N)->gr_helper_info.gr_helper_status == OSPF6_GR_ACTIVE_HELPER)
/* Check the LSA is GRACE LSA */
#define IS_GRACE_LSA(lsa) (ntohs(lsa->header->type) == OSPF6_LSTYPE_GRACE_LSA)
/* Check neighbour is in FULL state */
#define IS_NBR_STATE_FULL(nbr) (nbr->state == OSPF6_NEIGHBOR_FULL)
extern const char *ospf6_exit_reason_desc[];
extern const char *ospf6_restart_reason_desc[];
extern const char *ospf6_rejected_reason_desc[];
extern void ospf6_gr_helper_config_init(void);
extern void ospf6_gr_helper_init(struct ospf6 *ospf6);
extern void ospf6_gr_helper_deinit(struct ospf6 *ospf6);
extern void ospf6_gr_helper_exit(struct ospf6_neighbor *nbr,
enum ospf6_helper_exit_reason reason);
extern int ospf6_process_grace_lsa(struct ospf6 *ospf6, struct ospf6_lsa *lsa,
struct ospf6_neighbor *nbr);
extern void ospf6_process_maxage_grace_lsa(struct ospf6 *ospf,
struct ospf6_lsa *lsa,
struct ospf6_neighbor *nbr);
extern void ospf6_helper_handle_topo_chg(struct ospf6 *ospf6,
struct ospf6_lsa *lsa);
extern int config_write_ospf6_gr_helper(struct vty *vty, struct ospf6 *ospf6);
extern int config_write_ospf6_debug_gr_helper(struct vty *vty);
#endif /* OSPF6_GR_H */

1375
ospf6d/ospf6_gr_helper.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -44,9 +44,10 @@
#include "ospf6d.h" #include "ospf6d.h"
#include "ospf6_bfd.h" #include "ospf6_bfd.h"
#include "ospf6_zebra.h" #include "ospf6_zebra.h"
#include "ospf6_gr.h"
#include "lib/json.h" #include "lib/json.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names"); DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
DEFINE_QOBJ_TYPE(ospf6_interface); DEFINE_QOBJ_TYPE(ospf6_interface);
DEFINE_HOOK(ospf6_interface_change, DEFINE_HOOK(ospf6_interface_change,
@ -59,6 +60,22 @@ const char *const ospf6_interface_state_str[] = {
"None", "Down", "Loopback", "Waiting", "PointToPoint", "None", "Down", "Loopback", "Waiting", "PointToPoint",
"DROther", "BDR", "DR", NULL}; "DROther", "BDR", "DR", NULL};
int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
{
int count = 0;
struct ospf6_neighbor *nbr = NULL;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, nbr)) {
/* Down state is not shown. */
if (nbr->state == OSPF6_NEIGHBOR_DOWN)
continue;
count++;
}
return count;
}
struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex, struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex,
vrf_id_t vrf_id) vrf_id_t vrf_id)
{ {
@ -579,7 +596,7 @@ static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
return a; return a;
} }
static uint8_t dr_election(struct ospf6_interface *oi) uint8_t dr_election(struct ospf6_interface *oi)
{ {
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct ospf6_neighbor *on, *drouter, *bdrouter, myself; struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
@ -896,6 +913,17 @@ int interface_down(struct thread *thread)
/* Stop trying to set socket options. */ /* Stop trying to set socket options. */
THREAD_OFF(oi->thread_sso); THREAD_OFF(oi->thread_sso);
/* Cease the HELPER role for all the neighbours
* of this interface.
*/
if (ospf6_interface_neighbor_count(oi)) {
struct listnode *ln;
struct ospf6_neighbor *nbr = NULL;
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, ln, nbr))
ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_TOPO_CHG);
}
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
ospf6_neighbor_delete(on); ospf6_neighbor_delete(on);

View File

@ -218,6 +218,8 @@ extern void install_element_ospf6_clear_interface(void);
extern int config_write_ospf6_debug_interface(struct vty *vty); extern int config_write_ospf6_debug_interface(struct vty *vty);
extern void install_element_ospf6_debug_interface(void); extern void install_element_ospf6_debug_interface(void);
extern int ospf6_interface_neighbor_count(struct ospf6_interface *oi);
extern uint8_t dr_election(struct ospf6_interface *oi);
DECLARE_HOOK(ospf6_interface_change, DECLARE_HOOK(ospf6_interface_change,
(struct ospf6_interface * oi, int state, int old_state), (struct ospf6_interface * oi, int state, int old_state),

View File

@ -70,7 +70,8 @@
#define OSPF6_LSTYPE_TYPE_7 0x2007 #define OSPF6_LSTYPE_TYPE_7 0x2007
#define OSPF6_LSTYPE_LINK 0x0008 #define OSPF6_LSTYPE_LINK 0x0008
#define OSPF6_LSTYPE_INTRA_PREFIX 0x2009 #define OSPF6_LSTYPE_INTRA_PREFIX 0x2009
#define OSPF6_LSTYPE_SIZE 0x000a #define OSPF6_LSTYPE_GRACE_LSA 0x000b
#define OSPF6_LSTYPE_SIZE 0x000c
/* Masks for LS Type : RFC 2740 A.4.2.1 "LS type" */ /* Masks for LS Type : RFC 2740 A.4.2.1 "LS type" */
#define OSPF6_LSTYPE_UBIT_MASK 0x8000 #define OSPF6_LSTYPE_UBIT_MASK 0x8000
@ -146,6 +147,9 @@ struct ospf6_lsa {
/* lsa instance */ /* lsa instance */
struct ospf6_lsa_header *header; struct ospf6_lsa_header *header;
/*For topo chg detection in HELPER role*/
bool tobe_acknowledged;
}; };
#define OSPF6_LSA_HEADERONLY 0x01 #define OSPF6_LSA_HEADERONLY 0x01
@ -210,6 +214,14 @@ extern vector ospf6_lsa_handler_vector;
continue; \ continue; \
} }
#define CHECK_LSA_TOPO_CHG_ELIGIBLE(type) \
((type == OSPF6_LSTYPE_ROUTER) \
|| (type == OSPF6_LSTYPE_NETWORK) \
|| (type == OSPF6_LSTYPE_INTER_PREFIX) \
|| (type == OSPF6_LSTYPE_INTER_ROUTER) \
|| (type == OSPF6_LSTYPE_AS_EXTERNAL) \
|| (type == OSPF6_LSTYPE_TYPE_7) \
|| (type == OSPF6_LSTYPE_INTRA_PREFIX))
/* Function Prototypes */ /* Function Prototypes */
extern const char *ospf6_lstype_name(uint16_t type); extern const char *ospf6_lstype_name(uint16_t type);

View File

@ -46,7 +46,7 @@
#include "ospf6_flood.h" #include "ospf6_flood.h"
#include "ospf6d.h" #include "ospf6d.h"
#include "ospf6_gr.h"
#include <netinet/ip6.h> #include <netinet/ip6.h>
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
@ -84,7 +84,9 @@ const uint16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = {
/* 0x2006 */ 0, /* 0x2006 */ 0,
/* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
/* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE, /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
/* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE}; /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
/* 0x200a */ 0,
/* 0x000b */ OSPF6_GRACE_LSA_MIN_SIZE};
/* print functions */ /* print functions */
@ -512,8 +514,44 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
thread_execute(master, hello_received, on, 0); thread_execute(master, hello_received, on, 0);
if (twoway) if (twoway)
thread_execute(master, twoway_received, on, 0); thread_execute(master, twoway_received, on, 0);
else else {
thread_execute(master, oneway_received, on, 0); if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Received oneway hello from RESTARTER so ignore here.",
__PRETTY_FUNCTION__);
if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) {
/* If the router is DR_OTHER, RESTARTER will not wait
* until it receives the hello from it if it receives
* from DR and BDR.
* So, helper might receives ONE_WAY hello from
* RESTARTER. So not allowing to change the state if it
* receives one_way hellow when it acts as HELPER for
* that specific neighbor.
*/
thread_execute(master, oneway_received, on, 0);
}
}
if (OSPF6_GR_IS_ACTIVE_HELPER(on)) {
/* As per the GR Conformance Test Case 7.2. Section 3
* "Also, if X was the Designated Router on network segment S
* when the helping relationship began, Y maintains X as the
* Designated Router until the helping relationship is
* terminated."
* When it is a helper for this neighbor, It should not trigger
* the ISM Events. Also Intentionally not setting the priority
* and other fields so that when the neighbor exits the Grace
* period, it can handle if there is any change before GR and
* after GR.
*/
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Neighbor is under GR Restart, hence ignoring the ISM Events",
__PRETTY_FUNCTION__);
return;
}
/* Schedule interface events */ /* Schedule interface events */
if (backupseen) if (backupseen)
@ -1260,7 +1298,15 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
lsalen - OSPF6_LSA_HEADER_SIZE lsalen - OSPF6_LSA_HEADER_SIZE
- OSPF6_INTRA_PREFIX_LSA_MIN_SIZE, - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */ ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */
); );
case OSPF6_LSTYPE_GRACE_LSA:
if (lsalen < OSPF6_LSA_HEADER_SIZE + GRACE_PERIOD_TLV_SIZE
+ GRACE_RESTART_REASON_TLV_SIZE) {
if (IS_DEBUG_OSPF6_GR)
zlog_debug("%s: Undersized GraceLSA.",
__func__);
return MSG_NG;
}
} }
/* No additional validation is possible for unknown LSA types, which are /* No additional validation is possible for unknown LSA types, which are
themselves valid in OPSFv3, hence the default decision is to accept. themselves valid in OPSFv3, hence the default decision is to accept.

View File

@ -45,6 +45,7 @@
#include "ospf6_lsa.h" #include "ospf6_lsa.h"
#include "ospf6_spf.h" #include "ospf6_spf.h"
#include "ospf6_zebra.h" #include "ospf6_zebra.h"
#include "ospf6_gr.h"
#include "lib/json.h" #include "lib/json.h"
DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
@ -151,6 +152,7 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on)
THREAD_OFF(on->thread_send_lsreq); THREAD_OFF(on->thread_send_lsreq);
THREAD_OFF(on->thread_send_lsupdate); THREAD_OFF(on->thread_send_lsupdate);
THREAD_OFF(on->thread_send_lsack); THREAD_OFF(on->thread_send_lsack);
THREAD_OFF(on->gr_helper_info.t_grace_timer);
bfd_sess_free(&on->bfd_session); bfd_sess_free(&on->bfd_session);
XFREE(MTYPE_OSPF6_NEIGHBOR, on); XFREE(MTYPE_OSPF6_NEIGHBOR, on);
@ -192,19 +194,24 @@ static void ospf6_neighbor_state_change(uint8_t next_state,
if (prev_state == OSPF6_NEIGHBOR_FULL if (prev_state == OSPF6_NEIGHBOR_FULL
|| next_state == OSPF6_NEIGHBOR_FULL) { || next_state == OSPF6_NEIGHBOR_FULL) {
OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area); if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) {
if (on->ospf6_if->state == OSPF6_INTERFACE_DR) { OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area);
OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if); if (on->ospf6_if->state == OSPF6_INTERFACE_DR) {
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if); OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if);
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(
on->ospf6_if);
}
} }
if (next_state == OSPF6_NEIGHBOR_FULL) if (next_state == OSPF6_NEIGHBOR_FULL)
on->ospf6_if->area->intra_prefix_originate = 1; on->ospf6_if->area->intra_prefix_originate = 1;
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); if (!OSPF6_GR_IS_ACTIVE_HELPER(on))
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(
on->ospf6_if->area);
if ((prev_state == OSPF6_NEIGHBOR_LOADING || if ((prev_state == OSPF6_NEIGHBOR_LOADING
prev_state == OSPF6_NEIGHBOR_EXCHANGE) && || prev_state == OSPF6_NEIGHBOR_EXCHANGE)
next_state == OSPF6_NEIGHBOR_FULL) { && next_state == OSPF6_NEIGHBOR_FULL) {
OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if); OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if);
on->ospf6_if->area->full_nbrs++; on->ospf6_if->area->full_nbrs++;
} }
@ -601,12 +608,29 @@ int inactivity_timer(struct thread *thread)
on->drouter = on->prev_drouter = 0; on->drouter = on->prev_drouter = 0;
on->bdrouter = on->prev_bdrouter = 0; on->bdrouter = on->prev_bdrouter = 0;
ospf6_neighbor_state_change(OSPF6_NEIGHBOR_DOWN, on, if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) {
OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); on->drouter = on->prev_drouter = 0;
thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); on->bdrouter = on->prev_bdrouter = 0;
listnode_delete(on->ospf6_if->neighbor_list, on); ospf6_neighbor_state_change(
ospf6_neighbor_delete(on); OSPF6_NEIGHBOR_DOWN, on,
OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER);
thread_add_event(master, neighbor_change, on->ospf6_if, 0,
NULL);
listnode_delete(on->ospf6_if->neighbor_list, on);
ospf6_neighbor_delete(on);
} else {
if (IS_DEBUG_OSPF6_GR)
zlog_debug(
"%s, Acting as HELPER for this neighbour, So restart the dead timer.",
__PRETTY_FUNCTION__);
thread_add_timer(master, inactivity_timer, on,
on->ospf6_if->dead_interval,
&on->inactivity_timer);
}
return 0; return 0;
} }

View File

@ -32,6 +32,38 @@ extern unsigned char conf_debug_ospf6_neighbor;
#define IS_OSPF6_DEBUG_NEIGHBOR(level) \ #define IS_OSPF6_DEBUG_NEIGHBOR(level) \
(conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_##level) (conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_##level)
struct ospf6_helper_info {
/* Grace interval received from
* Restarting Router.
*/
uint32_t recvd_grace_period;
/* Grace interval used for grace
* gracetimer.
*/
uint32_t actual_grace_period;
/* Grace timer,This Router acts as
* helper until this timer until
* this timer expires.
*/
struct thread *t_grace_timer;
/* Helper status */
uint32_t gr_helper_status;
/* Helper exit reason*/
uint32_t helper_exit_reason;
/* Planned/Unplanned restart*/
uint32_t gr_restart_reason;
/* Helper rejected reason */
uint32_t rejected_reason;
};
/* Neighbor structure */ /* Neighbor structure */
struct ospf6_neighbor { struct ospf6_neighbor {
/* Neighbor Router ID String */ /* Neighbor Router ID String */
@ -104,6 +136,9 @@ struct ospf6_neighbor {
/* BFD information */ /* BFD information */
struct bfd_session_params *bfd_session; struct bfd_session_params *bfd_session;
/* ospf6 graceful restart HELPER info */
struct ospf6_helper_info gr_helper_info;
}; };
/* Neighbor state */ /* Neighbor state */

View File

@ -51,6 +51,7 @@
#include "ospf6_intra.h" #include "ospf6_intra.h"
#include "ospf6_spf.h" #include "ospf6_spf.h"
#include "ospf6d.h" #include "ospf6d.h"
#include "ospf6_gr.h"
#include "lib/json.h" #include "lib/json.h"
#include "ospf6_nssa.h" #include "ospf6_nssa.h"
@ -440,6 +441,7 @@ static struct ospf6 *ospf6_create(const char *name)
o->oi_write_q = list_new(); o->oi_write_q = list_new();
ospf6_gr_helper_init(o);
QOBJ_REG(o, ospf6); QOBJ_REG(o, ospf6);
/* Make ospf protocol socket. */ /* Make ospf protocol socket. */
@ -485,6 +487,7 @@ void ospf6_delete(struct ospf6 *o)
QOBJ_UNREG(o); QOBJ_UNREG(o);
ospf6_gr_helper_deinit(o);
ospf6_flush_self_originated_lsas_now(o); ospf6_flush_self_originated_lsas_now(o);
ospf6_disable(o); ospf6_disable(o);
ospf6_del(o); ospf6_del(o);
@ -2233,7 +2236,7 @@ static int config_write_ospf6(struct vty *vty)
ospf6_distance_config_write(vty, ospf6); ospf6_distance_config_write(vty, ospf6);
ospf6_distribute_config_write(vty, ospf6); ospf6_distribute_config_write(vty, ospf6);
ospf6_asbr_summary_config_write(vty, ospf6); ospf6_asbr_summary_config_write(vty, ospf6);
config_write_ospf6_gr_helper(vty, ospf6);
vty_out(vty, "!\n"); vty_out(vty, "!\n");
} }
return 0; return 0;

View File

@ -60,6 +60,43 @@ struct ospf6_redist {
#define ROUTEMAP(R) (R->route_map.map) #define ROUTEMAP(R) (R->route_map.map)
}; };
struct ospf6_gr_helper {
/* Gracefull restart Helper supported configs*/
/* Supported grace interval*/
uint32_t supported_grace_time;
/* Helper support
* Supported : True
* Not Supported : False.
*/
bool is_helper_supported;
/* Support for strict LSA check.
* if it is set,Helper aborted
* upon a TOPO change.
*/
bool strict_lsa_check;
/* Support as HELPER only for
* planned restarts.
*/
bool only_planned_restart;
/* This list contains the advertisement
* routerids for which Helper support is
* enabled.
*/
struct hash *enable_rtr_list;
/* HELPER for number of active
* RESTARTERs.
*/
int active_restarter_cnt;
/* last HELPER exit reason */
uint32_t last_exit_reason;
};
/* OSPFv3 top level data structure */ /* OSPFv3 top level data structure */
struct ospf6 { struct ospf6 {
/* The relevant vrf_id */ /* The relevant vrf_id */
@ -154,6 +191,10 @@ struct ospf6 {
* to support ECMP. * to support ECMP.
*/ */
uint16_t max_multipath; uint16_t max_multipath;
/*ospf6 Graceful restart helper info */
struct ospf6_gr_helper ospf6_helper_cfg;
/* Count of NSSA areas */ /* Count of NSSA areas */
uint8_t anyNSSA; uint8_t anyNSSA;
struct thread *t_abr_task; /* ABR task timer. */ struct thread *t_abr_task; /* ABR task timer. */

View File

@ -45,6 +45,7 @@
#include "ospf6_flood.h" #include "ospf6_flood.h"
#include "ospf6d.h" #include "ospf6d.h"
#include "ospf6_bfd.h" #include "ospf6_bfd.h"
#include "ospf6_gr.h"
#include "lib/json.h" #include "lib/json.h"
#include "ospf6_nssa.h" #include "ospf6_nssa.h"
@ -96,6 +97,7 @@ static int config_write_ospf6_debug(struct vty *vty)
config_write_ospf6_debug_abr(vty); config_write_ospf6_debug_abr(vty);
config_write_ospf6_debug_flood(vty); config_write_ospf6_debug_flood(vty);
config_write_ospf6_debug_nssa(vty); config_write_ospf6_debug_nssa(vty);
config_write_ospf6_debug_gr_helper(vty);
return 0; return 0;
} }
@ -1402,6 +1404,7 @@ void ospf6_init(struct thread_master *master)
ospf6_intra_init(); ospf6_intra_init();
ospf6_asbr_init(); ospf6_asbr_init();
ospf6_abr_init(); ospf6_abr_init();
ospf6_gr_helper_config_init();
/* initialize hooks for modifying filter rules */ /* initialize hooks for modifying filter rules */
prefix_list_add_hook(ospf6_plist_add); prefix_list_add_hook(ospf6_plist_add);

View File

@ -108,6 +108,12 @@ extern struct thread_master *master;
vrf_name = VRF_DEFAULT_NAME; \ vrf_name = VRF_DEFAULT_NAME; \
} }
#define OSPF6_FALSE false
#define OSPF6_TRUE true
#define OSPF6_SUCCESS 1
#define OSPF6_FAILURE 0
#define OSPF6_INVALID -1
extern struct zebra_privs_t ospf6d_privs; extern struct zebra_privs_t ospf6d_privs;
/* Function Prototypes */ /* Function Prototypes */

View File

@ -12,6 +12,7 @@ vtysh_scan += \
ospf6d/ospf6_area.c \ ospf6d/ospf6_area.c \
ospf6d/ospf6_bfd.c \ ospf6d/ospf6_bfd.c \
ospf6d/ospf6_flood.c \ ospf6d/ospf6_flood.c \
ospf6d/ospf6_gr_helper.c \
ospf6d/ospf6_interface.c \ ospf6d/ospf6_interface.c \
ospf6d/ospf6_intra.c \ ospf6d/ospf6_intra.c \
ospf6d/ospf6_lsa.c \ ospf6d/ospf6_lsa.c \
@ -39,6 +40,7 @@ ospf6d_libospf6_a_SOURCES = \
ospf6d/ospf6_routemap_nb_config.c \ ospf6d/ospf6_routemap_nb_config.c \
ospf6d/ospf6_bfd.c \ ospf6d/ospf6_bfd.c \
ospf6d/ospf6_flood.c \ ospf6d/ospf6_flood.c \
ospf6d/ospf6_gr_helper.c \
ospf6d/ospf6_interface.c \ ospf6d/ospf6_interface.c \
ospf6d/ospf6_intra.c \ ospf6d/ospf6_intra.c \
ospf6d/ospf6_lsa.c \ ospf6d/ospf6_lsa.c \
@ -61,6 +63,7 @@ noinst_HEADERS += \
ospf6d/ospf6_asbr.h \ ospf6d/ospf6_asbr.h \
ospf6d/ospf6_bfd.h \ ospf6d/ospf6_bfd.h \
ospf6d/ospf6_flood.h \ ospf6d/ospf6_flood.h \
ospf6d/ospf6_gr.h \
ospf6d/ospf6_interface.h \ ospf6d/ospf6_interface.h \
ospf6d/ospf6_intra.h \ ospf6d/ospf6_intra.h \
ospf6d/ospf6_lsa.h \ ospf6d/ospf6_lsa.h \
@ -91,6 +94,7 @@ clippy_scan += \
ospf6d/ospf6_top.c \ ospf6d/ospf6_top.c \
ospf6d/ospf6_asbr.c \ ospf6d/ospf6_asbr.c \
ospf6d/ospf6_lsa.c \ ospf6d/ospf6_lsa.c \
ospf6d/ospf6_gr_helper.c \
# end # end
nodist_ospf6d_ospf6d_SOURCES = \ nodist_ospf6d_ospf6d_SOURCES = \