back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_lsdb.c (source / functions) Hit Total Coverage
Test: test_ospf6_vlink.py::VirtualLinkBasic Lines: 142 214 66.4 %
Date: 2023-02-16 02:06:43 Functions: 13 17 76.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 Yasuhiro Ohara
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "memory.h"
      24             : #include "log.h"
      25             : #include "command.h"
      26             : #include "prefix.h"
      27             : #include "table.h"
      28             : #include "vty.h"
      29             : 
      30             : #include "ospf6_proto.h"
      31             : #include "ospf6_lsa.h"
      32             : #include "ospf6_lsdb.h"
      33             : #include "ospf6_asbr.h"
      34             : #include "ospf6_route.h"
      35             : #include "ospf6d.h"
      36             : #include "bitfield.h"
      37             : 
      38          24 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database");
      39             : 
      40         214 : struct ospf6_lsdb *ospf6_lsdb_create(void *data)
      41             : {
      42         214 :         struct ospf6_lsdb *lsdb;
      43             : 
      44         214 :         lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
      45         214 :         memset(lsdb, 0, sizeof(struct ospf6_lsdb));
      46             : 
      47         214 :         lsdb->data = data;
      48         214 :         lsdb->table = route_table_init();
      49         214 :         return lsdb;
      50             : }
      51             : 
      52         214 : void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb)
      53             : {
      54         214 :         if (lsdb != NULL) {
      55         214 :                 ospf6_lsdb_remove_all(lsdb);
      56         214 :                 route_table_finish(lsdb->table);
      57         214 :                 XFREE(MTYPE_OSPF6_LSDB, lsdb);
      58             :         }
      59         214 : }
      60             : 
      61       19412 : static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value,
      62             :                                int len)
      63             : {
      64       19412 :         assert(key->prefixlen % 8 == 0);
      65             : 
      66       19412 :         memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len);
      67       19412 :         key->family = AF_INET6;
      68       19412 :         key->prefixlen += len * 8;
      69       19412 : }
      70             : 
      71             : #ifdef DEBUG
      72             : static void _lsdb_count_assert(struct ospf6_lsdb *lsdb)
      73             : {
      74             :         struct ospf6_lsa *debug, *debugnext;
      75             :         unsigned int num = 0;
      76             :         for (ALL_LSDB(lsdb, debug, debugnext))
      77             :                 num++;
      78             : 
      79             :         if (num == lsdb->count)
      80             :                 return;
      81             : 
      82             :         zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb,
      83             :                    lsdb->count, num);
      84             :         for (ALL_LSDB(lsdb, debug, debugnext))
      85             :                 zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb);
      86             :         zlog_debug("DUMP END");
      87             : 
      88             :         assert(num == lsdb->count);
      89             : }
      90             : #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
      91             : #else  /*DEBUG*/
      92             : #define ospf6_lsdb_count_assert(t) ((void) 0)
      93             : #endif /*DEBUG*/
      94             : 
      95        2112 : static inline void ospf6_lsdb_stats_update(struct ospf6_lsa *lsa,
      96             :                                            struct ospf6_lsdb *lsdb, int count)
      97             : {
      98        2112 :         uint16_t stat = ntohs(lsa->header->type) & OSPF6_LSTYPE_FCODE_MASK;
      99             : 
     100        2112 :         if (stat >= OSPF6_LSTYPE_SIZE)
     101           0 :                 stat = OSPF6_LSTYPE_UNKNOWN;
     102        2112 :         lsdb->stats[stat] += count;
     103             : }
     104             : 
     105        1209 : void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
     106             : {
     107        1209 :         struct prefix_ipv6 key;
     108        1209 :         struct route_node *current;
     109        1209 :         struct ospf6_lsa *old = NULL;
     110             : 
     111        1209 :         memset(&key, 0, sizeof(key));
     112        1209 :         ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
     113        1209 :         ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
     114             :                            sizeof(lsa->header->adv_router));
     115        1209 :         ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
     116             : 
     117        1209 :         current = route_node_get(lsdb->table, (struct prefix *)&key);
     118        1209 :         old = current->info;
     119        1209 :         current->info = lsa;
     120        1209 :         lsa->rn = current;
     121        1209 :         ospf6_lsa_lock(lsa);
     122             : 
     123        1209 :         if (!old) {
     124        1056 :                 lsdb->count++;
     125        1056 :                 ospf6_lsdb_stats_update(lsa, lsdb, 1);
     126             : 
     127        1056 :                 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
     128         142 :                         if (lsdb->hook_remove)
     129           3 :                                 (*lsdb->hook_remove)(lsa);
     130             :                 } else {
     131         914 :                         if (lsdb->hook_add)
     132         139 :                                 (*lsdb->hook_add)(lsa);
     133             :                 }
     134             :         } else {
     135         153 :                 lsa->retrans_count = old->retrans_count;
     136             : 
     137         153 :                 if (OSPF6_LSA_IS_CHANGED(old, lsa)) {
     138         124 :                         if (OSPF6_LSA_IS_MAXAGE(lsa)) {
     139          41 :                                 if (lsdb->hook_remove) {
     140          39 :                                         (*lsdb->hook_remove)(old);
     141          39 :                                         (*lsdb->hook_remove)(lsa);
     142             :                                 }
     143          83 :                         } else if (OSPF6_LSA_IS_MAXAGE(old)) {
     144           2 :                                 if (lsdb->hook_add)
     145           1 :                                         (*lsdb->hook_add)(lsa);
     146             :                         } else {
     147          81 :                                 if (lsdb->hook_remove)
     148          52 :                                         (*lsdb->hook_remove)(old);
     149          81 :                                 if (lsdb->hook_add)
     150          52 :                                         (*lsdb->hook_add)(lsa);
     151             :                         }
     152             :                 }
     153             :                 /* to free the lookup lock in node get*/
     154         153 :                 route_unlock_node(current);
     155         153 :                 ospf6_lsa_unlock(old);
     156             :         }
     157             : 
     158        1209 :         ospf6_lsdb_count_assert(lsdb);
     159        1209 : }
     160             : 
     161        1056 : void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
     162             : {
     163        1056 :         struct route_node *node;
     164        1056 :         struct prefix_ipv6 key;
     165             : 
     166        1056 :         memset(&key, 0, sizeof(key));
     167        1056 :         ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
     168        1056 :         ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
     169             :                            sizeof(lsa->header->adv_router));
     170        1056 :         ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
     171             : 
     172        1056 :         node = route_node_lookup(lsdb->table, (struct prefix *)&key);
     173        1056 :         assert(node && node->info == lsa);
     174             : 
     175        1056 :         node->info = NULL;
     176        1056 :         lsdb->count--;
     177        1056 :         ospf6_lsdb_stats_update(lsa, lsdb, -1);
     178             : 
     179        1056 :         if (lsdb->hook_remove)
     180         142 :                 (*lsdb->hook_remove)(lsa);
     181             : 
     182        1056 :         route_unlock_node(node); /* to free the lookup lock */
     183        1056 :         route_unlock_node(node); /* to free the original lock */
     184        1056 :         ospf6_lsa_unlock(lsa);
     185             : 
     186        1056 :         ospf6_lsdb_count_assert(lsdb);
     187        1056 : }
     188             : 
     189        3751 : struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
     190             :                                     uint32_t adv_router,
     191             :                                     struct ospf6_lsdb *lsdb)
     192             : {
     193        3751 :         struct route_node *node;
     194        3751 :         struct prefix_ipv6 key;
     195             : 
     196        3751 :         if (lsdb == NULL)
     197             :                 return NULL;
     198             : 
     199        3751 :         memset(&key, 0, sizeof(key));
     200        3751 :         ospf6_lsdb_set_key(&key, &type, sizeof(type));
     201        3751 :         ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
     202        3751 :         ospf6_lsdb_set_key(&key, &id, sizeof(id));
     203             : 
     204        3751 :         node = route_node_lookup(lsdb->table, (struct prefix *)&key);
     205        3751 :         if (node == NULL || node->info == NULL)
     206             :                 return NULL;
     207             : 
     208        1929 :         route_unlock_node(node);
     209        1929 :         return (struct ospf6_lsa *)node->info;
     210             : }
     211             : 
     212           0 : struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
     213             : {
     214           0 :         struct ospf6_route *match;
     215           0 :         struct ospf6_lsa *lsa;
     216           0 :         struct ospf6_external_info *info;
     217             : 
     218           0 :         match = ospf6_route_lookup(p, ospf6->external_table);
     219           0 :         if (match == NULL) {
     220           0 :                 if (IS_OSPF6_DEBUG_ASBR)
     221           0 :                         zlog_debug("No such route %pFX to withdraw", p);
     222             : 
     223           0 :                 return NULL;
     224             :         }
     225             : 
     226           0 :         info = match->route_option;
     227           0 :         assert(info);
     228             : 
     229           0 :         lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
     230             :                                 htonl(info->id), ospf6->router_id, ospf6->lsdb);
     231           0 :         return lsa;
     232             : }
     233             : 
     234           0 : struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
     235             :                                          uint32_t adv_router,
     236             :                                          struct ospf6_lsdb *lsdb)
     237             : {
     238           0 :         struct route_node *node;
     239           0 :         struct prefix_ipv6 key;
     240             : 
     241           0 :         if (lsdb == NULL)
     242             :                 return NULL;
     243             : 
     244           0 :         memset(&key, 0, sizeof(key));
     245           0 :         ospf6_lsdb_set_key(&key, &type, sizeof(type));
     246           0 :         ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
     247           0 :         ospf6_lsdb_set_key(&key, &id, sizeof(id));
     248             : 
     249           0 :         zlog_debug("lsdb_lookup_next: key: %pFX", &key);
     250             : 
     251           0 :         node = route_table_get_next(lsdb->table, &key);
     252             : 
     253             :         /* skip to real existing entry */
     254           0 :         while (node && node->info == NULL)
     255           0 :                 node = route_next(node);
     256             : 
     257           0 :         if (!node)
     258             :                 return NULL;
     259             : 
     260           0 :         route_unlock_node(node);
     261           0 :         if (!node->info)
     262             :                 return NULL;
     263             : 
     264             :         return (struct ospf6_lsa *)node->info;
     265             : }
     266             : 
     267        2245 : const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode,
     268             :                                          uint16_t type, uint32_t adv_router,
     269             :                                          struct ospf6_lsa **lsa)
     270             : {
     271        2245 :         struct route_node *node, *end;
     272             : 
     273        2245 :         *lsa = NULL;
     274             : 
     275        2245 :         if (argmode > 0) {
     276         745 :                 struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0};
     277             : 
     278         745 :                 ospf6_lsdb_set_key(&key, &type, sizeof(type));
     279         745 :                 if (argmode > 1)
     280         619 :                         ospf6_lsdb_set_key(&key, &adv_router,
     281             :                                            sizeof(adv_router));
     282             : 
     283         745 :                 node = route_table_get_next(lsdb->table, &key);
     284         745 :                 if (!node || !prefix_match((struct prefix *)&key, &node->p))
     285         181 :                         return NULL;
     286             : 
     287         564 :                 for (end = node; end && end->parent
     288         564 :                                  && end->parent->p.prefixlen >= key.prefixlen;
     289             :                      end = end->parent)
     290             :                         ;
     291             :         } else {
     292        1500 :                 node = route_top(lsdb->table);
     293        1500 :                 end = NULL;
     294             :         }
     295             : 
     296        3057 :         while (node && !node->info)
     297         993 :                 node = route_next_until(node, end);
     298             : 
     299        2064 :         if (!node)
     300             :                 return NULL;
     301        1381 :         if (!node->info) {
     302           0 :                 route_unlock_node(node);
     303           0 :                 return NULL;
     304             :         }
     305             : 
     306        1381 :         *lsa = node->info;
     307        1381 :         ospf6_lsa_lock(*lsa);
     308             : 
     309        1381 :         return end;
     310             : }
     311             : 
     312        3256 : struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
     313             :                                   struct ospf6_lsa *lsa)
     314             : {
     315        3256 :         struct route_node *node = lsa->rn;
     316             : 
     317        3256 :         ospf6_lsa_unlock(lsa);
     318             : 
     319        4154 :         do
     320        4154 :                 node = route_next_until(node, iterend);
     321        4154 :         while (node && !node->info);
     322             : 
     323        3256 :         if (node && node->info) {
     324        1875 :                 struct ospf6_lsa *next = node->info;
     325        1875 :                 ospf6_lsa_lock(next);
     326        1875 :                 return next;
     327             :         }
     328             : 
     329           0 :         if (node)
     330           0 :                 route_unlock_node(node);
     331             :         return NULL;
     332             : }
     333             : 
     334         554 : void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb)
     335             : {
     336         554 :         struct ospf6_lsa *lsa, *lsanext;
     337             : 
     338         554 :         if (lsdb == NULL)
     339           0 :                 return;
     340             : 
     341         849 :         for (ALL_LSDB(lsdb, lsa, lsanext))
     342         295 :                 ospf6_lsdb_remove(lsa, lsdb);
     343             : }
     344             : 
     345           0 : void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
     346             : {
     347           0 :         if (lsa != NULL) {
     348           0 :                 if (lsa->rn != NULL)
     349           0 :                         route_unlock_node(lsa->rn);
     350           0 :                 ospf6_lsa_unlock(lsa);
     351             :         }
     352           0 : }
     353             : 
     354           0 : int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
     355             : {
     356           0 :         int reschedule = 0;
     357           0 :         struct ospf6_lsa *lsa, *lsanext;
     358             : 
     359           0 :         for (ALL_LSDB(lsdb, lsa, lsanext)) {
     360           0 :                 if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
     361           0 :                         if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
     362           0 :                                 zlog_debug("Not MaxAge %s", lsa->name);
     363           0 :                         continue;
     364             :                 }
     365             : 
     366           0 :                 if (lsa->retrans_count != 0) {
     367           0 :                         if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
     368           0 :                                 zlog_debug("Remove MaxAge %s retrans_count %d",
     369             :                                            lsa->name, lsa->retrans_count);
     370             : 
     371           0 :                         reschedule = 1;
     372           0 :                         continue;
     373             :                 }
     374           0 :                 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
     375           0 :                         zlog_debug("Remove MaxAge %s", lsa->name);
     376             : 
     377           0 :                 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
     378           0 :                         UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
     379             :                         /*
     380             :                          * lsa->header->age = 0;
     381             :                          */
     382           0 :                         lsa->header->seqnum =
     383           0 :                                 htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
     384           0 :                         ospf6_lsa_checksum(lsa->header);
     385             : 
     386           0 :                         THREAD_OFF(lsa->refresh);
     387           0 :                         thread_execute(master, ospf6_lsa_refresh, lsa, 0);
     388             :                 } else {
     389           0 :                         zlog_debug("calling ospf6_lsdb_remove %s", lsa->name);
     390           0 :                         ospf6_lsdb_remove(lsa, lsdb);
     391             :                 }
     392             :         }
     393             : 
     394           0 :         return (reschedule);
     395             : }
     396             : 
     397           2 : uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router,
     398             :                          struct ospf6_lsdb *lsdb)
     399             : {
     400           2 :         struct ospf6_lsa *lsa;
     401           2 :         uint32_t id = 1, tmp_id;
     402             : 
     403             :         /* This routine is curently invoked only for Inter-Prefix LSAs for
     404             :          * non-summarized routes (no area/range).
     405             :          */
     406           2 :         for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) {
     407           0 :                 tmp_id = ntohl(lsa->header->id);
     408           0 :                 if (tmp_id < id)
     409           0 :                         continue;
     410             : 
     411           0 :                 if (tmp_id > id) {
     412           0 :                         ospf6_lsdb_lsa_unlock(lsa);
     413           0 :                         break;
     414             :                 }
     415           0 :                 id++;
     416             :         }
     417             : 
     418           2 :         return ((uint32_t)htonl(id));
     419             : }
     420             : 
     421             : /* Decide new LS sequence number to originate.
     422             :    note return value is network byte order */
     423         126 : uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router,
     424             :                              struct ospf6_lsdb *lsdb)
     425             : {
     426         126 :         struct ospf6_lsa *lsa;
     427         126 :         signed long seqnum = 0;
     428             : 
     429             :         /* if current database copy not found, return InitialSequenceNumber */
     430         126 :         lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb);
     431         126 :         if (lsa == NULL)
     432             :                 seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
     433             :         else
     434          85 :                 seqnum = (signed long)ntohl(lsa->header->seqnum) + 1;
     435             : 
     436         126 :         return ((uint32_t)htonl(seqnum));
     437             : }

Generated by: LCOV version v1.16-topotato