]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospf6d/ospf6_flood.c
Merge pull request #12989 from opensourcerouting/fix/memory_leaks_bgpd
[mirror_frr.git] / ospf6d / ospf6_flood.c
index 6e00bd766f777f3c1e96eebf657c3c262eb4b942..db1520ff20aab4408a354b0b5ecc6ce9df9120d5 100644 (file)
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2003 Yasuhiro Ohara
- *
- * 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>
@@ -151,24 +136,6 @@ void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa,
        ospf6_lsa_originate(oi->area->ospf6, lsa);
 }
 
-void ospf6_remove_id_from_external_id_table(struct ospf6 *ospf6,
-                                               uint32_t id)
-{
-       struct prefix prefix_id;
-       struct route_node *node;
-
-       /* remove binding in external_id_table */
-       prefix_id.family = AF_INET;
-       prefix_id.prefixlen = 32;
-       prefix_id.u.prefix4.s_addr = id;
-       node = route_node_lookup(ospf6->external_id_table, &prefix_id);
-       assert(node);
-       node->info = NULL;
-       route_unlock_node(node); /* to free the lookup lock */
-       route_unlock_node(node); /* to free the original lock */
-
-}
-
 void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
 {
        uint32_t id = lsa->header->id;
@@ -177,8 +144,6 @@ void ospf6_external_lsa_purge(struct ospf6 *ospf6, struct ospf6_lsa *lsa)
 
        ospf6_lsa_purge(lsa);
 
-       ospf6_remove_id_from_external_id_table(ospf6, id);
-
        /* Delete the corresponding NSSA LSA */
        for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, lnode, oa)) {
                lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), id,
@@ -484,11 +449,28 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
                                lsa->header->type, lsa->header->id,
                                lsa->header->adv_router, on->retrans_list);
                        if (!old) {
+                               struct ospf6_lsa *orig;
+                               struct ospf6_lsdb *lsdb;
+
                                if (is_debug)
                                        zlog_debug(
                                                "Increment %s from retrans_list of %s",
                                                lsa->name, on->name);
-                               ospf6_increment_retrans_count(lsa);
+
+                               /* Increment the retrans count on the original
+                                * copy of LSA if present, to maintain the
+                                * counter consistency.
+                                */
+
+                               lsdb = ospf6_get_scoped_lsdb(lsa);
+                               orig = ospf6_lsdb_lookup(
+                                       lsa->header->type, lsa->header->id,
+                                       lsa->header->adv_router, lsdb);
+                               if (orig)
+                                       ospf6_increment_retrans_count(orig);
+                               else
+                                       ospf6_increment_retrans_count(lsa);
+
                                ospf6_lsdb_add(ospf6_lsa_copy(lsa),
                                               on->retrans_list);
                                thread_add_timer(
@@ -881,6 +863,28 @@ static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa,
        return 0;
 }
 
+static bool ospf6_lsa_check_min_arrival(struct ospf6_lsa *lsa,
+                                       struct ospf6_neighbor *from)
+{
+       struct timeval now, res;
+       unsigned int time_delta_ms;
+
+       monotime(&now);
+       timersub(&now, &lsa->installed, &res);
+       time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
+
+       if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) {
+               if (IS_OSPF6_DEBUG_FLOODING ||
+                   IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type))
+                       zlog_debug(
+                               "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
+                               time_delta_ms,
+                               from->ospf6_if->area->ospf6->lsa_minarrival);
+               return true;
+       }
+       return false;
+}
+
 /* RFC2328 section 13 The Flooding Procedure */
 void ospf6_receive_lsa(struct ospf6_neighbor *from,
                       struct ospf6_lsa_header *lsa_header)
@@ -888,7 +892,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
        struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
        int ismore_recent;
        int is_debug = 0;
-       unsigned int time_delta_ms;
 
        ismore_recent = 1;
        assert(from);
@@ -996,19 +999,7 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
 
                /* (a) MinLSArrival check */
                if (old) {
-                       struct timeval now, res;
-                       monotime(&now);
-                       timersub(&now, &old->installed, &res);
-                       time_delta_ms =
-                               (res.tv_sec * 1000) + (int)(res.tv_usec / 1000);
-                       if (time_delta_ms
-                           < from->ospf6_if->area->ospf6->lsa_minarrival) {
-                               if (is_debug)
-                                       zlog_debug(
-                                               "LSA can't be updated within MinLSArrival, %dms < %dms, discard",
-                                               time_delta_ms,
-                                               from->ospf6_if->area->ospf6
-                                                       ->lsa_minarrival);
+                       if (ospf6_lsa_check_min_arrival(old, from)) {
                                ospf6_lsa_delete(new);
                                return; /* examin next lsa */
                        }
@@ -1114,9 +1105,12 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
                                         &new->refresh);
                }
 
+               /* GR: check for network topology change. */
                struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
                struct ospf6_area *area = from->ospf6_if->area;
-               if (ospf6->gr_info.restart_in_progress)
+               if (ospf6->gr_info.restart_in_progress &&
+                   (new->header->type == ntohs(OSPF6_LSTYPE_ROUTER) ||
+                    new->header->type == ntohs(OSPF6_LSTYPE_NETWORK)))
                        ospf6_gr_check_lsdb_consistency(ospf6, area);
 
                return;
@@ -1225,7 +1219,11 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
                                                __PRETTY_FUNCTION__, old->name);
                        }
 
-                       /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
+                       /* MinLSArrival check as per RFC 2328 13 (8) */
+                       if (ospf6_lsa_check_min_arrival(old, from)) {
+                               ospf6_lsa_delete(new);
+                               return; /* examin next lsa */
+                       }
 
                        ospf6_lsdb_add(ospf6_lsa_copy(old),
                                       from->lsupdate_list);