+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* OSPF Link State Advertisement
* Copyright (C) 1999, 2000 Toshiaki Takada
- *
- * 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 <zebra.h>
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_errors.h"
-#include "ospfd/ospf_te.h"
-#include "ospfd/ospf_orr.h"
static struct ospf_lsa *ospf_handle_summarylsa_lsId_chg(struct ospf *ospf,
struct prefix_ipv4 *p,
return m;
}
+/** @brief The Function checks self generated DoNotAge.
+ * @param lsa pointer.
+ * @return true or false.
+ */
+bool ospf_check_dna_lsa(const struct ospf_lsa *lsa)
+{
+ return ((IS_LSA_SELF(lsa) && CHECK_FLAG(lsa->data->ls_age, DO_NOT_AGE))
+ ? true
+ : false);
+}
struct timeval int2tv(int a)
{
{
struct timeval rel;
+ /* As per rfc4136, the self-originated LSAs in their
+ * own database keep aging, however rfc doesn't tell
+ * till how long the LSA should be aged, as of now
+ * we are capping it for OSPF_LSA_MAXAGE.
+ */
+
+ /* If LSA is marked as donotage */
+ if (CHECK_FLAG(lsa->data->ls_age, DO_NOT_AGE) && !IS_LSA_SELF(lsa))
+ return ntohs(lsa->data->ls_age);
+
monotime_since(&lsa->tv_recv, &rel);
return ntohs(lsa->data->ls_age) + rel.tv_sec;
}
}
return NULL;
}
+
+ if (oi->state != ISM_DR)
+ return NULL;
+
/* Delete LSA from neighbor retransmit-list. */
ospf_ls_retransmit_delete_nbr_area(area, lsa);
struct ospf_lsa *new;
struct summary_lsa *sl;
struct prefix p;
+ bool ind_lsa = false;
/* Sanity check. */
assert(lsa->data);
+ if (lsa->area->fr_info.indication_lsa_self &&
+ (lsa->area->fr_info.indication_lsa_self == lsa))
+ ind_lsa = true;
+
sl = (struct summary_lsa *)lsa->data;
p.prefixlen = ip_masklen(sl->mask);
new = ospf_summary_asbr_lsa_new(lsa->area, &p, GET_METRIC(sl->metric),
/* Flood LSA through area. */
ospf_flood_through_area(new->area, NULL, new);
+ if (ind_lsa)
+ new->area->fr_info.indication_lsa_self = new;
+
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug("LSA[Type%d:%pI4]: summary-ASBR-LSA refresh",
new->data->type, &new->data->id);
ospf_refresher_register_lsa(ospf, new);
}
- /* For BGP ORR SPF should be calculated from specified root(s) */
- else if (ospf->orr_spf_request) {
- ospf_lsa_unlock(&area->router_lsa_rcvd);
- area->router_lsa_rcvd = ospf_lsa_lock(new);
- ospf_orr_root_update_rcvd_lsa(area->router_lsa_rcvd);
- }
-
if (rt_recalc)
ospf_spf_calculate_schedule(ospf, SPF_FLAG_ROUTER_LSA_INSTALL);
return new;
struct ospf_lsa *new,
int rt_recalc)
{
+
/* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
The entire routing table must be recalculated, starting with
the shortest path calculations for each area (not just the
return NULL;
}
-struct ospf_lsa *ospf_lsa_lookup_by_adv_rid(struct ospf_area *area,
- uint32_t type, struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
-
- switch (type) {
- case OSPF_ROUTER_LSA:
- for (rn = route_top(ROUTER_LSDB(area)); rn;
- rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- if (IPV4_ADDR_SAME(&lsa->data->adv_router,
- &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- break;
- case OSPF_NETWORK_LSA:
- case OSPF_SUMMARY_LSA:
- case OSPF_ASBR_SUMMARY_LSA:
- case OSPF_AS_EXTERNAL_LSA:
- case OSPF_AS_NSSA_LSA:
- case OSPF_OPAQUE_LINK_LSA:
- case OSPF_OPAQUE_AREA_LSA:
- case OSPF_OPAQUE_AS_LSA:
- /* Currently not used. */
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
-struct ospf_lsa *ospf_lsa_lookup_by_mpls_te_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
- struct lsa_header *lsah = NULL;
- uint32_t lsid;
- uint8_t opaque_type;
- struct tlv_header *tlvh = NULL;
- struct te_tlv_router_addr *router_addr = NULL;
-
- if (type != OSPF_OPAQUE_AREA_LSA)
- return NULL;
-
- for (rn = route_top(OPAQUE_AREA_LSDB(area)); rn; rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- lsah = lsa->data;
- lsid = ntohl(lsah->id.s_addr);
- opaque_type = GET_OPAQUE_TYPE(lsid);
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- continue;
-
- tlvh = TLV_HDR_TOP(lsah);
- if (!tlvh ||
- (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- continue;
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IPV4_ADDR_SAME(&router_addr->value, &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- return NULL;
-}
-
struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area,
struct lsa_header *lsah)
{
return;
}
+/** @brief Function to refresh all the self originated
+ * LSAs for area, when FR state change happens.
+ * @param area pointer.
+ * @return Void.
+ */
+void ospf_refresh_area_self_lsas(struct ospf_area *area)
+{
+ struct listnode *node2;
+ struct listnode *nnode2;
+ struct ospf_interface *oi;
+ struct route_node *rn;
+ struct ospf_lsa *lsa;
+
+ if (!area)
+ return;
+
+ if (area->router_lsa_self)
+ ospf_lsa_refresh(area->ospf, area->router_lsa_self);
+
+ for (ALL_LIST_ELEMENTS(area->oiflist, node2, nnode2, oi))
+ if (oi->network_lsa_self)
+ ospf_lsa_refresh(oi->ospf, oi->network_lsa_self);
+
+ LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+ LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+ LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+ LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+ LSDB_LOOP (EXTERNAL_LSDB(area->ospf), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+ LSDB_LOOP (OPAQUE_AS_LSDB(area->ospf), rn, lsa)
+ if (IS_LSA_SELF(lsa))
+ ospf_lsa_refresh(area->ospf, lsa);
+}
+
/* If there is self-originated LSA, then return 1, otherwise return 0. */
/* An interface-independent version of ospf_lsa_is_self_originated */
int ospf_lsa_is_self_originated(struct ospf *ospf, struct ospf_lsa *lsa)
struct as_external_lsa *al;
struct prefix_ipv4 p;
- if (!CHECK_FLAG(lsa->flags, OSPF_LSA_SELF) && !IS_LSA_SELF(lsa) &&
- !IS_LSA_ORR(lsa))
- return NULL;
+ assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF));
+ assert(IS_LSA_SELF(lsa));
assert(lsa->lock > 0);
switch (lsa->data->type) {
uint16_t index, current_index;
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) && !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list < 0) {
int delay;
void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
{
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) || !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list >= 0) {
struct list *refresh_list =
ospf->lsa_refresh_queue.qs[lsa->refresh_list];
struct ospf_lsa *lsa;
int i;
struct list *lsa_to_refresh = list_new();
+ bool dna_lsa;
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
zlog_debug("LSA[Refresh]: %s: start", __func__);
ospf->lsa_refresher_started = monotime(NULL);
for (ALL_LIST_ELEMENTS(lsa_to_refresh, node, nnode, lsa)) {
- ospf_lsa_refresh(ospf, lsa);
- assert(lsa->lock > 0);
- ospf_lsa_unlock(
- &lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/
+ dna_lsa = ospf_check_dna_lsa(lsa);
+ if (!dna_lsa) { /* refresh only non-DNA LSAs */
+ ospf_lsa_refresh(ospf, lsa);
+ assert(lsa->lock > 0);
+ ospf_lsa_unlock(&lsa); /* lsa_refresh_queue & temp for
+ * lsa_to_refresh.
+ */
+ }
}
list_delete(&lsa_to_refresh);