📄 ospf6_lsdb.c
字号:
/* * Copyright (C) 2002 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 GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <zebra.h>#include "memory.h"#include "log.h"#include "command.h"#include "if.h"#include "ospf6_dump.h"#include "ospf6_lsdb.h"#include "ospf6_interface.h"#include "ospf6_area.h"#include "ospf6_top.h"#define OSPF6_LSDB_MATCH_TYPE 0x01#define OSPF6_LSDB_MATCH_ID 0x02#define OSPF6_LSDB_MATCH_ADV_ROUTER 0x04#define OSPF6_LSDB_SHOW_DUMP 0x08#define OSPF6_LSDB_SHOW_DETAIL 0x10struct ospf6_lsdb_hook_t hooks[0x2000];struct ospf6_lsdb_hook_t *ospf6_lsdb_hook = hooks;struct ospf6_lsdb *ospf6_lsdb_create (){ struct ospf6_lsdb *lsdb; lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb)); if (lsdb == NULL) { zlog_warn ("Can't malloc lsdb"); return NULL; } memset (lsdb, 0, sizeof (struct ospf6_lsdb)); lsdb->table = route_table_init (); return lsdb;}voidospf6_lsdb_delete (struct ospf6_lsdb *lsdb){ ospf6_lsdb_remove_all (lsdb); route_table_finish (lsdb->table); XFREE (MTYPE_OSPF6_LSDB, lsdb);}static voidospf6_lsdb_set_key (struct prefix_ipv6 *key, int flag, u_int16_t type, u_int32_t id, u_int32_t adv_router){ int len = 0; memset (key, 0, sizeof (struct prefix_ipv6)); if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE)) { len += 2; if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER)) { len += 4; if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID)) len += 4; } } if (len > 0) memcpy ((char *)&key->prefix, &type, 2); if (len > 2) memcpy ((char *)&key->prefix + 2, &adv_router, 4); if (len > 6) memcpy ((char *)&key->prefix + 6, &id, 4); key->family = AF_INET6; key->prefixlen = len * 8;}voidospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb){ int flag; struct prefix_ipv6 key; struct route_node *rn; struct ospf6_lsa *old = NULL; flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | OSPF6_LSDB_MATCH_ADV_ROUTER; ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id, lsa->header->adv_router); rn = route_node_get (lsdb->table, (struct prefix *) &key); if (rn->info) old = rn->info; rn->info = lsa; ospf6_lsa_lock (lsa); if (old) ospf6_lsa_unlock (old); else lsdb->count++;}voidospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb){ int flag; struct prefix_ipv6 key; struct route_node *rn; struct ospf6_lsa *old; flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | OSPF6_LSDB_MATCH_ADV_ROUTER; ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id, lsa->header->adv_router); rn = route_node_lookup (lsdb->table, (struct prefix *) &key); if (! rn || ! rn->info) { zlog_warn ("LSDB: Can't remove: no such LSA: %s", lsa->str); return; } old = rn->info; if (old != lsa) { zlog_warn ("LSDB: Can't remove: different instance: %s (%p <-> %p) %s", lsa->str, lsa, old, old->str); return; } rn->info = NULL; ospf6_lsa_unlock (old); lsdb->count--;}static voidospf6_lsdb_lookup_node (struct ospf6_lsdb_node *node, u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb){ int flag; struct route_node *rn; memset (node, 0, sizeof (struct ospf6_lsdb_node)); flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | OSPF6_LSDB_MATCH_ADV_ROUTER; ospf6_lsdb_set_key (&node->key, flag, type, id, adv_router); rn = route_node_lookup (lsdb->table, (struct prefix *) &node->key); if (! rn || ! rn->info) return; node->node = rn; node->next = route_next (rn); node->lsa = rn->info; if (node->next != NULL) route_unlock_node (node->next);}struct ospf6_lsa *ospf6_lsdb_lookup_lsdb (u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb){ struct ospf6_lsdb_node node; ospf6_lsdb_lookup_node (&node, type, id, adv_router, lsdb); return node.lsa;}/* Iteration function */voidospf6_lsdb_head (struct ospf6_lsdb_node *node, struct ospf6_lsdb *lsdb){ struct route_node *rn; memset (node, 0, sizeof (struct ospf6_lsdb_node)); rn = route_top (lsdb->table); if (rn == NULL) return; while (rn && rn->info == NULL) rn = route_next (rn); if (rn && rn->info) { node->node = rn; node->next = route_next (rn); node->lsa = rn->info; if (node->next != NULL) route_unlock_node (node->next); }}voidospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type, struct ospf6_lsdb *lsdb){ int flag; struct route_node *rn; memset (node, 0, sizeof (struct ospf6_lsdb_node)); flag = OSPF6_LSDB_MATCH_TYPE; ospf6_lsdb_set_key (&node->key, flag, type, 0, 0); /* get the closest radix node */ rn = route_node_get (lsdb->table, (struct prefix *) &node->key); /* skip to the real existing lsdb entry */ while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && prefix_match ((struct prefix *) &node->key, &rn->p)) rn = route_next (rn); if (rn && rn->info) { node->node = rn; node->next = route_next (rn); node->lsa = rn->info; if (node->next != NULL) route_unlock_node (node->next); }}voidospf6_lsdb_type_router (struct ospf6_lsdb_node *node, u_int16_t type, u_int32_t adv_router, struct ospf6_lsdb *lsdb){ int flag; struct route_node *rn; memset (node, 0, sizeof (struct ospf6_lsdb_node)); flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ADV_ROUTER; ospf6_lsdb_set_key (&node->key, flag, type, 0, adv_router); /* get the closest radix node */ rn = route_node_get (lsdb->table, (struct prefix *) &node->key); /* skip to the real existing lsdb entry */ while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && prefix_match ((struct prefix *) &node->key, &rn->p)) rn = route_next (rn); if (rn && rn->info) { node->node = rn; node->next = route_next (rn); node->lsa = rn->info; if (node->next != NULL) route_unlock_node (node->next); }}voidospf6_lsdb_next (struct ospf6_lsdb_node *node){ struct route_node *rn; route_lock_node (node->node); rn = route_next (node->node); /* skip to the real existing lsdb entry */ while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && prefix_match ((struct prefix *) &node->key, &rn->p)) rn = route_next (rn); if (rn && rn->info && rn->p.prefixlen >= node->key.prefixlen && prefix_match ((struct prefix *) &node->key, &rn->p)) { node->node = rn; node->next = route_next (rn); node->lsa = rn->info; if (node->next != NULL) route_unlock_node (node->next); } else { node->node = NULL; node->next = NULL; node->lsa = NULL; }}struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, void *scope){ struct ospf6_interface *o6i; struct ospf6_area *o6a; listnode i, j; if (scope == (void *) ospf6) return ospf6_lsdb_lookup_lsdb (type, id, adv_router, ospf6->lsdb); for (i = listhead (ospf6->area_list); i; nextnode (i)) { o6a = getdata (i); if (scope == (void *) o6a) return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb); for (j = listhead (o6a->if_list); j; nextnode (j)) { o6i = getdata (j); if (scope == (void *) o6i) return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6i->lsdb); } } zlog_warn ("LSDB: Can't lookup: unknown scope, type %#hx", ntohs (type)); return NULL;}voidospf6_lsdb_install (struct ospf6_lsa *new){ struct ospf6_lsdb *lsdb; struct ospf6_lsa *old; int need_hook = 0; void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *); struct ospf6 *as = NULL; struct ospf6_area *area = NULL; struct ospf6_interface *linklocal = NULL; hook = NULL; switch (ntohs (new->header->type) & OSPF6_LSTYPE_SCOPE_MASK) { case OSPF6_LSA_SCOPE_LINKLOCAL: linklocal = (struct ospf6_interface *) new->scope; lsdb = linklocal->lsdb; break; case OSPF6_LSA_SCOPE_AREA: area = (struct ospf6_area *) new->scope; lsdb = area->lsdb; break; case OSPF6_LSA_SCOPE_AS: as = (struct ospf6 *) new->scope;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -