]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_lsa.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ospfd / ospf_lsa.c
index 92558e3c51ab51420016d019821e5120f0b424d0..49e342d72b563fd663ac88632637f40924da9ee3 100644 (file)
@@ -1,22 +1,7 @@
+// 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>
@@ -52,8 +37,6 @@
 #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,
@@ -87,6 +70,16 @@ uint32_t get_metric(uint8_t *metric)
        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)
 {
@@ -138,6 +131,16 @@ int get_age(struct ospf_lsa *lsa)
 {
        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;
 }
@@ -428,8 +431,10 @@ struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *oi)
 
        /* PtoP link must have only 1 neighbor. */
        if (ospf_nbr_count(oi, 0) > 1)
-               flog_warn(EC_OSPF_PTP_NEIGHBOR,
-                         "Point-to-Point link has more than 1 neighobrs.");
+               flog_warn(
+                       EC_OSPF_PTP_NEIGHBOR,
+                       "Point-to-Point link on interface %s has more than 1 neighbor.",
+                       oi->ifp->name);
 
        return nbr;
 }
@@ -1134,6 +1139,10 @@ static struct ospf_lsa *ospf_network_lsa_refresh(struct ospf_lsa *lsa)
                }
                return NULL;
        }
+
+       if (oi->state != ISM_DR)
+               return NULL;
+
        /* Delete LSA from neighbor retransmit-list. */
        ospf_ls_retransmit_delete_nbr_area(area, lsa);
 
@@ -1533,10 +1542,15 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf,
        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),
@@ -1551,6 +1565,9 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf,
        /* 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);
@@ -2643,13 +2660,6 @@ ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc)
 
                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;
@@ -2661,6 +2671,7 @@ static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf,
                                                 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
@@ -3409,82 +3420,6 @@ struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *area, uint32_t type,
        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)
 {
@@ -3723,6 +3658,49 @@ void ospf_flush_self_originated_lsas_now(struct ospf *ospf)
        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)
@@ -3916,9 +3894,8 @@ struct ospf_lsa *ospf_lsa_refresh(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) {
@@ -3988,8 +3965,7 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
        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;
@@ -4038,8 +4014,7 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
 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];
@@ -4061,6 +4036,7 @@ void ospf_lsa_refresh_walker(struct thread *t)
        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__);
@@ -4119,10 +4095,14 @@ void ospf_lsa_refresh_walker(struct thread *t)
        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);