From 59790f521a843d46b0640592c34bdc0731d7f8db Mon Sep 17 00:00:00 2001 From: rgirada Date: Mon, 28 Jun 2021 00:04:54 -0700 Subject: [PATCH] ospf6d: Init/De-init gr helper functionality Description: Graceful restart helper functionality initialisation and deinit apis. Signed-off-by: Rajesh Girada --- ospf6d/ospf6_gr_helper.c | 155 +++++++++++++++++++++++++++++++++++++++ ospf6d/ospf6_gr_helper.h | 137 ++++++++++++++++++++++++++++++++++ ospf6d/ospf6_top.c | 4 +- ospf6d/ospf6d.h | 6 ++ ospf6d/subdir.am | 4 + 5 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 ospf6d/ospf6_gr_helper.c create mode 100644 ospf6d/ospf6_gr_helper.h diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c new file mode 100644 index 0000000000..0108423cee --- /dev/null +++ b/ospf6d/ospf6_gr_helper.c @@ -0,0 +1,155 @@ +/* + * 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 + */ + +#include + +#include "log.h" +#include "vty.h" +#include "command.h" +#include "prefix.h" +#include "stream.h" +#include "zclient.h" +#include "memory.h" +#include "table.h" +#include "lib/bfd.h" +#include "lib_errors.h" +#include "jhash.h" + +#include "ospf6_proto.h" +#include "ospf6_lsa.h" +#include "ospf6_lsdb.h" +#include "ospf6_route.h" +#include "ospf6_message.h" + +#include "ospf6_top.h" +#include "ospf6_area.h" +#include "ospf6_interface.h" +#include "ospf6_neighbor.h" +#include "ospf6_intra.h" +#include "ospf6d.h" +#include "ospf6_gr_helper.h" +#include "lib/json.h" +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_gr_helper_clippy.c" +#endif + +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_GR_HELPER, "OSPF6 Graceful restart helper"); + +const char *ospf6_exit_reason_desc[] = { + "Unknown reason", "Helper inprogress", "Topology Change", + "Grace timer expiry", "Successful graceful restart", +}; + +const char *ospf6_restart_reason_desc[] = { + "Unknown restart", + "Software restart", + "Software reload/upgrade", + "Switch to redundant control processor", +}; + +const char *ospf6_rejected_reason_desc[] = { + "Unknown reason", + "Helper support disabled", + "Neighbour is not in FULL state", + "Supports only planned restart but received for unplanned", + "Topo change due to change in lsa rxmt list", + "LSA age is more than Grace interval", +}; + +static unsigned int ospf6_enable_rtr_hash_key(const void *data) +{ + const struct advRtr *rtr = data; + + return jhash_1word(rtr->advRtrAddr, 0); +} + +static bool ospf6_enable_rtr_hash_cmp(const void *d1, const void *d2) +{ + const struct advRtr *rtr1 = d1; + const struct advRtr *rtr2 = d2; + + return (rtr1->advRtrAddr == rtr2->advRtrAddr); +} + +static void *ospf6_enable_rtr_hash_alloc(void *p) +{ + struct advRtr *rid; + + rid = XCALLOC(MTYPE_OSPF6_GR_HELPER, sizeof(struct advRtr)); + rid->advRtrAddr = ((struct advRtr *)p)->advRtrAddr; + + return rid; +} + +static void ospf6_disable_rtr_hash_free(void *rtr) +{ + XFREE(MTYPE_OSPF6_GR_HELPER, rtr); +} + +static void ospf6_enable_rtr_hash_destroy(struct ospf6 *ospf6) +{ + if (ospf6->ospf6_helper_cfg.enable_rtr_list == NULL) + return; + + hash_clean(ospf6->ospf6_helper_cfg.enable_rtr_list, + ospf6_disable_rtr_hash_free); + hash_free(ospf6->ospf6_helper_cfg.enable_rtr_list); + ospf6->ospf6_helper_cfg.enable_rtr_list = NULL; +} + +/* + * Initilise GR helper config datastructer. + * + * ospf6 + * ospf6 pointer + * + * Returns: + * Nothing + */ +void ospf6_gr_helper_init(struct ospf6 *ospf6) +{ + ospf6->ospf6_helper_cfg.is_helper_supported = OSPF6_FALSE; + ospf6->ospf6_helper_cfg.strict_lsa_check = OSPF6_TRUE; + ospf6->ospf6_helper_cfg.only_planned_restart = OSPF6_FALSE; + ospf6->ospf6_helper_cfg.supported_grace_time = OSPF6_MAX_GRACE_INTERVAL; + ospf6->ospf6_helper_cfg.last_exit_reason = OSPF6_GR_HELPER_EXIT_NONE; + ospf6->ospf6_helper_cfg.active_restarter_cnt = 0; + + ospf6->ospf6_helper_cfg.enable_rtr_list = hash_create( + ospf6_enable_rtr_hash_key, ospf6_enable_rtr_hash_cmp, + "Ospf6 enable router hash"); +} + +/* + * De-Initilise GR helper config datastructer. + * + * ospf6 + * ospf6 pointer + * + * Returns: + * Nothing + */ +void ospf6_gr_helper_deinit(struct ospf6 *ospf6) +{ + ospf6_enable_rtr_hash_destroy(ospf6); +} diff --git a/ospf6d/ospf6_gr_helper.h b/ospf6d/ospf6_gr_helper.h new file mode 100644 index 0000000000..f5d49d4c06 --- /dev/null +++ b/ospf6d/ospf6_gr_helper.h @@ -0,0 +1,137 @@ +/* + * 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_HELPER_H +#define OSPF6_GR_HELPER_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 + +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 appendex-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.enableRtrList->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)->grHelperInfo.grHelper_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_init(struct ospf6 *ospf6); +extern void ospf6_gr_helper_deinit(struct ospf6 *ospf6); +#endif /* OSPF6_GR_HELPER_H */ diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6105e2c24b..e445e8703c 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -51,6 +51,7 @@ #include "ospf6_intra.h" #include "ospf6_spf.h" #include "ospf6d.h" +#include "ospf6_gr_helper.h" #include "lib/json.h" #include "ospf6_nssa.h" @@ -440,6 +441,7 @@ static struct ospf6 *ospf6_create(const char *name) o->oi_write_q = list_new(); + ospf6_gr_helper_init(o); QOBJ_REG(o, ospf6); /* Make ospf protocol socket. */ @@ -485,6 +487,7 @@ void ospf6_delete(struct ospf6 *o) QOBJ_UNREG(o); + ospf6_gr_helper_deinit(o); ospf6_flush_self_originated_lsas_now(o); ospf6_disable(o); ospf6_del(o); @@ -2233,7 +2236,6 @@ static int config_write_ospf6(struct vty *vty) ospf6_distance_config_write(vty, ospf6); ospf6_distribute_config_write(vty, ospf6); ospf6_asbr_summary_config_write(vty, ospf6); - vty_out(vty, "!\n"); } return 0; diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index 5afece9b0a..d5170be7cc 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -108,6 +108,12 @@ extern struct thread_master *master; 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; /* Function Prototypes */ diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index 78fb26b00e..608d3d1a29 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -12,6 +12,7 @@ vtysh_scan += \ ospf6d/ospf6_area.c \ ospf6d/ospf6_bfd.c \ ospf6d/ospf6_flood.c \ + ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_interface.c \ ospf6d/ospf6_intra.c \ ospf6d/ospf6_lsa.c \ @@ -39,6 +40,7 @@ ospf6d_libospf6_a_SOURCES = \ ospf6d/ospf6_routemap_nb_config.c \ ospf6d/ospf6_bfd.c \ ospf6d/ospf6_flood.c \ + ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_interface.c \ ospf6d/ospf6_intra.c \ ospf6d/ospf6_lsa.c \ @@ -61,6 +63,7 @@ noinst_HEADERS += \ ospf6d/ospf6_asbr.h \ ospf6d/ospf6_bfd.h \ ospf6d/ospf6_flood.h \ + ospf6d/ospf6_gr_helper.h \ ospf6d/ospf6_interface.h \ ospf6d/ospf6_intra.h \ ospf6d/ospf6_lsa.h \ @@ -91,6 +94,7 @@ clippy_scan += \ ospf6d/ospf6_top.c \ ospf6d/ospf6_asbr.c \ ospf6d/ospf6_lsa.c \ + ospf6d/ospf6_gr_helper.c \ # end nodist_ospf6d_ospf6d_SOURCES = \ -- 2.39.5