2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2002-12-13 21:15:29 +01:00
|
|
|
/*
|
2004-05-18 20:57:06 +02:00
|
|
|
* Copyright (C) 2003 Yasuhiro Ohara
|
2002-12-13 21:15:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "memory.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "command.h"
|
2004-05-18 20:57:06 +02:00
|
|
|
#include "prefix.h"
|
|
|
|
#include "table.h"
|
2004-08-04 22:02:13 +02:00
|
|
|
#include "vty.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
#include "ospf6_proto.h"
|
2023-03-01 21:31:56 +01:00
|
|
|
#include "ospf6_area.h"
|
2004-05-18 20:57:06 +02:00
|
|
|
#include "ospf6_lsa.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "ospf6_lsdb.h"
|
2023-03-01 21:31:56 +01:00
|
|
|
#include "ospf6_abr.h"
|
2021-05-28 11:33:03 +02:00
|
|
|
#include "ospf6_asbr.h"
|
2015-05-20 03:03:39 +02:00
|
|
|
#include "ospf6_route.h"
|
2004-08-04 22:02:13 +02:00
|
|
|
#include "ospf6d.h"
|
2015-05-20 03:03:39 +02:00
|
|
|
#include "bitfield.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2021-03-22 19:31:56 +01:00
|
|
|
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database");
|
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
struct ospf6_lsdb *ospf6_lsdb_create(void *data)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct ospf6_lsdb *lsdb;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
|
|
|
|
memset(lsdb, 0, sizeof(struct ospf6_lsdb));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-15 07:52:07 +02:00
|
|
|
lsdb->data = data;
|
2002-12-13 21:15:29 +01:00
|
|
|
lsdb->table = route_table_init();
|
|
|
|
return lsdb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb)
|
|
|
|
{
|
2013-08-24 09:55:14 +02:00
|
|
|
if (lsdb != NULL) {
|
|
|
|
ospf6_lsdb_remove_all(lsdb);
|
|
|
|
route_table_finish(lsdb->table);
|
|
|
|
XFREE(MTYPE_OSPF6_LSDB, lsdb);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value,
|
|
|
|
int len)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(key->prefixlen % 8 == 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len);
|
|
|
|
key->family = AF_INET6;
|
|
|
|
key->prefixlen += len * 8;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2013-08-24 09:55:36 +02:00
|
|
|
#ifdef DEBUG
|
2004-05-18 20:57:06 +02:00
|
|
|
static void _lsdb_count_assert(struct ospf6_lsdb *lsdb)
|
|
|
|
{
|
2020-11-18 17:06:10 +01:00
|
|
|
struct ospf6_lsa *debug, *debugnext;
|
2004-10-10 14:54:58 +02:00
|
|
|
unsigned int num = 0;
|
2020-11-18 17:06:10 +01:00
|
|
|
for (ALL_LSDB(lsdb, debug, debugnext))
|
2004-05-18 20:57:06 +02:00
|
|
|
num++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
if (num == lsdb->count)
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb,
|
2004-08-19 08:56:53 +02:00
|
|
|
lsdb->count, num);
|
2020-11-18 17:06:10 +01:00
|
|
|
for (ALL_LSDB(lsdb, debug, debugnext))
|
2017-08-01 11:34:15 +02:00
|
|
|
zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb);
|
2004-12-24 07:00:11 +01:00
|
|
|
zlog_debug("DUMP END");
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
assert(num == lsdb->count);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2004-05-18 20:57:06 +02:00
|
|
|
#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
|
2013-08-24 09:55:36 +02:00
|
|
|
#else /*DEBUG*/
|
2004-05-18 20:57:06 +02:00
|
|
|
#define ospf6_lsdb_count_assert(t) ((void) 0)
|
2013-08-24 09:55:36 +02:00
|
|
|
#endif /*DEBUG*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2022-01-12 12:30:59 +01:00
|
|
|
static inline void ospf6_lsdb_stats_update(struct ospf6_lsa *lsa,
|
|
|
|
struct ospf6_lsdb *lsdb, int count)
|
|
|
|
{
|
|
|
|
uint16_t stat = ntohs(lsa->header->type) & OSPF6_LSTYPE_FCODE_MASK;
|
|
|
|
|
|
|
|
if (stat >= OSPF6_LSTYPE_SIZE)
|
|
|
|
stat = OSPF6_LSTYPE_UNKNOWN;
|
|
|
|
lsdb->stats[stat] += count;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
|
|
|
{
|
|
|
|
struct prefix_ipv6 key;
|
2013-08-24 09:55:14 +02:00
|
|
|
struct route_node *current;
|
|
|
|
struct ospf6_lsa *old = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
|
|
|
|
sizeof(lsa->header->adv_router));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
current = route_node_get(lsdb->table, (struct prefix *)&key);
|
|
|
|
old = current->info;
|
|
|
|
current->info = lsa;
|
2013-08-24 09:55:14 +02:00
|
|
|
lsa->rn = current;
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf6_lsa_lock(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-08-24 09:55:14 +02:00
|
|
|
if (!old) {
|
|
|
|
lsdb->count++;
|
2022-01-12 12:30:59 +01:00
|
|
|
ospf6_lsdb_stats_update(lsa, lsdb, 1);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
|
|
if (lsdb->hook_remove)
|
|
|
|
(*lsdb->hook_remove)(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2013-08-24 09:55:14 +02:00
|
|
|
if (lsdb->hook_add)
|
|
|
|
(*lsdb->hook_add)(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2013-08-24 09:55:14 +02:00
|
|
|
} else {
|
2022-03-17 12:28:02 +01:00
|
|
|
lsa->retrans_count = old->retrans_count;
|
|
|
|
|
2013-08-24 09:55:14 +02:00
|
|
|
if (OSPF6_LSA_IS_CHANGED(old, lsa)) {
|
|
|
|
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
|
|
if (lsdb->hook_remove) {
|
|
|
|
(*lsdb->hook_remove)(old);
|
|
|
|
(*lsdb->hook_remove)(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2004-08-25 11:10:37 +02:00
|
|
|
} else if (OSPF6_LSA_IS_MAXAGE(old)) {
|
2013-08-24 09:55:14 +02:00
|
|
|
if (lsdb->hook_add)
|
|
|
|
(*lsdb->hook_add)(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2004-05-18 20:57:06 +02:00
|
|
|
if (lsdb->hook_remove)
|
|
|
|
(*lsdb->hook_remove)(old);
|
2013-08-24 09:55:14 +02:00
|
|
|
if (lsdb->hook_add)
|
|
|
|
(*lsdb->hook_add)(lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-13 20:39:22 +02:00
|
|
|
/* to free the lookup lock in node get*/
|
|
|
|
route_unlock_node(current);
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_unlock(&old);
|
2013-08-24 09:55:14 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsdb_count_assert(lsdb);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
struct route_node *node;
|
|
|
|
struct prefix_ipv6 key;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
|
|
|
|
sizeof(lsa->header->adv_router));
|
|
|
|
ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
node = route_node_lookup(lsdb->table, (struct prefix *)&key);
|
|
|
|
assert(node && node->info == lsa);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
node->info = NULL;
|
|
|
|
lsdb->count--;
|
2022-01-12 12:30:59 +01:00
|
|
|
ospf6_lsdb_stats_update(lsa, lsdb, -1);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
if (lsdb->hook_remove)
|
|
|
|
(*lsdb->hook_remove)(lsa);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2013-08-24 09:55:14 +02:00
|
|
|
route_unlock_node(node); /* to free the lookup lock */
|
|
|
|
route_unlock_node(node); /* to free the original lock */
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_unlock(&lsa);
|
2004-08-15 07:52:07 +02:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsdb_count_assert(lsdb);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
|
|
|
|
uint32_t adv_router,
|
2004-05-18 20:57:06 +02:00
|
|
|
struct ospf6_lsdb *lsdb)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2004-05-18 20:57:06 +02:00
|
|
|
struct route_node *node;
|
|
|
|
struct prefix_ipv6 key;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
if (lsdb == NULL)
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
ospf6_lsdb_set_key(&key, &type, sizeof(type));
|
|
|
|
ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
|
|
|
|
ospf6_lsdb_set_key(&key, &id, sizeof(id));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
node = route_node_lookup(lsdb->table, (struct prefix *)&key);
|
|
|
|
if (node == NULL || node->info == NULL)
|
|
|
|
return NULL;
|
2013-08-24 09:55:14 +02:00
|
|
|
|
|
|
|
route_unlock_node(node);
|
2004-05-18 20:57:06 +02:00
|
|
|
return (struct ospf6_lsa *)node->info;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2021-05-28 11:33:03 +02:00
|
|
|
struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
|
|
|
|
{
|
|
|
|
struct ospf6_route *match;
|
|
|
|
struct ospf6_lsa *lsa;
|
|
|
|
struct ospf6_external_info *info;
|
|
|
|
|
|
|
|
match = ospf6_route_lookup(p, ospf6->external_table);
|
|
|
|
if (match == NULL) {
|
|
|
|
if (IS_OSPF6_DEBUG_ASBR)
|
|
|
|
zlog_debug("No such route %pFX to withdraw", p);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-07-14 19:55:43 +02:00
|
|
|
info = match->route_option;
|
2021-05-28 11:33:03 +02:00
|
|
|
assert(info);
|
|
|
|
|
|
|
|
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
|
|
|
|
htonl(info->id), ospf6->router_id, ospf6->lsdb);
|
|
|
|
return lsa;
|
|
|
|
}
|
|
|
|
|
2023-03-01 21:31:56 +01:00
|
|
|
struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
|
|
|
|
struct ospf6_area *area,
|
|
|
|
struct prefix *p)
|
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa;
|
|
|
|
uint16_t type = htons(OSPF6_LSTYPE_INTER_PREFIX);
|
|
|
|
|
|
|
|
for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
|
|
|
|
struct ospf6_inter_prefix_lsa *prefix_lsa;
|
|
|
|
struct prefix prefix;
|
|
|
|
|
2024-05-21 01:47:20 +02:00
|
|
|
prefix_lsa = (struct ospf6_inter_prefix_lsa *)
|
|
|
|
ospf6_lsa_header_end(lsa->header);
|
2023-03-01 21:31:56 +01:00
|
|
|
prefix.family = AF_INET6;
|
|
|
|
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
|
|
|
|
ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
|
|
|
|
&prefix_lsa->prefix);
|
2023-06-30 13:02:27 +02:00
|
|
|
if (prefix_same(p, &prefix)) {
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_unlock(&lsa);
|
2023-03-01 21:31:56 +01:00
|
|
|
return lsa;
|
2023-06-30 13:02:27 +02:00
|
|
|
}
|
2023-03-01 21:31:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
|
|
|
|
uint32_t adv_router,
|
2004-11-25 21:54:46 +01:00
|
|
|
struct ospf6_lsdb *lsdb)
|
|
|
|
{
|
|
|
|
struct route_node *node;
|
|
|
|
struct prefix_ipv6 key;
|
|
|
|
|
|
|
|
if (lsdb == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
ospf6_lsdb_set_key(&key, &type, sizeof(type));
|
|
|
|
ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
|
|
|
|
ospf6_lsdb_set_key(&key, &id, sizeof(id));
|
|
|
|
|
2020-10-18 13:33:54 +02:00
|
|
|
zlog_debug("lsdb_lookup_next: key: %pFX", &key);
|
2004-11-25 21:54:46 +01:00
|
|
|
|
2017-07-07 18:26:09 +02:00
|
|
|
node = route_table_get_next(lsdb->table, &key);
|
2004-11-25 21:54:46 +01:00
|
|
|
|
|
|
|
/* skip to real existing entry */
|
|
|
|
while (node && node->info == NULL)
|
|
|
|
node = route_next(node);
|
|
|
|
|
|
|
|
if (!node)
|
|
|
|
return NULL;
|
|
|
|
|
2017-07-07 18:26:09 +02:00
|
|
|
route_unlock_node(node);
|
|
|
|
if (!node->info)
|
2004-11-25 21:54:46 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return (struct ospf6_lsa *)node->info;
|
|
|
|
}
|
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode,
|
|
|
|
uint16_t type, uint32_t adv_router,
|
|
|
|
struct ospf6_lsa **lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-06 15:02:31 +02:00
|
|
|
struct route_node *node, *end;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
*lsa = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
if (argmode > 0) {
|
|
|
|
struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0};
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
ospf6_lsdb_set_key(&key, &type, sizeof(type));
|
|
|
|
if (argmode > 1)
|
|
|
|
ospf6_lsdb_set_key(&key, &adv_router,
|
|
|
|
sizeof(adv_router));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
node = route_table_get_next(lsdb->table, &key);
|
|
|
|
if (!node || !prefix_match((struct prefix *)&key, &node->p))
|
|
|
|
return NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
for (end = node; end && end->parent
|
|
|
|
&& end->parent->p.prefixlen >= key.prefixlen;
|
|
|
|
end = end->parent)
|
|
|
|
;
|
|
|
|
} else {
|
|
|
|
node = route_top(lsdb->table);
|
|
|
|
end = NULL;
|
2013-08-24 09:55:14 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
while (node && !node->info)
|
|
|
|
node = route_next_until(node, end);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
if (!node)
|
2004-05-18 20:57:06 +02:00
|
|
|
return NULL;
|
2017-07-06 15:02:31 +02:00
|
|
|
if (!node->info) {
|
|
|
|
route_unlock_node(node);
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
*lsa = node->info;
|
|
|
|
ospf6_lsa_lock(*lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
return end;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
|
|
|
|
struct ospf6_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-06 15:02:31 +02:00
|
|
|
struct route_node *node = lsa->rn;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_unlock(&lsa);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
do
|
|
|
|
node = route_next_until(node, iterend);
|
|
|
|
while (node && !node->info);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
if (node && node->info) {
|
|
|
|
struct ospf6_lsa *next = node->info;
|
|
|
|
ospf6_lsa_lock(next);
|
|
|
|
return next;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-06 15:02:31 +02:00
|
|
|
if (node)
|
|
|
|
route_unlock_node(node);
|
|
|
|
return NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-05-18 20:57:06 +02:00
|
|
|
void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2020-08-17 14:25:12 +02:00
|
|
|
struct ospf6_lsa *lsa, *lsanext;
|
2013-08-24 09:55:14 +02:00
|
|
|
|
|
|
|
if (lsdb == NULL)
|
|
|
|
return;
|
|
|
|
|
2020-08-17 14:25:12 +02:00
|
|
|
for (ALL_LSDB(lsdb, lsa, lsanext))
|
2004-05-18 20:57:06 +02:00
|
|
|
ospf6_lsdb_remove(lsa, lsdb);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2013-08-24 09:55:14 +02:00
|
|
|
void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
|
|
|
|
{
|
|
|
|
if (lsa != NULL) {
|
|
|
|
if (lsa->rn != NULL)
|
|
|
|
route_unlock_node(lsa->rn);
|
2023-07-05 15:28:50 +02:00
|
|
|
ospf6_lsa_unlock(&lsa);
|
2013-08-24 09:55:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-24 09:54:17 +02:00
|
|
|
int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
|
|
|
|
{
|
|
|
|
int reschedule = 0;
|
2020-08-17 14:25:12 +02:00
|
|
|
struct ospf6_lsa *lsa, *lsanext;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-17 14:25:12 +02:00
|
|
|
for (ALL_LSDB(lsdb, lsa, lsanext)) {
|
2021-03-25 12:29:51 +01:00
|
|
|
if (!OSPF6_LSA_IS_MAXAGE(lsa)) {
|
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
|
|
|
|
zlog_debug("Not MaxAge %s", lsa->name);
|
2013-08-24 09:54:17 +02:00
|
|
|
continue;
|
2021-03-25 12:29:51 +01:00
|
|
|
}
|
|
|
|
|
2013-08-24 09:54:17 +02:00
|
|
|
if (lsa->retrans_count != 0) {
|
2021-03-25 12:29:51 +01:00
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
|
|
|
|
zlog_debug("Remove MaxAge %s retrans_count %d",
|
|
|
|
lsa->name, lsa->retrans_count);
|
|
|
|
|
2013-08-24 09:54:17 +02:00
|
|
|
reschedule = 1;
|
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2013-08-24 09:54:17 +02:00
|
|
|
if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
|
|
|
|
zlog_debug("Remove MaxAge %s", lsa->name);
|
ospf6d: Handle Premature Aging of LSAs
RFC 2328 (14.1) Premature aging of LSAs from
routing domain :
When ospf6d is going away (router going down),
send MAXAGEd self originated LSAs to all
neighbors in routing domain to trigger
Premature aging to remove from resepective LSDBs.
Neighbor Router Reboot:
Upon receiving Self-originate MAXAGEd LSA, simply
discard, Current copy could be non maxaged latest.
For neighbor advertised LSA's (current copy in LSDB)
is set to MAXAGE but received new LSA with Non-MAXAGE
(with current age), discard the current MAXAGE LSA,
Send latest copy of LSA to neighbors and update the
LSDB with new LSA.
When a neighbor transition to FULL, trigger AS-External
LSAs update from external LSDB to new neighbor.
Testing:
R1 ---- DUT --- R5
| \
R2 R3
|
R4
Area 1: R5 and DUT
Area 0: DUT, R1, R2, R3
Area 2: R2 R4
Add IPv6 static routes at R5
Redistribute kernel routes at R5,
Validate routes at R4, redistributed via backbone
to area 2.
Stop n start frr.service at R5 and validated
MAXAGE LSAs then recent age LSAs in Database at DUT-R4.
Validated external routes installed DUT to R4.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2018-01-26 23:53:43 +01:00
|
|
|
|
2013-08-24 10:00:44 +02:00
|
|
|
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
|
|
|
|
UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
|
2017-07-17 14:03:14 +02:00
|
|
|
/*
|
2013-08-24 10:00:44 +02:00
|
|
|
* lsa->header->age = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2013-08-24 10:00:44 +02:00
|
|
|
lsa->header->seqnum =
|
|
|
|
htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
|
|
|
|
ospf6_lsa_checksum(lsa->header);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(lsa->refresh);
|
2023-07-11 22:03:38 +02:00
|
|
|
event_execute(master, ospf6_lsa_refresh, lsa, 0, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2021-03-25 12:29:51 +01:00
|
|
|
zlog_debug("calling ospf6_lsdb_remove %s", lsa->name);
|
2013-08-24 10:00:44 +02:00
|
|
|
ospf6_lsdb_remove(lsa, lsdb);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2013-08-24 09:54:17 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2013-08-24 09:54:17 +02:00
|
|
|
return (reschedule);
|
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router,
|
|
|
|
struct ospf6_lsdb *lsdb)
|
2004-08-04 22:02:13 +02:00
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t id = 1, tmp_id;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:03:39 +02:00
|
|
|
/* This routine is curently invoked only for Inter-Prefix LSAs for
|
|
|
|
* non-summarized routes (no area/range).
|
|
|
|
*/
|
2017-07-07 17:23:30 +02:00
|
|
|
for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) {
|
2015-05-20 03:03:39 +02:00
|
|
|
tmp_id = ntohl(lsa->header->id);
|
|
|
|
if (tmp_id < id)
|
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 03:03:39 +02:00
|
|
|
if (tmp_id > id) {
|
2013-08-24 09:55:14 +02:00
|
|
|
ospf6_lsdb_lsa_unlock(lsa);
|
2004-08-15 07:52:07 +02:00
|
|
|
break;
|
2009-12-01 19:12:38 +01:00
|
|
|
}
|
2004-08-04 22:02:13 +02:00
|
|
|
id++;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
return ((uint32_t)htonl(id));
|
2004-08-04 22:02:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Decide new LS sequence number to originate.
|
|
|
|
note return value is network byte order */
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router,
|
|
|
|
struct ospf6_lsdb *lsdb)
|
2004-08-04 22:02:13 +02:00
|
|
|
{
|
|
|
|
struct ospf6_lsa *lsa;
|
|
|
|
signed long seqnum = 0;
|
|
|
|
|
|
|
|
/* if current database copy not found, return InitialSequenceNumber */
|
|
|
|
lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb);
|
|
|
|
if (lsa == NULL)
|
2013-10-23 02:42:18 +02:00
|
|
|
seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
|
2004-08-04 22:02:13 +02:00
|
|
|
else
|
|
|
|
seqnum = (signed long)ntohl(lsa->header->seqnum) + 1;
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
return ((uint32_t)htonl(seqnum));
|
2004-08-04 22:02:13 +02:00
|
|
|
}
|